بنية التقاط الفيديوهات باستخدام CameraX

يسجّل نظام الالتقاط بشكل عام أحداث الفيديو والصوت ويضغطها، ثم يدمج الحدثين، ثم يكتب الحدث الناتج على القرص.

مخطّط بياني مفاهيمي لنظام التقاط الفيديو والصوت
الشكل 1. مخطّط مفاهيمي لنظام تسجيل الفيديو والصوت

في CameraX، الحلّ لالتقاط الفيديو هو حالة الاستخدام VideoCapture:

مخطّط مفاهيمي يوضّح كيفية تعامل CameraX مع حالة استخدام التقاط الفيديو
الشكل 2. مخطّط بياني مفاهيمي يوضّح كيفية تعامل CameraX مع حالة استخدام VideoCapture

كما هو موضّح في الشكل 2، يتضمّن التقاط الفيديو في CameraX بعض المكوّنات المعمارية عالية المستوى:

  • ‫SurfaceProvider لمصدر الفيديو
  • ‫AudioSource لمصدر الصوت
  • برنامجا ترميز لترميز الفيديو والصوت وضغطهما
  • مُضاعِف وسائط لمضاعفة البثَّين
  • أداة حفظ ملفات لكتابة النتيجة

تجرّد واجهة برمجة التطبيقات VideoCapture API محرّك التسجيل المعقّد وتوفّر للتطبيقات واجهة برمجة تطبيقات أبسط وأسهل بكثير.

نظرة عامة على VideoCapture API

‫VideoCapture هي حالة استخدام في CameraX تعمل بشكل جيد بمفردها أو عند دمجها مع حالات استخدام أخرى. تعتمد المجموعات المحدّدة المتوافقة على إمكانات أجهزة الكاميرا، ولكن Preview وVideoCapture هما مجموعة صالحة لحالات الاستخدام على جميع الأجهزة.

تتكوّن واجهة برمجة التطبيقات VideoCapture من العناصر التالية التي تتواصل مع التطبيقات:

  • VideoCapture هي فئة حالة الاستخدام الأعلى مستوى. يرتبط VideoCapture بـ LifecycleOwner مع CameraSelector وحالات استخدام CameraX الأخرى. لمزيد من المعلومات حول هذه المفاهيم والاستخدامات، يُرجى الاطّلاع على بنية CameraX.
  • Recorder هو تنفيذ لـ VideoOutput مرتبط بشكل وثيق بـ VideoCapture. يُستخدم "Recorder" لتسجيل الفيديو والصوت. ينشئ التطبيق تسجيلات من Recorder.
  • يضبط PendingRecording التسجيل، ويوفّر خيارات مثل تفعيل الصوت وضبط متتبِّع الأحداث. يجب استخدام Recorder لإنشاء PendingRecording. لا يسجّل جهاز PendingRecording أي شيء.
  • يُجري Recording التسجيل الفعلي. يجب استخدام PendingRecording لإنشاء Recording.

يوضّح الشكل 3 العلاقات بين هذه العناصر:

مخطّط بياني يعرض التفاعلات التي تحدث في حالة استخدام التقاط الفيديو
الشكل 3. مخطّط بياني يعرض التفاعلات التي تحدث في حالة استخدام VideoCapture

الشرح:

  1. أنشئ Recorder باستخدام QualitySelector.
  2. اضبط Recorder باستخدام أحد OutputOptions.
  3. فعِّل الصوت باستخدام withAudioEnabled() إذا لزم الأمر.
  4. اتصل بـ start() باستخدام مستمع VideoRecordEvent لبدء التسجيل.
  5. استخدِم pause()/resume()/stop() على Recording للتحكّم في التسجيل.
  6. الرد على VideoRecordEvents داخل متتبِّع الأحداث

تتوفّر قائمة واجهات برمجة التطبيقات المفصّلة في ملف current.txt داخل الرمز المصدر.

استخدام VideoCapture API

لدمج حالة استخدام VideoCapture في CameraX في تطبيقك، اتّبِع الخطوات التالية:

  1. ربط VideoCapture
  2. إعداد التسجيل وضبطه
  3. بدء تسجيل وقت التشغيل والتحكّم فيه

توضّح الأقسام التالية ما يمكنك فعله في كل خطوة للحصول على جلسة تسجيل شاملة.

ربط VideoCapture

لربط حالة الاستخدام VideoCapture، اتّبِع الخطوات التالية:

  1. أنشِئ عنصر Recorder.
  2. إنشاء عنصر واحد (VideoCapture)
  3. الربط بـ Lifecycle

تتّبع واجهة برمجة التطبيقات VideoCapture في CameraX نمط تصميم أداة الإنشاء. تستخدم التطبيقات Recorder.Builder لإنشاء Recorder. يمكنك أيضًا ضبط درجة دقة الفيديو في "Recorder" من خلال عنصر "QualitySelector".

تتيح واجهة برمجة التطبيقات CameraX Recorder استخدام Qualities المحدّدة مسبقًا التالية لدرجات دقة الفيديو:

  • ‫Quality.UHD لحجم فيديو بدقة فائقة للغاية 4K‏ (2160p)
  • Quality.QHD لحجم فيديو بدقة Quad HD ‏(1440p)، تم تقديمه في CameraX 1.7.0-alpha02
  • ‫Quality.FHD لحجم فيديو بدقة فائقة (1080p)
  • ‫Quality.HD لحجم الفيديو بدقة عالية (720p)
  • ‫Quality.SD لحجم الفيديو بدقة عادية (480p)

يُرجى العِلم أنّ CameraX يمكنه أيضًا اختيار درجات دقة أخرى عندما يسمح التطبيق بذلك.

يعتمد حجم الفيديو الدقيق لكل خيار على إمكانات الكاميرا وبرنامج الترميز. لمزيد من المعلومات، يُرجى الاطّلاع على مستندات CamcorderProfile.

يمكن للتطبيقات ضبط الدقة من خلال إنشاء QualitySelector. يمكنك إنشاء QualitySelector باستخدام إحدى الطرق التالية:

  • قدِّم بعض درجات الدقة المفضّلة باستخدام السمة fromOrderedList، وأدرِج استراتيجية احتياطية لاستخدامها في حال عدم توفّر أي من درجات الدقة المفضّلة.

    يمكن لـ CameraX تحديد أفضل مطابقة احتياطية استنادًا إلى إمكانات الكاميرا المحدّدة، يُرجى الرجوع إلى FallbackStrategy specification في QualitySelector لمزيد من التفاصيل. على سبيل المثال، يطلب الرمز التالي أعلى درجة دقة متاحة للتسجيل، وإذا لم تكن أي من درجات الدقة المطلوبة متاحة، يتم السماح لـ CameraX باختيار درجة دقة تكون الأقرب إلى Quality.SD:

    val qualitySelector = QualitySelector.fromOrderedList(
             listOf(Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD),
             FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))
    
  • استعلم عن إمكانات الكاميرا أولاً، ثم اختَر من بين درجات الدقة المتوافقة باستخدام QualitySelector.from:

    val cameraInfo = cameraProvider.availableCameraInfos.filter {
        it.cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
            CameraMetadata.LENS_FACING_BACK
    }
    
    // Filter to SDR resolutions supported by both the camera sensor and Recorder
    // encoder so the UI picker only displays valid options.
    val supportedQualities =
        Recorder.getVideoCapabilities(cameraInfo[0]).getSupportedQualities(DynamicRange.SDR)
    val filteredQualities = arrayListOf (Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD)
                           .filter { supportedQualities.contains(it) }
    
    viewBinding.simpleQualityListView.apply {
        adapter = ArrayAdapter(context,
                               android.R.layout.simple_list_item_1,
                               filteredQualities.map { it.qualityToString() })
    
        setOnItemClickListener { _, _, position, _ ->
            // QualitySelector is configured at Recorder build time, so selecting
            // a new resolution requires building a new Recorder instance.
            val qualitySelector = QualitySelector.from(filteredQualities[position])
    
            val recorder = Recorder.Builder()
                .setQualitySelector(qualitySelector).build()
    
             // ...
        }
    }
    
    fun Quality.qualityToString() : String {
        return when (this) {
            Quality.UHD -> "UHD"
            Quality.QHD -> "QHD"
            Quality.FHD -> "FHD"
            Quality.HD -> "HD"
            Quality.SD -> "SD"
            else -> throw IllegalArgumentException()
        }
    }
    
    

    كل Quality يتم عرضه من خلال VideoCapabilities.getSupportedQualities (من Recorder.getVideoCapabilities لـ DynamicRange.SDR) يعمل مع حالة استخدام 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. اضبط OutputOptions باستخدام prepareRecording().
  2. (اختياري) فعِّل ميزة تسجيل الصوت.
  3. استخدِم start() لتسجيل مستمع VideoRecordEvent وبدء التقاط الفيديو.

تعرض السمة Recorder عنصر Recording عند استدعاء الدالة start(). يمكن لتطبيقك استخدام عنصر Recording هذا لإنهاء عملية التسجيل أو لتنفيذ إجراءات أخرى، مثل الإيقاف المؤقت أو الاستئناف.

يتيح Recorder استخدام عنصر Recording واحد في كل مرة. يمكنك بدء تسجيل جديد بعد استدعاء Recording.stop() أو Recording.close() على عنصر Recording السابق.

لنلقِ نظرة على هذه الخطوات بمزيد من التفصيل. أولاً، يضبط التطبيق OutputOptions لـ "المسجّلة الذكية" باستخدام Recorder.prepareRecording(). يتيح Recorder استخدام الأنواع التالية من OutputOptions:

  • FileDescriptorOutputOptions لالتقاطها في FileDescriptor.
  • FileOutputOptions لالتقاط الصور في File.
  • MediaStoreOutputOptions لالتقاطها في MediaStore.

تتيح لك جميع أنواع OutputOptions ضبط الحد الأقصى لحجم الملف باستخدام setFileSizeLimit(). تتعلّق الخيارات الأخرى بنوع الإخراج الفردي، مثل ParcelFileDescriptor لـ FileDescriptorOutputOptions.

يعرض 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 لا تكون معكوسة تلقائيًا. باستخدام الإصدار 1.3 من CameraX، أصبح من الممكن الآن عكس تسجيلات الفيديو بحيث تتطابق معاينة الكاميرا الأمامية مع الفيديو المسجّل.

هناك ثلاثة خيارات لـ MirrorMode: MIRROR_MODE_OFF وMIRROR_MODE_ON وMIRROR_MODE_ON_FRONT_ONLY. للمحاذاة مع معاينة الكاميرا، تنصح Google باستخدام MIROR_MODE_ON_FRONT_ONLY، ما يعني أنّه لا يتم تفعيل الانعكاس للكاميرا الخلفية، ولكن يتم تفعيله للكاميرا الأمامية. لمزيد من المعلومات حول MirrorMode، يُرجى الاطّلاع على MirrorMode constants.

يوضّح مقتطف الرمز هذا كيفية استدعاء VideoCapture.Builder.setMirrorMode() باستخدام MIRROR_MODE_ON_FRONT_ONLY. لمزيد من المعلومات، يُرجى الاطّلاع على 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);

النطاق الديناميكي (فيديو HDR)

تتيح واجهة CameraX تسجيل فيديوهات 10 بت بنطاق عالي الديناميكية (HDR)، مثل HLG10 أو HDR10 أو HDR10+‎ أو Dolby Vision، باستخدام DynamicRange.

لاستخدام ميزة تسجيل الفيديو بنطاق عالي الديناميكية، أكمِل الخطوات التالية:

  1. يمكنك الاستعلام عن النطاقات الديناميكية المتوافقة مع الكاميرا باستخدام VideoCapabilities.getSupportedDynamicRanges().
  2. اختياري: في حال ضبط QualitySelector مخصّص، تحقَّق من الجودة المتوافقة مع هذا النطاق الديناميكي باستخدام getSupportedQualities(DynamicRange).
  3. اضبط "VideoCapture.Builder" باستخدام setDynamicRange().

يتيح المثال التالي تسجيل فيديو 10 بت بنطاق عالي الديناميكية بتقنية HLG عندما تتيح الكاميرا ذلك:

Kotlin

val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo)
val supportedHdrRanges = videoCapabilities.supportedDynamicRanges
    .filter { it != DynamicRange.SDR }

val recorder = Recorder.Builder().build()
val videoCapture = VideoCapture.Builder(recorder)
    .apply {
        if (supportedHdrRanges.contains(DynamicRange.HLG_10_BIT)) {
            setDynamicRange(DynamicRange.HLG_10_BIT)
        }
    }
    .build()

Java

VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(cameraInfo);
Set<DynamicRange> supportedRanges = videoCapabilities.getSupportedDynamicRanges();

Recorder recorder = new Recorder.Builder().build();
VideoCapture.Builder<Recorder> builder = new VideoCapture.Builder<>(recorder);
if (supportedRanges.contains(DynamicRange.HLG_10_BIT)) {
    builder.setDynamicRange(DynamicRange.HLG_10_BIT);
}
VideoCapture<Recorder> videoCapture = builder.build();

تثبيت صورة الفيديو

تتيح واجهة CameraX تثبيت صورة الفيديو لتقليل الاهتزاز والتشويش أثناء حمل الجهاز باليد عند تسجيل الفيديو.

لتفعيل ميزة "تثبيت الفيديو"، اتّبِع الخطوات التالية:

  1. تحقَّق مما إذا كانت الكاميرا تتيح ميزة التثبيت باستخدام VideoCapabilities.isStabilizationSupported().
  2. يمكنك تفعيلها على VideoCapture.Builder باستخدام setVideoStabilizationEnabled(true).

يؤدي المثال التالي إلى تفعيل ميزة التثبيت عندما تكون الكاميرا متوافقة معها:

Kotlin

val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo)
val videoCapture = VideoCapture.Builder(recorder)
    .setVideoStabilizationEnabled(videoCapabilities.isStabilizationSupported)
    .build()

Java

VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(cameraInfo);
VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(recorder)
    .setVideoStabilizationEnabled(videoCapabilities.isStabilizationSupported())
    .build();

التحكّم في تسجيل نشط

يمكنك إيقاف Recording جارية مؤقتًا واستئنافها وإيقافها باستخدام الطرق التالية:

  • pause لإيقاف التسجيل النشط الحالي مؤقتًا
  • resume() لاستئناف تسجيل نشط تم إيقافه مؤقتًا
  • stop() لإنهاء التسجيل ومحو أي عناصر تسجيل مرتبطة به
  • mute() لكتم صوت التسجيل الحالي أو إعادته

يُرجى العِلم أنّه يمكنك استدعاء stop() لإنهاء Recording بغض النظر عمّا إذا كان التسجيل في حالة إيقاف مؤقت أو نشط.

إذا سجّلت EventListener في PendingRecording.start()، يتواصل Recording باستخدام VideoRecordEvent.

  • يُستخدم VideoRecordEvent.EVENT_TYPE_STATUS لتسجيل الإحصاءات، مثل حجم الملف الحالي والنطاق الزمني المسجَّل.
  • يتم استخدام VideoRecordEvent.EVENT_TYPE_FINALIZE لنتيجة التسجيل ويتضمّن معلومات مثل معرّف الموارد المنتظم (URI) للملف النهائي مع أي أخطاء ذات صلة.

بعد أن يتلقّى تطبيقك EVENT_TYPE_FINALIZE يشير إلى نجاح جلسة التسجيل، يمكنك الوصول إلى الفيديو الذي تم تسجيله من الموقع الجغرافي المحدّد في OutputOptions.

سعة الصوت وحالته في الوقت الفعلي

أثناء التسجيل، توفّر أحداث VideoRecordEvent.Status إحصاءات صوتية في الوقت الفعلي من خلال AudioStats:

  • تعرض الدالة AudioStats.getAudioAmplitude() السعة القصوى الحالية للصوت، وتتراوح قيمتها بين 0.0 و1.0. يمكنك استخدام هذه القيمة لتشغيل عدّادات واجهة المستخدم أو أدوات العرض المرئي للشكل الموجي الصوتي.
  • AudioStats.getAudioState() تشير إلى الحالة الحالية للبث الصوتي، مثل AUDIO_STATE_ACTIVE أو AUDIO_STATE_MUTED أو AUDIO_STATE_SOURCE_SILENCED.

يقرأ المثال التالي سعة الصوت من حدث حالة:

Kotlin

when (event) {
    is VideoRecordEvent.Status -> {
        val audioStats = event.recordingStats.audioStats
        if (audioStats.hasAudio()) {
            val amplitude = audioStats.audioAmplitude
            updateAudioWaveform(amplitude)
        }
    }
    // ...
}

Java

if (event instanceof VideoRecordEvent.Status) {
    VideoRecordEvent.Status status = (VideoRecordEvent.Status) event;
    AudioStats audioStats = status.getRecordingStats().getAudioStats();
    if (audioStats.hasAudio()) {
        double amplitude = audioStats.getAudioAmplitude();
        updateAudioWaveform(amplitude);
    }
}

فيديو عالي السرعة وبالتصوير البطيء

تتيح واجهة CameraX تسجيل الفيديو بسرعة عالية، مثل 120 أو 240 أو 480 لقطة في الثانية، ما يتيح حالتي استخدام مختلفتين:

  • فيديو بمعدّل لقطات مرتفع (الحركة البطيئة التي يعالجها المشغّل): تلتقط واجهة CameraX اللقطات وتحفظها بمعدّل لقطات مرتفع (على سبيل المثال، 120 لقطة في الثانية). يتحكم مشغل الفيديو في سرعة التشغيل، مما يسمح للمستخدمين بالتبديل بين السرعة العادية والحركة البطيئة أو إجراء تحليل إطار تلو الآخر.
  • فيديو بالحركة البطيئة جاهز للتشغيل: تعالج واجهة CameraX البث العالي السرعة وتُخرج ملف فيديو عاديًا بمعدل 30 لقطة في الثانية مع طوابع زمنية معدَّلة للقطات. يتم "دمج" تأثير الحركة البطيئة، لذا يتم تشغيل الفيديو بالحركة البطيئة تلقائيًا في أي مشغّل عادي بدون الحاجة إلى مشغّل خاص. على سبيل المثال، إذا تم التقاط فيديو بمعدّل 120 لقطة في الثانية وتشغيله بمعدّل 30 لقطة في الثانية، سيتم إنتاج فيديو بالتصوير البطيء بسرعة 1/4.

التحقّق من إمكانات السرعة العالية

يتطلّب التقاط الفيديو بسرعة عالية توفُّر أجهزة متوافقة وتعريفات CamcorderProfile ذات صلة من الشركات المصنّعة للأجهزة، مثل CamcorderProfile.QUALITY_HIGH_SPEED_1080P أو QUALITY_HIGH_SPEED_720P.

قبل ضبط التسجيل العالي السرعة، يمكنك الاستعلام عن الإمكانات العالية السرعة باستخدام Recorder.getHighSpeedVideoCapabilities(CameraInfo):

Kotlin

val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)
if (highSpeedCapabilities == null) {
    // Camera does not support high-speed video capture
    return
}
val supportedQualities = highSpeedCapabilities.getSupportedQualities(DynamicRange.SDR)

Java

VideoCapabilities highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo);
if (highSpeedCapabilities == null) {
    // Camera does not support high-speed video capture
    return;
}
List<Quality> supportedQualities = highSpeedCapabilities.getSupportedQualities(DynamicRange.SDR);

ضبط HighSpeedVideoSessionConfig

لاستخدام ميزة "الالتقاط العالي السرعة"، ادمج حالتَي استخدام VideoCapture وPreview في HighSpeedVideoSessionConfig. لضبط الجلسة، أكمِل الخطوات التالية:

  1. أنشئ حالة استخدام VideoCapture وحالة استخدام Preview.
  2. ابدأ HighSpeedVideoSessionConfig.Builder باستخدام حالة الاستخدام VideoCapture وأرفِق Preview.
  3. يمكنك الاستعلام عن نطاقات عدد اللقطات في الثانية المتوافقة باستخدام CameraInfo.getSupportedFrameRateRanges(SessionConfig) وضبط النطاق المحدّد.
  4. اختَر بين فيديو بمعدّل لقطات مرتفع أو فيديو بالحركة البطيئة جاهز للتشغيل:
    • لإنشاء فيديو بمعدّل لقطات مرتفع، اترك setSlowMotionEnabled(false) (الإعداد التلقائي).
    • لإنشاء فيديو بالحركة البطيئة جاهز للتشغيل، يمكنك استدعاء setSlowMotionEnabled(true).
  5. اربط إعدادات الجلسة باستخدام cameraProvider.bindToLifecycle().

يضبط المثال التالي جلسة حركة بطيئة جاهزة للتشغيل ويربطها:

Kotlin

val preview = Preview.Builder().build()
val recorder = Recorder.Builder()
    .setQualitySelector(QualitySelector.from(supportedQualities.first()))
    .build()
val videoCapture = VideoCapture.withOutput(recorder)

// Build HighSpeedVideoSessionConfig
val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)
    .setPreview(preview)
    // Enable automatic slow-motion playback at 30 fps
    .setSlowMotionEnabled(true)

// Query and set a supported high-speed frame rate range (such as 120 or 240 fps).
// The set is non-empty because getHighSpeedVideoCapabilities() returned non-null earlier.
val supportedFpsRanges = cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())
sessionConfigBuilder.setFrameRateRange(supportedFpsRanges.first())

val sessionConfig = sessionConfigBuilder.build()

// Bind session config to lifecycle
cameraProvider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    sessionConfig
)

Java

Preview preview = new Preview.Builder().build();
Recorder recorder = new Recorder.Builder()
    .setQualitySelector(QualitySelector.from(supportedQualities.get(0)))
    .build();
VideoCapture<Recorder> videoCapture = VideoCapture.withOutput(recorder);

HighSpeedVideoSessionConfig.Builder sessionConfigBuilder =
    new HighSpeedVideoSessionConfig.Builder(videoCapture)
        .setPreview(preview)
        .setSlowMotionEnabled(true);

// The set is non-empty because getHighSpeedVideoCapabilities() returned non-null earlier.
Set<Range<Integer>> supportedFpsRanges =
    cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build());
sessionConfigBuilder.setFrameRateRange(supportedFpsRanges.iterator().next());

HighSpeedVideoSessionConfig sessionConfig = sessionConfigBuilder.build();

cameraProvider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    sessionConfig
);

يمكنك أيضًا استخدام لغة DSL في Kotlin، التي تم تقديمها في الإصدار 1.7.0-alpha02 من CameraX، لضبط جلسات عالية السرعة بإيجاز:

val sessionConfig = highSpeedVideoSessionConfig(videoCapture) {
    this.preview = preview
    isSlowMotionEnabled = true
    frameRateRange = supportedFpsRanges.first()
}
cameraProvider.bindToLifecycle(
    lifecycleOwner,
    CameraSelector.DEFAULT_BACK_CAMERA,
    sessionConfig
)

تسجيل فيديو عالي السرعة أو بالحركة البطيئة

بعد ربط HighSpeedVideoSessionConfig، ابدأ التسجيل باستخدام VideoCapture بالطريقة نفسها التي تستخدمها في تسجيلات الفيديو العادية:

Kotlin

val recording = videoCapture.output
    .prepareRecording(context, mediaStoreOutput)
    .withAudioEnabled()
    .start(ContextCompat.getMainExecutor(context)) { event ->
        when (event) {
            is VideoRecordEvent.Start -> Log.d(TAG, "Recording started")
            is VideoRecordEvent.Finalize -> {
                if (!event.hasError()) {
                    Log.d(TAG, "Video saved: ${event.outputResults.outputUri}")
                }
            }
        }
    }

Java

Recording recording = videoCapture.getOutput()
    .prepareRecording(context, mediaStoreOutput)
    .withAudioEnabled()
    .start(ContextCompat.getMainExecutor(context), event -> {
        if (event instanceof VideoRecordEvent.Start) {
            Log.d(TAG, "Recording started");
        } else if (event instanceof VideoRecordEvent.Finalize) {
            VideoRecordEvent.Finalize finalize = (VideoRecordEvent.Finalize) event;
            if (!finalize.hasError()) {
                Log.d(TAG, "Video saved: " + finalize.getOutputResults().getOutputUri());
            }
        }
    });

مراجع إضافية

لمزيد من المعلومات حول CameraX، يُرجى الاطّلاع على المراجع الإضافية التالية: