يسجّل نظام الالتقاط بشكل عام عمليات بث الفيديو والصوت ويضغطها مزج البثين، ثم كتابة الدفق الناتج إلى القرص.
![مخطط المفاهيمي لنظام التقاط الفيديو والصوت](https://developer.android.com/static/images/training/camera/camerax/conceptual-capturing-system.png?authuser=9&hl=ar)
في CameraX، يكون حل التقاط الفيديو هو
VideoCapture
حالة الاستخدام:
![رسم بياني مفاهيمي يوضّح طريقة تعامل الكاميرا x مع
حالة استخدام تصوير فيديو](https://developer.android.com/static/images/training/camera/camerax/videocapture-use-case.png?authuser=9&hl=ar)
VideoCapture
.كما هو موضح في الشكل 2، يتضمن التقاط فيديو CameraX بعض الطبقات المكونات المعمارية:
SurfaceProvider
لمصدر الفيديو.AudioSource
لمصدر الصوت.- برنامجا ترميز لترميز الفيديو/الصوت وضغطه
- جهاز وسائط لمزج البث المباشر
- توفير ملفات لكتابة النتيجة
تعمل واجهة برمجة التطبيقات VideoCapture على تجريد محرك الالتقاط المعقد وتوفر ذات واجهة برمجة تطبيقات أبسط ومباشرة.
نظرة عامة حول VideoCapture API
إنّ VideoCapture
هي حالة استخدام CameraX تعمل بشكل منفرد أو عندما
إلى جانب حالات استخدام أخرى. تعتمد المجموعات المحددة المعتمدة على
إمكانات جهاز الكاميرا، ولكن Preview
وVideoCapture
تركيبة حالة استخدام صالحة على جميع الأجهزة.
تتألف واجهة برمجة التطبيقات VideoCapture من الكائنات التالية التي تتصل مع التطبيقات:
VideoCapture
هو فئة حالة استخدام عالية المستوى. يرتبطVideoCapture
بـLifecycleOwner
معCameraSelector
وجهاز CameraX آخر حالات الاستخدام. لمزيد من المعلومات عن هذه المفاهيم والاستخدامات، يُرجى الاطّلاع على بنية CameraX.Recorder
هي تنفيذ "مخرجات الفيديو" إلى جانبVideoCapture
. تُستخدَمRecorder
لتسجيل الفيديو والصوت. إنّ ينشئ التطبيق تسجيلات منRecorder
.PendingRecording
لإعداد التسجيل، وتوفير خيارات مثل تفعيل الصوت والإعدادات أداة معالجة الحدث. يجب استخدامRecorder
لإنشاءPendingRecording
. لا تسجِّلPendingRecording
أي بيانات.- ينفذ
Recording
التسجيل الفعلي. يجب استخدامPendingRecording
لإنشاءRecording
.
يوضح الشكل 3 العلاقات بين هذه الكائنات:
![رسم تخطيطي يوضح التفاعلات التي تحدث في مقطع فيديو
التقاط حالة الاستخدام](https://developer.android.com/static/images/training/camera/camerax/videocapture-roles-interaction.png?authuser=9&hl=ar)
وسيلة الإيضاح:
- إنشاء
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 باختيار الدقة الأقرب إلى درجة دقة 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
لالتقاط صورةFileDescriptor
FileOutputOptions
لتسجيل فيديو فيFile
MediaStoreOutputOptions
لالتقاط صورةMediaStore
تتيح لك جميع أنواع OutputOptions
ضبط حد أقصى لحجم الملف باستخدام
setFileSizeLimit()
أمّا الخيارات الأخرى، تقتصر على النتائج الفردية
النوع، مثل ParcelFileDescriptor
للإشارة إلى FileDescriptorOutputOptions
.
تعرض الدالة prepareRecording()
الكائن PendingRecording
،
كائن وسيط يستخدم لإنشاء
كائن Recording
. PendingRecording
هي فئة عابرة يجب
تكون غير مرئية في معظم الحالات ونادرًا ما يتم تخزينها مؤقتًا بواسطة التطبيق.
يمكن للتطبيقات ضبط المزيد من إعدادات التسجيل، مثل:
- تفعيل الصوت مع
withAudioEnabled()
- تسجيل أداة استماع لتلقّي أحداث تسجيلات الفيديو
مع
start(Executor, Consumer<VideoRecordEvent>)
. - السماح بتسجيل التسجيل باستمرار أثناء إرفاقه بـ VideoCapture
بالعودة إلى كاميرا أخرى، باستخدام
PendingRecording.asPersistentRecording()
لبدء التسجيل، اتصل برقم PendingRecording.start()
. تقوم كاميرا X بتحويل
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
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)); } VideoCaptureR<ecorder >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، يمكنك الاطلاع على الموارد الإضافية التالية:
- بدء استخدام الدرس التطبيقي حول ترميز الكاميراX
- نموذج تطبيق CameraX الرسمي
- قائمة أحدث واجهة برمجة التطبيقات لـ CameraX Video Capture
- ملاحظات إصدار CameraX
- رمز المصدر CameraX