يسجّل نظام الالتقاط بشكل عام بث الفيديو والصوت، ويضغطها، ثم يدمج البثين، ثم يكتب البث الناتج على القرص.
في CameraX، يتمثّل حل التقاط الفيديو في
VideoCapture
حالة الاستخدام التالية:
VideoCapture حالة الاستخدام.كما هو موضّح في الشكل 2، يتضمّن التقاط الفيديو باستخدام CameraX بعض المكوّنات المعمارية ذات المستوى العالي:
SurfaceProviderلمصدر الفيديوAudioSourceلمصدر الصوت- برنامجا ترميز لترميز الفيديو/الصوت وضغطهما
- أداة دمج وسائط لدمج تدفقَي البيانات.
- أداة لحفظ الملفات من أجل كتابة النتيجة
تجرِّد واجهة برمجة التطبيقات VideoCapture محرك الالتقاط المعقّد وتوفّر للتطبيقات واجهة برمجة تطبيقات أبسط وأكثر وضوحًا.
نظرة عامة على 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 العلاقات بين هذه العناصر:
وسيلة الإيضاح:
- إنشاء
RecorderباستخدامQualitySelector - اضبط
Recorderباستخدام أحدOutputOptions. - فعِّل الصوت باستخدام
withAudioEnabled()إذا لزم الأمر. - اتّصِل
start()بمستمعVideoRecordEventلبدء التسجيل. - استخدِم
pause()/resume()/stop()علىRecordingللتحكّم في التسجيل. - الرد على
VideoRecordEventsداخل أداة معالجة الحدث
تتوفّر قائمة مفصّلة بواجهات برمجة التطبيقات في ملف current.txt داخل رمز المصدر.
استخدام VideoCapture API
لدمج حالة استخدام VideoCapture CameraX في تطبيقك، اتّبِع الخطوات التالية:
- ربط
VideoCapture - إعداد التسجيل وضبطه
- ابدأ تسجيل وقت التشغيل وتحكَّم فيه.
توضّح الأقسام التالية الإجراءات التي يمكنك اتّخاذها في كل خطوة للحصول على جلسة تسجيل شاملة.
Bind VideoCapture
لربط حالة الاستخدام VideoCapture، اتّبِع الخطوات التالية:
- أنشئ عنصر
Recorder. - أنشئ عنصر
VideoCapture. - الربط بـ
Lifecycle
تتّبع واجهة برمجة التطبيقات VideoCapture في CameraX نمط التصميم الخاص بأداة الإنشاء. تستخدم التطبيقات Recorder.Builder لإنشاء Recorder. يمكنك أيضًا ضبط درجة دقة الفيديو Recorder من خلال عنصر QualitySelector.
تتوافق مكتبة CameraX Recorder مع Qualities المحدّدة مسبقًا التالية لدرجات دقة الفيديو:
Quality.UHDلحجم فيديو بدقة فائقة للغاية (2160p) بتنسيق 4KQuality.FHDلحجم الفيديو بدقة فائقة (1080p)Quality.HDلحجم الفيديو بدقة عالية (720p)Quality.SDلحجم الفيديو بدقة عادية (480p)
يُرجى العِلم أنّه يمكن لتطبيق 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، يمكن للتطبيق إنشاء عناصر تسجيل لتنفيذ عملية تسجيل الفيديو والصوت. تنشئ التطبيقات التسجيلات من خلال تنفيذ ما يلي:
- اضبط
OutputOptionsباستخدامprepareRecording(). - (اختياري) فعِّل التسجيل الصوتي.
- استخدِم
start()لتسجيلVideoRecordEventمستمع، وابدأ في التقاط الفيديو.
تعرضRecorder عنصر Recording عند استدعاء الدالة start().
يمكن أن يستخدم تطبيقك عنصر Recording هذا لإنهاء عملية الالتقاط أو لتنفيذ إجراءات أخرى، مثل الإيقاف المؤقت أو الاستئناف.
يمكن أن يتضمّن Recorder عنصر Recording واحدًا في كل مرة. يمكنك بدء تسجيل جديد بعد الاتصال بالرقم Recording.stop() أو Recording.close() على العنصر السابق Recording.
لنلقِ نظرة على هذه الخطوات بمزيد من التفصيل. أولاً، يضبط التطبيق
OutputOptions لمسجِّلة باستخدام Recorder.prepareRecording().
تتيح Recorder الأنواع التالية من OutputOptions:
FileDescriptorOutputOptionsلالتقاط المحتوى فيFileDescriptorFileOutputOptionsلالتقاط صورة فيFileMediaStoreOutputOptionsلالتقاط صورة في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. باستخدام CameraX 1.3، أصبح بإمكانك الآن عكس تسجيلات الفيديو لكي تتطابق معاينة الكاميرا الأمامية مع الفيديو المسجّل.
تتوفّر ثلاثة خيارات لوضع MirrorMode: MIRROR_MODE_OFF وMIRROR_MODE_ON وMIRROR_MODE_ON_FRONT_ONLY. للمحاذاة مع معاينة الكاميرا، تنصح Google باستخدام MIRROR_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);
التحكّم في تسجيل نشط
يمكنك إيقاف 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.
مراجع إضافية
لمزيد من المعلومات حول CameraX، يُرجى الاطّلاع على المراجع الإضافية التالية:
- درس تطبيقي حول الترميز: بدء استخدام CameraX
- تطبيق تجريبي رسمي لـ CameraX
- قائمة أحدث واجهات برمجة التطبيقات لالتقاط الفيديو في CameraX
- ملاحظات إصدار CameraX
- رمز المصدر CameraX