بشكل عام، يعمل نظام الالتقاط على تسجيل البث المباشر للفيديو والصوت وضغطه ودمج البثين، ثم كتابة البث الناتج على القرص.
في CameraX، يكون الحل لالتقاط صورة الفيديو هو حالة الاستخدام
VideoCapture
:
كما هو موضح في الشكل 2، يشتمل التقاط فيديو CameraX على بعض المكونات ذات المستوى المعماري عالي المستوى:
SurfaceProvider
لمصدر الفيديو.AudioSource
لمصدر الصوت.- برنامجا ترميز لتشفير وضغط الفيديو/الصوت.
- برنامج دمج وسائط لمزج مجموعتَي البث.
- موفر ملف لكتابة النتيجة.
تعمل واجهة برمجة التطبيقات VideoCapture على استخلاص محرك الالتقاط المعقد كما توفر للتطبيقات واجهة برمجة تطبيقات أكثر بساطة ووضوحًا.
نظرة عامة على VideoCapture API
"VideoCapture
" هي حالة استخدام من CameraX تعمل بشكل جيد من تلقاء نفسها أو عند دمجها مع حالات استخدام أخرى. تعتمد بعض المجموعات المتوافقة على إمكانات جهاز الكاميرا، غير أنّ Preview
وVideoCapture
هما مزيجان صالحان من حالات الاستخدام على جميع الأجهزة.
تتكوّن واجهة برمجة التطبيقات VideoCapture من الكائنات التالية التي تتصل بالتطبيقات:
VideoCapture
هي فئة حالة الاستخدام ذات المستوى الأعلى. يربطVideoCapture
بـLifecycleOwner
معCameraSelector
و CameraX UseCases الأخرى. لمزيد من المعلومات حول هذه المفاهيم والاستخدامات، يُرجى الاطّلاع على بنية CameraX.Recorder
هي عملية تنفيذ لمخرجات الفيديو ترتبط ارتباطًا وثيقًا بـ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
لدمج حالة استخدام CameraX VideoCapture
في تطبيقك، عليك اتّباع
الخطوات التالية:
- ربط
VideoCapture
. - تحضير التسجيل وإعداده
- بدء تسجيل وقت التشغيل والتحكّم فيه
توضّح الأقسام التالية الإجراءات التي يمكنك اتّخاذها في كل خطوة للحصول على جلسة تسجيل شامل.
ربط التقاط الفيديو
لربط حالة استخدام VideoCapure
، عليك اتّباع الخطوات التالية:
- أنشِئ عنصر
Recorder
. - إنشاء كائن
VideoCapture
- الربط بـ
Lifecycle
.
تتبع واجهة برمجة تطبيقات CameraX VideoCapture نمط تصميم أداة الإنشاء. تستخدم التطبيقات Recorder.Builder
لإنشاء Recorder
. ويمكنك أيضًا ضبط درجة دقة الفيديو للسمة Recorder
من خلال كائن QualitySelector
.
يتوافق تطبيق CameraX Recorder
مع Qualities
التالية المحدِّدة مسبقًا لدرجات دقة الفيديو:
Quality.UHD
لحجم الفيديو بدقة فائقة بتنسيق 4K (2160p)Quality.FHD
لحجم الفيديو بدقة فائقة (1080p)Quality.HD
لحجم الفيديو بدقة عالية (720p)Quality.SD
لحجم الفيديو بدقة عادية (480p)
وتجدر الإشارة إلى أنّ تطبيق CameraX يمكنه أيضًا اختيار درجات دقة أخرى عندما يسمح التطبيق بذلك.
يعتمد الحجم الدقيق للفيديو لكلّ اختيار على إمكانات الكاميرا وبرنامج الترميز. لمزيد من المعلومات، يمكنك الاطّلاع على مستندات
CamcorderProfile
.
يمكن للتطبيقات ضبط درجة الدقة من خلال إنشاء QualitySelector
.
يمكنك إنشاء QualitySelector
باستخدام إحدى الطرق التالية:
قدِّم بعض درجات الدقة المفضّلة باستخدام
fromOrderedList()
، وأدرِج استراتيجية احتياطية لاستخدامها في حال عدم توافق أي من درجات الدقة المفضّلة.يمكن أن تحدّد CameraX أفضل مطابقة احتياطية استنادًا إلى إمكانات الكاميرا التي تم اختيارها. يُرجى الرجوع إلى
FallbackStrategy specification
الخاصة بـQualitySelector
للاطّلاع على مزيد من التفاصيل. على سبيل المثال، يطلب الرمز التالي الحصول على درجة دقة أعلى متوافقة للتسجيل، وإذا كان لا يمكن إتاحة أي من درجات دقة الطلب، يمكنك تفويض تطبيق CameraX لاختيار درجة الدقة الأقرب من حيث الدقة العادية: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
من أجل التقاط صور له فيFileDescriptor
.FileOutputOptions
من أجل التقاط الصورة فيFile
.MediaStoreOutputOptions
من أجل التقاط صور له فيMediaStore
.
تتيح لك جميع أنواع OutputOptions
ضبط حد أقصى لحجم الملف باستخدام
setFileSizeLimit()
. وهناك خيارات أخرى خاصة بنوع الإخراج الفردي،
مثل ParcelFileDescriptor
في FileDescriptorOutputOptions
.
وتعرض prepareRecording()
الكائن PendingRecording
، وهو كائن وسيط يُستخدَم لإنشاء كائن Recording
المقابل. PendingRecording
هي فئة مؤقتة يجب أن تكون
غير مرئية في معظم الحالات ونادرًا ما يتم تخزينها مؤقتًا بواسطة التطبيق.
يمكن للتطبيقات ضبط إعدادات التسجيل بشكل أكبر، مثل:
- فعِّل ميزة الصوت باستخدام "
withAudioEnabled()
". - عليك تسجيل مستمع لتلقّي أحداث تسجيل الفيديو
مع
start(Executor, Consumer<VideoRecordEvent>)
. - السماح للتسجيل بالتسجيل بشكل مستمر أثناء ارتداد كاميرا الفيديو
المرفقة بها إلى كاميرا أخرى باستخدام
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 باستخدام 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);
التحكّم في تسجيل نشط
يمكنك إيقاف 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