हम सभी अपने फोन में कैमरे का इस्तेमाल करते हैं और हम इसका इस्तेमाल एल-ओ-टी करते हैं। यहां तक कि कुछ एप्लिकेशन भी हैं जिन्होंने कैमरे को एक फीचर के रूप में एकीकृत किया है।
एक तरफ, कैमरे के साथ बातचीत करने का एक मानक तरीका है। दूसरी ओर, कैमरे के साथ आपकी बातचीत को अनुकूलित करने का एक तरीका है। यह भेद करना महत्वपूर्ण है। और यहीं से कैमरा2 आता है।
Camera2 क्या है?
जबकि यह एपीआई स्तर 21 के बाद से उपलब्ध है, कैमरा 2 एपीआई को आर्किटेक्चर डेवलपर्स के अधिक जटिल टुकड़ों में से एक होना चाहिए।
इस एपीआई और इसके पूर्ववर्ती को रखा गया था ताकि डेवलपर्स अपने अनुप्रयोगों के अंदर कैमरे के साथ बातचीत करने की शक्ति का उपयोग कर सकें।
माइक्रोफ़ोन या डिवाइस के वॉल्यूम के साथ इंटरैक्ट करने के तरीके के समान, कैमरा 2 एपीआई आपको डिवाइस के कैमरे से इंटरैक्ट करने के लिए टूल देता है।
सामान्य तौर पर, यदि आप कैमरा 2 एपीआई का उपयोग करना चाहते हैं, तो यह शायद सिर्फ एक तस्वीर लेने या वीडियो रिकॉर्ड करने से ज्यादा होगा। ऐसा इसलिए है क्योंकि एपीआई आपको विभिन्न वर्गों को उजागर करके कैमरे पर गहराई से नियंत्रण करने देता है, जिन्हें प्रति विशिष्ट डिवाइस को कॉन्फ़िगर करने की आवश्यकता होगी।
यहां तक कि अगर आपने पहले कैमरे के साथ काम किया है, तो यह पूर्व कैमरा एपीआई से इतना बड़ा बदलाव है, कि आप वह सब भूल सकते हैं जो आप जानते हैं।
वहाँ बहुत सारे संसाधन हैं जो यह दिखाने की कोशिश करते हैं कि इस एपीआई का सीधे उपयोग कैसे करें, लेकिन उनमें से कुछ पुराने हो सकते हैं और कुछ पूरी तस्वीर पेश नहीं करते हैं।
इसलिए, गुम हुए अंशों को अपने आप भरने की कोशिश करने के बजाय, यह लेख (उम्मीद है) कैमरा2 एपीआई के साथ बातचीत करने के लिए आपकी वन स्टॉप शॉप होगी।
Camera2 उपयोग के मामले
इससे पहले कि हम किसी भी चीज़ में गोता लगाएँ, यह समझना महत्वपूर्ण है कि यदि आप केवल चित्र लेने या वीडियो रिकॉर्ड करने के लिए कैमरे का उपयोग करना चाहते हैं, तो आपको Camera2 API से परेशान होने की आवश्यकता नहीं है।
कैमरा 2 एपीआई का उपयोग करने का प्राथमिक कारण यह है कि यदि आपके एप्लिकेशन को कैमरे या इसकी कार्यक्षमता के साथ कुछ कस्टम इंटरैक्शन की आवश्यकता है।
यदि आप बाद वाले के बजाय पहले वाले को करने में रुचि रखते हैं, तो मेरा सुझाव है कि आप Google से निम्नलिखित दस्तावेज़ देखें:
- फ़ोटो लें
- वीडियो कैप्चर करें
वहां आपको अपने कैमरे से शानदार तस्वीरें और वीडियो कैप्चर करने के लिए आवश्यक सभी आवश्यक कदम मिलेंगे। लेकिन इस लेख में, मुख्य फोकस इस बात पर होगा कि Camera2 का उपयोग कैसे करें।
अब, कुछ चीजें हैं जिन्हें हमें अपनी मेनिफेस्ट फ़ाइल में जोड़ने की आवश्यकता है:
कैमरा अनुमतियां:
<uses-permission android:name="android.permission.CAMERA" />
कैमरा सुविधा:
<uses-feature android:name="android.hardware.camera" />
आपको कैमरे की अनुमति दी गई है या नहीं, इसकी जांच करनी होगी, लेकिन चूंकि इस विषय को व्यापक रूप से कवर किया गया है, इसलिए हम इस लेख में उस पर विचार नहीं करेंगे।
Camera2 API घटकों को कैसे सेट करें
कैमरा 2 एपीआई कई नए इंटरफेस और कक्षाएं पेश करता है। आइए उनमें से प्रत्येक को तोड़ दें ताकि हम बेहतर ढंग से समझ सकें कि उनका उपयोग कैसे करना है।
सबसे पहले, हम TextureView से शुरुआत करेंगे।
Camera2 TextureView Component
TextureView एक UI घटक है जिसका उपयोग आप सामग्री स्ट्रीम (वीडियो सोचें) प्रदर्शित करने के लिए करते हैं। हमें कैमरे से फ़ीड प्रदर्शित करने के लिए TextureView का उपयोग करने की आवश्यकता है, चाहे वह पूर्वावलोकन हो या चित्र/वीडियो लेने से पहले।
TextureView के संबंध में उपयोग करने के लिए महत्वपूर्ण दो गुण हैं:
- सरफेसटेक्स्चर फ़ील्ड
- सरफेसटेक्स्चर लिस्टनर इंटरफ़ेस
पहली वह जगह है जहां सामग्री प्रदर्शित होगी, और दूसरी में चार कॉलबैक हैं:
- सतह पर उपलब्ध है
- SurfaceTextureSizeबदला हुआ
- SurfaceTextureUpdated
- SurfaceTextureDestroyed
private val surfaceTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) {
}
override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) {
}
override fun onSurfaceTextureDestroyed(texture: SurfaceTexture) {
}
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {
}
}
कैमरे का उपयोग करते समय पहला कॉलबैक महत्वपूर्ण है। ऐसा इसलिए है क्योंकि हम चाहते हैं कि जब SurfaceTexture उपलब्ध हो तो हमें सूचित किया जाए ताकि हम उस पर फ़ीड प्रदर्शित करना शुरू कर सकें।
ध्यान रखें कि केवल एक बार TextureView एक विंडो से संलग्न होने के बाद ही यह उपलब्ध हो पाता है।
पिछले एपीआई के बाद से कैमरे के साथ इंटरैक्ट करना बदल गया है। अब, हमारे पास कैमरामैनेजर है। यह एक सिस्टम सेवा है जो हमें CameraDevice ऑब्जेक्ट के साथ इंटरैक्ट करने की अनुमति देती है।
आप जिन तरीकों पर पूरा ध्यान देना चाहते हैं वे हैं:
- ओपनकैमरा
- getCameraविशेषताएं
- GetCameraIdList
जब हम जानते हैं कि TextureView उपलब्ध है और तैयार है, तो हमें कैमरे से कनेक्शन खोलने के लिए openCamera को कॉल करने की आवश्यकता है। इस विधि में तीन तर्क होते हैं:
- कैमरा आईडी - स्ट्रिंग
- CameraDevice.StateCallback
- एक हैंडलर
CameraId तर्क दर्शाता है कि हम किस कैमरे से जुड़ना चाहते हैं। आपके फ़ोन में मुख्य रूप से दो कैमरे होते हैं, आगे और पीछे। प्रत्येक की अपनी विशिष्ट आईडी होती है। आमतौर पर, यह या तो शून्य या एक होता है।
हम कैमरा आईडी कैसे प्राप्त करते हैं? हम कैमरामैनेजर की getCamerasIdList विधि का उपयोग करते हैं। यह डिवाइस से पहचाने गए सभी कैमरा आईडी के स्ट्रिंग प्रकार की एक सरणी लौटाएगा।
val cameraManager: CameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
val cameraIds: Array<String> = cameraManager.cameraIdList
var cameraId: String = ""
for (id in cameraIds) {
val cameraCharacteristics = cameraManager.getCameraCharacteristics(id)
//If we want to choose the rear facing camera instead of the front facing one
if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT)
continue
}
val previewSize = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!.getOutputSizes(ImageFormat.JPEG).maxByOrNull { it.height * it.width }!!
val imageReader = ImageReader.newInstance(previewSize.width, previewSize.height, ImageFormat.JPEG, 1)
imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler)
cameraId = id
}
जब हम इसे खोलने का प्रयास करते हैं तो अगला तर्क कैमरा स्थिति में कॉलबैक होता है। यदि आप इसके बारे में सोचते हैं, तो इस क्रिया के केवल कई परिणाम हो सकते हैं:
- कैमरा सफलतापूर्वक खुलने का प्रबंधन करता है
- कैमरा डिस्कनेक्ट हो जाता है
- कुछ त्रुटि होती है
और यही आपको CameraDevice.StateCallback के अंदर मिलेगा:
private val cameraStateCallback = object : CameraDevice.StateCallback() {
override fun onOpened(camera: CameraDevice) {
}
override fun onDisconnected(cameraDevice: CameraDevice) {
}
override fun onError(cameraDevice: CameraDevice, error: Int) {
val errorMsg = when(error) {
ERROR_CAMERA_DEVICE -> "Fatal (device)"
ERROR_CAMERA_DISABLED -> "Device policy"
ERROR_CAMERA_IN_USE -> "Camera in use"
ERROR_CAMERA_SERVICE -> "Fatal (service)"
ERROR_MAX_CAMERAS_IN_USE -> "Maximum cameras in use"
else -> "Unknown"
}
Log.e(TAG, "Error when trying to connect camera $errorMsg")
}
}
तीसरा तर्क इस बात से संबंधित है कि यह कार्य कहाँ होगा। चूंकि हम मुख्य धागे पर कब्जा नहीं करना चाहते हैं, इसलिए इस काम को पृष्ठभूमि में करना बेहतर है।
इसलिए हमें इसके लिए एक हैंडलर पास करने की आवश्यकता है। यह बुद्धिमानी होगी कि इस हैंडलर इंस्टेंस को हमारी पसंद के धागे के साथ तुरंत चालू किया जाए ताकि हम इसे काम सौंप सकें।
private lateinit var backgroundHandlerThread: HandlerThread
private lateinit var backgroundHandler: Handler
private fun startBackgroundThread() {
backgroundHandlerThread = HandlerThread("CameraVideoThread")
backgroundHandlerThread.start()
backgroundHandler = Handler(
backgroundHandlerThread.looper)
}
private fun stopBackgroundThread() {
backgroundHandlerThread.quitSafely()
backgroundHandlerThread.join()
}
हमने जो कुछ भी किया है, उसके साथ अब हम openCamera को कॉल कर सकते हैं:
cameraManager.openCamera(cameraId, cameraStateCallback,backgroundHandler)
फिर ऑनओपन . में कॉलबैक, हम इस तर्क से निपटना शुरू कर सकते हैं कि कैसे TextureView के माध्यम से उपयोगकर्ता को कैमरा फ़ीड प्रस्तुत किया जाए।
फ़ीड का पूर्वावलोकन कैसे दिखाएं
फ़ीड दिखाने के लिए हमारे पास हमारा कैमरा (कैमराडिवाइस) और हमारा TextureView है। लेकिन हमें उन्हें एक-दूसरे से कनेक्ट करने की आवश्यकता है ताकि हम फ़ीड का पूर्वावलोकन दिखा सकें।
ऐसा करने के लिए, हम TextureView की SurfaceTexture प्रॉपर्टी का उपयोग करेंगे और हम CaptureRequest का निर्माण करेंगे।
val surfaceTexture : SurfaceTexture? = textureView.surfaceTexture // 1
val cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId) //2
val previewSize = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!
.getOutputSizes(ImageFormat.JPEG).maxByOrNull { it.height * it.width }!!
surfaceTexture?.setDefaultBufferSize(previewSize.width, previewSize.height) //3
val previewSurface: Surface = Surface(surfaceTexture)
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) //4
captureRequestBuilder.addTarget(previewSurface) //5
cameraDevice.createCaptureSession(listOf(previewSurface, imageReader.surface), captureStateCallback, null) //6
उपरोक्त कोड में, सबसे पहले हम अपने TextureView से SurfaceTexture प्राप्त करते हैं। फिर हम सभी आउटपुट आकारों की सूची प्राप्त करने के लिए कैमरा कैरेक्टरिस्टिक्स ऑब्जेक्ट का उपयोग करते हैं। वांछित आकार प्राप्त करने के लिए, हम इसे सतह बनावट के लिए सेट करते हैं।
इसके बाद, हम एक कैप्चर रिक्वेस्ट बनाते हैं जहां हम TEMPLATE_PREVIEW . में पास होते हैं . हम अपनी इनपुट सतह को कैप्चर रिक्वेस्ट में जोड़ते हैं।
अंत में, हम अपने इनपुट और आउटपुट सतहों के साथ एक कैप्चर सत्र शुरू करते हैं, कैप्चरस्टेट कॉलबैक, और हैंडलर के लिए शून्य में पास करते हैं
तो यह कैप्चरस्टेट कॉलबैक क्या है? यदि आपको इस लेख की शुरुआत से आरेख याद है, तो यह CameraCaptureSession का हिस्सा है जिसे हम शुरू कर रहे हैं। यह ऑब्जेक्ट निम्नलिखित कॉलबैक के साथ कैप्चर रिक्वेस्ट की प्रगति को ट्रैक करता है:
- कॉन्फ़िगर पर
- कॉन्फ़िगर करने में विफल
private val captureStateCallback = object : CameraCaptureSession.StateCallback() {
override fun onConfigureFailed(session: CameraCaptureSession) {
}
override fun onConfigured(session: CameraCaptureSession) {
}
}
जब cameraCaptureSession सफलतापूर्वक कॉन्फ़िगर किया गया है, हम लगातार पूर्वावलोकन दिखाने की अनुमति देने के लिए सत्र के लिए एक दोहराव अनुरोध सेट करते हैं।
ऐसा करने के लिए, हम कॉलबैक में प्राप्त सत्र ऑब्जेक्ट का उपयोग करते हैं:
session.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler)
आप हमारे कैप्चर रिक्वेस्टबिल्डर ऑब्जेक्ट को पहचान लेंगे जिसे हमने पहले इस विधि के लिए पहले तर्क के रूप में बनाया था। हम बिल्ड विधि को लागू करते हैं, इसलिए पास किया गया अंतिम पैरामीटर CaptureRequest है।
दूसरा तर्क एक CameraCaptureSession.captureCallback श्रोता है, लेकिन चूंकि हम कैप्चर की गई छवियों के साथ कुछ भी नहीं करना चाहते हैं (क्योंकि यह एक पूर्वावलोकन है), हम शून्य में गुजरते हैं।
तीसरा तर्क एक हैंडलर है, और यहां हम अपने स्वयं के बैकग्राउंडहैंडलर का उपयोग करते हैं। यही कारण है कि हम पिछले खंड में शून्य में पास हुए, क्योंकि दोहराव अनुरोध बैकग्राउंड थ्रेड पर चलेगा।
तस्वीर कैसे लें
कैमरे का लाइव प्रीव्यू शानदार है, लेकिन अधिकांश उपयोगकर्ता शायद इसके साथ कुछ करना चाहेंगे। कुछ तर्क जो हम तस्वीर लेने के लिए लिखेंगे, वही होंगे जो हमने पिछले भाग में किए थे।
- हम एक कैप्चर रिक्वेस्ट बनाएंगे
- हम ली गई तस्वीर को इकट्ठा करने के लिए एक इमेजरीडर और उसके श्रोता का उपयोग करेंगे
- अपने कैमरेकैप्चरसेशन का उपयोग करके, हम कैप्चर विधि लागू करेंगे
val orientations : SparseIntArray = SparseIntArray(4).apply {
append(Surface.ROTATION_0, 0)
append(Surface.ROTATION_90, 90)
append(Surface.ROTATION_180, 180)
append(Surface.ROTATION_270, 270)
}
val captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
captureRequestBuilder.addTarget(imageReader.surface)
val rotation = windowManager.defaultDisplay.rotation
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, orientations.get(rotation))
cameraCaptureSession.capture(captureRequestBuilder.build(), captureCallback, null)
लेकिन यह ImageReader क्या है? खैर, एक ImageReader छवि डेटा तक पहुंच प्रदान करता है जो सतह पर प्रदान किया जाता है। हमारे मामले में, यह TextureView की सतह है।
यदि आप पिछले अनुभाग के कोड स्निपेट को देखते हैं, तो आप देखेंगे कि हमने वहां पहले से ही एक ImageReader परिभाषित किया है।
val cameraManager: CameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
val cameraIds: Array<String> = cameraManager.cameraIdList
var cameraId: String = ""
for (id in cameraIds) {
val cameraCharacteristics = cameraManager.getCameraCharacteristics(id)
//If we want to choose the rear facing camera instead of the front facing one
if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT)
continue
}
val previewSize = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!.getOutputSizes(ImageFormat.JPEG).maxByOrNull { it.height * it.width }!!
val imageReader = ImageReader.newInstance(previewSize.width, previewSize.height, ImageFormat.JPEG, 1)
imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler)
cameraId = id
}
जैसा कि आप ऊपर देख सकते हैं, हम एक इमेजरीडर को चौड़ाई और ऊंचाई से गुजरते हुए, छवि प्रारूप में हम चाहते हैं कि हमारी छवि हो और छवियों की संख्या जो इसे कैप्चर कर सके।
ImageReader वर्ग की एक संपत्ति एक श्रोता है जिसे onImageAvailableListener कहा जाता है। एक बार फ़ोटो लेने के बाद यह श्रोता चालू हो जाएगा (चूंकि हम अपने कैप्चर अनुरोध के लिए आउटपुट स्रोत के रूप में इसकी सतह पर चले गए हैं)।
val onImageAvailableListener = object: ImageReader.OnImageAvailableListener{
override fun onImageAvailable(reader: ImageReader) {
val image: Image = reader.acquireLatestImage()
}
}
⚠️ छवि को संसाधित करने के बाद उसे बंद करना सुनिश्चित करें अन्यथा आप दूसरी फ़ोटो नहीं ले पाएंगे.
वीडियो कैसे रिकॉर्ड करें
वीडियो रिकॉर्ड करने के लिए, हमें MediaRecorder नामक एक नई वस्तु के साथ बातचीत करने की आवश्यकता है। मीडिया रिकॉर्डर ऑब्जेक्ट ऑडियो और वीडियो रिकॉर्ड करने का प्रभारी है और हम इसका उपयोग करेंगे।
इससे पहले कि हम कुछ भी करें, हमें मीडिया रिकॉर्डर को सेटअप करना होगा। निपटने के लिए विभिन्न विन्यास हैं और उन्हें सही क्रम में होना चाहिए अन्यथा अपवादों को फेंक दिया जाएगा .
नीचे कॉन्फ़िगरेशन के चयन का एक उदाहरण है जो हमें वीडियो (ऑडियो के बिना) कैप्चर करने की अनुमति देगा।
fun setupMediaRecorder(width: Int, height: Int) {
val mediaRecorder: MediaRecorder = MediaRecorder()
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
mediaRecorder.setVideoSize(videoSize.width, videoSize.height)
mediaRecorder.setVideoFrameRate(30)
mediaRecorder.setOutputFile(PATH_TO_FILE)
mediaRecorder.setVideoEncodingBitRate(10_000_000)
mediaRecorder.prepare()
}
setOutputFile . पर ध्यान दें विधि के रूप में यह फ़ाइल के लिए एक पथ की अपेक्षा करता है जो हमारे वीडियो को संग्रहीत करेगा। इन सभी कॉन्फ़िगरेशन को सेट करने के अंत में हमें तैयार कॉल करने की आवश्यकता है।
ध्यान दें कि MediaRecorder में एक प्रारंभ विधि भी है और हमें इसे कॉल करने से पहले तैयार करना होगा।
हमारे MediaRecoder को स्थापित करने के बाद, हमें एक कैप्चर अनुरोध और एक कैप्चर सत्र बनाने की आवश्यकता है।
fun startRecording() {
val surfaceTexture : SurfaceTexture? = textureView.surfaceTexture
surfaceTexture?.setDefaultBufferSize(previewSize.width, previewSize.height)
val previewSurface: Surface = Surface(surfaceTexture)
val recordingSurface = mediaRecorder.surface
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)
captureRequestBuilder.addTarget(previewSurface)
captureRequestBuilder.addTarget(recordingSurface)
cameraDevice.createCaptureSession(listOf(previewSurface, recordingSurface), captureStateVideoCallback, backgroundHandler)
}
पूर्वावलोकन सेट करने या एक तस्वीर लेने के समान, हमें अपने इनपुट और आउटपुट सतहों को परिभाषित करना होगा।
यहां हम टेक्सचर व्यू के सरफेस टेक्सचर से सरफेस ऑब्जेक्ट बना रहे हैं और मीडिया रिकॉर्डर से भी सरफेस ले रहे हैं। हम TEMPLATE_RECORD . से गुजर रहे हैं कैप्चर अनुरोध बनाते समय मान।
हमारा कैप्चरस्टेटवीडियोकॉलबैक उसी प्रकार का है जिसका उपयोग हमने स्टिल फोटो के लिए किया था, लेकिन ऑनकॉन्फ़िगर किए गए कॉलबैक के अंदर हम मीडिया रिकॉर्डर की स्टार्ट विधि कहते हैं।
val captureStateVideoCallback = object : CameraCaptureSession.StateCallback() {
override fun onConfigureFailed(session: CameraCaptureSession) {
}
override fun onConfigured(session: CameraCaptureSession) {
session.setRepeatingRequest(captureRequestBuilder.build(), null, backgroundHandler)
mediaRecorder.start()
}
}
अब हम वीडियो रिकॉर्ड कर रहे हैं, लेकिन हम रिकॉर्डिंग कैसे रोकें? उसके लिए, हम MediaRecorder ऑब्जेक्ट पर स्टॉप और रीसेट विधियों का उपयोग करेंगे:
mediaRecorder.stop()
mediaRecorder.reset()
निष्कर्ष
यह प्रक्रिया करने के लिए बहुत कुछ था। तो अगर आपने इसे यहां बनाया है, बधाई हो! इसके चारों ओर कोई रास्ता नहीं है - केवल अपने हाथों को कोड से गंदा करने से आप यह समझने लगेंगे कि सब कुछ एक साथ कैसे जुड़ता है।
नीचे दिए गए इस लेख में दिखाए गए सभी कोड को देखने के लिए आपको प्रोत्साहित किया जाता है:
मध्यम लेख/Camrea2API मास्टर में TomerPacificGitHubध्यान रखें कि जब कैमरा 2 एपीआई की बात आती है तो यह हिमशैल का सिरा है। आप और भी बहुत कुछ कर सकते हैं, जैसे धीमी गति का वीडियो कैप्चर करना, आगे और पीछे के कैमरों के बीच स्विच करना, फ़ोकस को नियंत्रित करना, और भी बहुत कुछ।