CameraX वीडियो कैप्चर करने का आर्किटेक्चर

कैप्चर करने वाला सिस्टम, आम तौर पर वीडियो और ऑडियो स्ट्रीम रिकॉर्ड करता है. इसके बाद, उन्हें कंप्रेस करता है. इसके बाद, दोनों स्ट्रीम को मक्स करता है. इसके बाद, नतीजे वाली स्ट्रीम को डिस्क पर लिखता है.

वीडियो और ऑडियो कैप्चर करने वाले सिस्टम का कॉन्सेप्ट डायग्राम
पहली इमेज. वीडियो और ऑडियो कैप्चर करने वाले सिस्टम का कॉन्सेप्ट डायग्राम.

CameraX में, वीडियो कैप्चर करने के लिए VideoCapture यूज़ केस का इस्तेमाल किया जाता है:

कॉन्सेप्ट वाला डायग्राम, जिसमें यह दिखाया गया है कि CameraX, वीडियो कैप्चर करने के इस्तेमाल के उदाहरण को कैसे हैंडल करता है
दूसरी इमेज. कॉन्सेप्ट वाला डायग्राम, जिसमें दिखाया गया है कि CameraX, VideoCapture इस्तेमाल के उदाहरण को कैसे हैंडल करता है.

आकृति 2 में दिखाए गए CameraX वीडियो कैप्चर में, कुछ हाई-लेवल आर्किटेक्चरल कॉम्पोनेंट शामिल हैं:

  • SurfaceProvider पर क्लिक करें.
  • AudioSource के लिए ऑडियो सोर्स.
  • वीडियो/ऑडियो को एन्कोड और कंप्रेस करने के लिए दो एन्कोडर.
  • दो स्ट्रीम को मक्स करने के लिए मीडिया मक्सर.
  • नतीजे को सेव करने के लिए, फ़ाइल सेवर.

VideoCapture API, कैप्चर करने वाले इंजन को ऐब्स्ट्रैक्ट करता है. साथ ही, यह ऐप्लिकेशन को ज़्यादा आसान और सीधे तौर पर काम करने वाला एपीआई उपलब्ध कराता है.

VideoCapture API के बारे में खास जानकारी

VideoCapture, CameraX का एक ऐसा इस्तेमाल है जो अकेले या अन्य इस्तेमाल के साथ मिलकर अच्छी तरह से काम करता है. सुविधाओं के साथ काम करने वाले खास कॉम्बिनेशन, कैमरे के हार्डवेयर की क्षमताओं पर निर्भर करते हैं. हालांकि, Preview और VideoCapture का कॉम्बिनेशन, सभी डिवाइसों पर इस्तेमाल किया जा सकता है.

VideoCapture API में ये ऑब्जेक्ट शामिल होते हैं, जो ऐप्लिकेशन के साथ कम्यूनिकेट करते हैं:

  • VideoCapture, इस्तेमाल के उदाहरण की सबसे ऊपरी क्लास है. VideoCapture, LifecycleOwner से CameraSelector और अन्य CameraX UseCases के साथ बाइंड होता है. इन कॉन्सेप्ट और इस्तेमाल के बारे में ज़्यादा जानने के लिए, CameraX आर्किटेक्चर देखें.
  • Recorder, VideoOutput का एक ऐसा वर्शन है जो VideoCapture के साथ काम करता है. Recorder का इस्तेमाल, वीडियो और ऑडियो कैप्चर करने के लिए किया जाता है. कोई ऐप्लिकेशन, Recorder से रिकॉर्डिंग बनाता है.
  • PendingRecording रिकॉर्डिंग को कॉन्फ़िगर करता है. इसमें ऑडियो चालू करने और इवेंट लिसनर सेट करने जैसे विकल्प मिलते हैं. PendingRecording बनाने के लिए, आपको Recorder का इस्तेमाल करना होगा. PendingRecording कुछ भी रिकॉर्ड नहीं करता है.
  • Recording असली रिकॉर्डिंग करता है. Recording बनाने के लिए, आपको PendingRecording का इस्तेमाल करना होगा.

तीसरी इमेज में, इन ऑब्जेक्ट के बीच के संबंध दिखाए गए हैं:

वीडियो कैप्चर करने के इस्तेमाल के उदाहरण में होने वाले इंटरैक्शन दिखाने वाला डायग्राम
तीसरी इमेज. इस डायग्राम में, VideoCapture के इस्तेमाल के उदाहरण में होने वाले इंटरैक्शन दिखाए गए हैं.

लेजेंड:

  1. QualitySelector की मदद से Recorder बनाएं.
  2. OutputOptions में से किसी एक का इस्तेमाल करके, Recorder को कॉन्फ़िगर करें.
  3. अगर ज़रूरी हो, तो withAudioEnabled() की मदद से ऑडियो चालू करें.
  4. रिकॉर्डिंग शुरू करने के लिए, VideoRecordEvent लिसनर के साथ start() को कॉल करें.
  5. रिकॉर्डिंग को कंट्रोल करने के लिए, Recording पर pause()/resume()/stop() का इस्तेमाल करें.
  6. अपने इवेंट लिसनर में VideoRecordEvents का जवाब दें.

एपीआई की पूरी सूची, सोर्स कोड में मौजूद current.txt फ़ाइल में है.

VideoCapture API का इस्तेमाल करना

अपने ऐप्लिकेशन में CameraX VideoCapture यूज़ केस को इंटिग्रेट करने के लिए, यह तरीका अपनाएं:

  1. VideoCapture को बाइंड करें.
  2. रिकॉर्डिंग की तैयारी करना और उसे कॉन्फ़िगर करना.
  3. रनटाइम रिकॉर्डिंग शुरू और कंट्रोल करें.

यहां दिए गए सेक्शन में, एंड-टू-एंड रिकॉर्डिंग सेशन पाने के लिए, हर चरण में की जा सकने वाली कार्रवाइयों के बारे में बताया गया है.

VideoCapture को बाइंड करें

VideoCapture के इस्तेमाल के उदाहरण को बाइंड करने के लिए, यह तरीका अपनाएं:

  1. Recorder ऑब्जेक्ट बनाएं.
  2. VideoCapture ऑब्जेक्ट बनाएं.
  3. किसी Lifecycle से बाइंड करें.

CameraX VideoCapture API, बिल्डर डिज़ाइन पैटर्न का पालन करता है. ऐप्लिकेशन, Recorder बनाने के लिए Recorder.Builder का इस्तेमाल करते हैं. Recorder ऑब्जेक्ट के ज़रिए, Recorder के लिए वीडियो रिज़ॉल्यूशन भी कॉन्फ़िगर किया जा सकता है.QualitySelector

CameraX, वीडियो रिज़ॉल्यूशन के लिए पहले से तय किए गए Qualities Recorder के साथ काम करता है:

  • Quality.UHD 4K अल्ट्रा एचडी वीडियो साइज़ (2160 पिक्सल) के लिए
  • Quality.FHD फ़ुल एचडी वीडियो साइज़ (1080 पिक्सल) के लिए
  • Quality.HD एचडी वीडियो के साइज़ (720 पिक्सल) के लिए
  • Quality.SD एसडी वीडियो के साइज़ (480 पिक्सल) के लिए

ध्यान दें कि ऐप्लिकेशन से अनुमति मिलने पर, CameraX अन्य रिज़ॉल्यूशन भी चुन सकता है.

हर चुने गए वीडियो का साइज़, कैमरे और एनकोडर की क्षमताओं पर निर्भर करता है. ज़्यादा जानकारी के लिए, CamcorderProfile का दस्तावेज़ देखें.

ऐप्लिकेशन, QualitySelector बनाकर रिज़ॉल्यूशन को कॉन्फ़िगर कर सकते हैं. इनमें से किसी एक तरीके का इस्तेमाल करके, QualitySelector बनाया जा सकता है:

  • fromOrderedList() का इस्तेमाल करके, कुछ पसंदीदा रिज़ॉल्यूशन दें. साथ ही, अगर कोई भी पसंदीदा रिज़ॉल्यूशन काम नहीं करता है, तो फ़ॉलबैक रणनीति शामिल करें.

    CameraX, चुने गए कैमरे की क्षमता के आधार पर, सबसे अच्छा फ़ॉलबैक मैच तय कर सकता है. ज़्यादा जानकारी के लिए, QualitySelector के FallbackStrategy specification पर जाएं. उदाहरण के लिए, यहाँ दिए गए कोड में रिकॉर्डिंग के लिए सबसे ज़्यादा रिज़ॉल्यूशन का अनुरोध किया गया है. अगर अनुरोध किए गए रिज़ॉल्यूशन में से किसी को भी इस्तेमाल नहीं किया जा सकता, तो CameraX को Quality.SD रिज़ॉल्यूशन के सबसे करीब वाला रिज़ॉल्यूशन चुनने की अनुमति दी गई है:

    val qualitySelector = QualitySelector.fromOrderedList(
             listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD),
             FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))
    
  • सबसे पहले कैमरे की क्षमताओं के बारे में क्वेरी करें. इसके बाद, QualitySelector::from() का इस्तेमाल करके, काम करने वाले रिज़ॉल्यूशन में से कोई एक चुनें:

    val cameraInfo = cameraProvider.availableCameraInfos.filter {
        Camera2CameraInfo
        .from(it)
        .getCameraCharacteristic(CameraCharacteristics.LENS\_FACING) == CameraMetadata.LENS_FACING_BACK
    }
    
    val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo[0])
    val filteredQualities = arrayListOf (Quality.UHD, Quality.FHD, Quality.HD, Quality.SD)
                           .filter { supportedQualities.contains(it) }
    
    // Use a simple ListView with the id of simple_quality_list_view
    viewBinding.simpleQualityListView.apply {
        adapter = ArrayAdapter(context,
                               android.R.layout.simple_list_item_1,
                               filteredQualities.map { it.qualityToString() })
    
        // Set up the user interaction to manually show or hide the system UI.
        setOnItemClickListener { _, _, position, _ ->
            // Inside View.OnClickListener,
            // convert Quality.* constant to QualitySelector
            val qualitySelector = QualitySelector.from(filteredQualities[position])
    
            // Create a new Recorder/VideoCapture for the new quality
            // and bind to lifecycle
            val recorder = Recorder.Builder()
                .setQualitySelector(qualitySelector).build()
    
             // ...
        }
    }
    
    // A helper function to translate Quality to a string
    fun Quality.qualityToString() : String {
        return when (this) {
            Quality.UHD -> "UHD"
            Quality.FHD -> "FHD"
            Quality.HD -> "HD"
            Quality.SD -> "SD"
            else -> throw IllegalArgumentException()
        }
    }
    
    

    ध्यान दें कि QualitySelector.getSupportedQualities() से मिली सुविधा, VideoCapture इस्तेमाल के उदाहरण या VideoCapture और Preview इस्तेमाल के उदाहरणों के कॉम्बिनेशन के लिए काम करेगी. ImageCapture या ImageAnalysis इस्तेमाल के उदाहरण के साथ बाइंड करने पर, CameraX अब भी बाइंड नहीं हो सकता. ऐसा तब होता है, जब अनुरोध किए गए कैमरे पर ज़रूरी कॉम्बिनेशन काम नहीं करता.

QualitySelector मिलने के बाद, ऐप्लिकेशन एक VideoCapture ऑब्जेक्ट बना सकता है और बाइंडिंग कर सकता है. ध्यान दें कि यह बाइंडिंग, इस्तेमाल के अन्य उदाहरणों की तरह ही है:

val recorder = Recorder.Builder()
    .setExecutor(cameraExecutor).setQualitySelector(qualitySelector)
    .build()
val videoCapture = VideoCapture.withOutput(recorder)

try {
    // Bind use cases to camera
    cameraProvider.bindToLifecycle(
            this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture)
} catch(exc: Exception) {
    Log.e(TAG, "Use case binding failed", exc)
}

ध्यान दें कि bindToLifecycle(), Camera ऑब्जेक्ट दिखाता है. ज़ूम और एक्सपोज़र जैसे कैमरा आउटपुट को कंट्रोल करने के बारे में ज़्यादा जानने के लिए, यह गाइड देखें.

Recorder, सिस्टम के लिए सबसे सही फ़ॉर्मैट चुनता है. सबसे आम वीडियो कोडेक H.264 AVC है. इसका कंटेनर फ़ॉर्मैट MPEG-4 है.

रिकॉर्डिंग कॉन्फ़िगर करना और रिकॉर्डिंग बनाना

Recorder से, ऐप्लिकेशन रिकॉर्डिंग ऑब्जेक्ट बना सकता है, ताकि वीडियो और ऑडियो कैप्चर किया जा सके. ऐप्लिकेशन, इन तरीकों से रिकॉर्डिंग करते हैं:

  1. prepareRecording() की मदद से OutputOptions को कॉन्फ़िगर करें.
  2. (ज़रूरी नहीं) ऑडियो रिकॉर्डिंग की सुविधा चालू करें.
  3. start() का इस्तेमाल करके, VideoRecordEvent लिसनर रजिस्टर करें और वीडियो कैप्चर करना शुरू करें.

start() फ़ंक्शन को कॉल करने पर, Recorder एक Recording ऑब्जेक्ट दिखाता है. आपका ऐप्लिकेशन, इस Recording ऑब्जेक्ट का इस्तेमाल करके, कैप्चर करने की प्रोसेस को पूरा कर सकता है. इसके अलावा, वह अन्य कार्रवाइयाँ भी कर सकता है. जैसे, कैप्चर करने की प्रोसेस को रोकना या फिर से शुरू करना.

एक Recorder ऑब्जेक्ट में एक बार में सिर्फ़ एक Recording ऑब्जेक्ट इस्तेमाल किया जा सकता है. पिछले Recording ऑब्जेक्ट पर Recording.stop() या Recording.close() को कॉल करने के बाद, नई रिकॉर्डिंग शुरू की जा सकती है.

आइए, इन चरणों के बारे में ज़्यादा जानें. सबसे पहले, ऐप्लिकेशन Recorder.prepareRecording() की मदद से रिकॉर्डर के लिए OutputOptions को कॉन्फ़िगर करता है. Recorder में, इस तरह के OutputOptions इस्तेमाल किए जा सकते हैं:

  • FileDescriptor में कैप्चर करने के लिए FileDescriptorOutputOptions.
  • File में कैप्चर करने के लिए FileOutputOptions.
  • MediaStore में कैप्चर करने के लिए MediaStoreOutputOptions.

OutputOptions टाइप की सभी फ़ाइलों के लिए, setFileSizeLimit() का इस्तेमाल करके फ़ाइल के साइज़ की सीमा सेट की जा सकती है. अन्य विकल्प, आउटपुट टाइप के हिसाब से अलग-अलग होते हैं. जैसे, FileDescriptorOutputOptions के लिए ParcelFileDescriptor.

prepareRecording(), PendingRecording ऑब्जेक्ट दिखाता है. यह एक इंटरमीडिएट ऑब्जेक्ट है, जिसका इस्तेमाल Recording ऑब्जेक्ट बनाने के लिए किया जाता है. PendingRecording एक ट्रांज़िएंट क्लास है. ज़्यादातर मामलों में यह दिखनी नहीं चाहिए. साथ ही, ऐप्लिकेशन इसे कभी-कभार ही कैश मेमोरी में सेव करता है.

ऐप्लिकेशन, रिकॉर्डिंग को और भी कॉन्फ़िगर कर सकते हैं. जैसे:

  • withAudioEnabled() के साथ ऑडियो चालू करें.
  • start(Executor, Consumer<VideoRecordEvent>) की मदद से, वीडियो रिकॉर्डिंग इवेंट पाने के लिए लिसनर रजिस्टर करें.
  • इस विकल्प को चुनने पर, रिकॉर्डिंग को लगातार रिकॉर्ड करने की अनुमति मिलती है. ऐसा तब होता है, जब VideoCapture को PendingRecording.asPersistentRecording() की मदद से किसी दूसरे कैमरे से फिर से बाइंड किया जाता है.

रिकॉर्डिंग शुरू करने के लिए, PendingRecording.start() पर कॉल करें. CameraX, PendingRecording को Recording में बदलता है, रिकॉर्डिंग के अनुरोध को लाइन में लगाता है, और ऐप्लिकेशन को नया Recording ऑब्जेक्ट दिखाता है. कैमरा डिवाइस पर रिकॉर्डिंग शुरू होने के बाद, CameraX एक VideoRecordEvent.EVENT_TYPE_START इवेंट भेजता है.

यहां दिए गए उदाहरण में, MediaStore फ़ाइल में वीडियो और ऑडियो रिकॉर्ड करने का तरीका बताया गया है:

// Create MediaStoreOutputOptions for our recorder
val name = "CameraX-recording-" +
        SimpleDateFormat(FILENAME_FORMAT, Locale.US)
                .format(System.currentTimeMillis()) + ".mp4"
val contentValues = ContentValues().apply {
   put(MediaStore.Video.Media.DISPLAY_NAME, name)
}
val mediaStoreOutput = MediaStoreOutputOptions.Builder(this.contentResolver,
                              MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
                              .setContentValues(contentValues)
                              .build()

// 2. Configure Recorder and Start recording to the mediaStoreOutput.
val recording = videoCapture.output
                .prepareRecording(context, mediaStoreOutput)
                .withAudioEnabled()
                .start(ContextCompat.getMainExecutor(this), captureListener)

कैमरे की झलक, डिफ़ॉल्ट रूप से सामने वाले कैमरे पर मिरर की जाती है. हालांकि, VideoCapture से रिकॉर्ड किए गए वीडियो, डिफ़ॉल्ट रूप से मिरर नहीं किए जाते. CameraX 1.3 की मदद से, अब वीडियो रिकॉर्डिंग को मिरर किया जा सकता है. इससे फ़्रंट कैमरे की झलक और रिकॉर्ड किए गए वीडियो को मैच किया जा सकता है.

MirrorMode के तीन विकल्प होते हैं: MIRROR_MODE_OFF, MIRROR_MODE_ON, और MIRROR_MODE_ON_FRONT_ONLY. कैमरे की झलक को अलाइन करने के लिए, Google का सुझाव है कि MIRROR_MODE_ON_FRONT_ONLY का इस्तेमाल करें. इसका मतलब है कि रियर कैमरे के लिए मिररिंग की सुविधा चालू नहीं है, लेकिन फ़्रंट कैमरे के लिए यह सुविधा चालू है. MirrorMode के बारे में ज़्यादा जानकारी के लिए, MirrorMode constants देखें.

इस कोड स्निपेट में, MIRROR_MODE_ON_FRONT_ONLY का इस्तेमाल करके VideoCapture.Builder.setMirrorMode() को कॉल करने का तरीका दिखाया गया है. ज़्यादा जानकारी के लिए, setMirrorMode() देखें.

Kotlin

val recorder = Recorder.Builder().build()

val videoCapture = VideoCapture.Builder(recorder)
    .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY)
    .build()

useCases.add(videoCapture);

Java

Recorder.Builder builder = new Recorder.Builder();
if (mVideoQuality != QUALITY_AUTO) {
    builder.setQualitySelector(
        QualitySelector.from(mVideoQuality));
}
  VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(builder.build())
      .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY)
      .build();
    useCases.add(videoCapture);

चालू रिकॉर्डिंग को कंट्रोल करना

Recording को इन तरीकों से रोका, फिर से शुरू किया, और बंद किया जा सकता है:

  • pause मौजूदा रिकॉर्डिंग को रोकने के लिए.
  • resume() रोकी गई ऐक्टिव रिकॉर्डिंग को फिर से शुरू करने के लिए.
  • stop() रिकॉर्डिंग बंद करने और उससे जुड़े सभी रिकॉर्डिंग ऑब्जेक्ट को फ़्लश करने के लिए.
  • mute() मौजूदा रिकॉर्डिंग को म्यूट या अनम्यूट करने के लिए.

ध्यान दें कि रिकॉर्डिंग को रोके जाने या चालू रहने की स्थिति में, Recording को खत्म करने के लिए stop() पर कॉल किया जा सकता है.

अगर आपने EventListener को PendingRecording.start() के साथ रजिस्टर किया है, तो Recording, VideoRecordEvent का इस्तेमाल करके कम्यूनिकेट करता है.

  • VideoRecordEvent.EVENT_TYPE_STATUS का इस्तेमाल, मौजूदा फ़ाइल के साइज़ और रिकॉर्ड किए गए समय जैसे आंकड़ों को रिकॉर्ड करने के लिए किया जाता है.
  • VideoRecordEvent.EVENT_TYPE_FINALIZE का इस्तेमाल रिकॉर्डिंग के नतीजे के लिए किया जाता है. इसमें फ़ाइनल फ़ाइल का यूआरआई और उससे जुड़ी गड़बड़ियों जैसी जानकारी शामिल होती है.

जब आपके ऐप्लिकेशन को EVENT_TYPE_FINALIZE मिलता है, तो इसका मतलब है कि रिकॉर्डिंग सेशन पूरा हो गया है. इसके बाद, OutputOptions में बताई गई जगह से रिकॉर्ड किया गया वीडियो ऐक्सेस किया जा सकता है.

अन्य संसाधन

CameraX के बारे में ज़्यादा जानने के लिए, यहां दिए गए अन्य संसाधन देखें: