نقدّم لكم CameraX 1.5: تسجيل فيديوهات فعّال والتقاط صور احترافي
مدّة القراءة: 7 دقائق
يسرّ فريق CameraX الإعلان عن إصدار النسخة 1.5. يركّز هذا التحديث الأخير على توفير إمكانات احترافية بين أيديكم، مع تسهيل إعداد جلسة الكاميرا أكثر من أي وقت مضى.
بالنسبة إلى تسجيل الفيديوهات، يمكن للمستخدمين الآن تسجيل فيديوهات مذهلة بالحركة البطيئة أو بمعدّل إطارات مرتفع بدون عناء. والأهم من ذلك، تتيح لكم واجهة برمجة التطبيقات الجديدة Feature Group API تفعيل مجموعات معقّدة من الميزات بثقة، مثل النطاق العالي الديناميكية (HDR) بمعدّل 10 بت و60 لقطة في الثانية، ما يضمن الحصول على نتائج متّسقة على الأجهزة المتوافقة.
في ما يتعلق بالتقاط الصور ، يمكنكم الاستفادة من أقصى قدر من المرونة من خلال إمكانية التقاط ملفات DNG (RAW) غير معالَجة وغير مضغوطة. بالإضافة إلى ذلك، يمكنكم الآن الاستفادة من إخراج دقة HDR الفائقة حتى عند استخدام "إضافات الكاميرا" القوية.
تستند هذه الميزات إلى واجهة برمجة التطبيقات SessionConfig API الجديدة التي تُبسّط عملية إعداد الكاميرا وإعادة ضبطها. لننتقل الآن إلى تفاصيل هذه الميزات الجديدة الرائعة.
تسجيل فيديوهات فعّال: سرعة عالية ومجموعات من الميزات
توسّع النسخة 1.5 من CameraX إمكانات تسجيل الفيديوهات بشكلٍ كبير، ما يتيح تجارب تسجيل أكثر إبداعًا وقوة.
فيديو الحركة البطيئة والفيديو بمعدّل إطارات مرتفع
تتوفّر الآن ميزة فيديو الحركة البطيئة التي كنّا ننتظرها بفارغ الصبر. يمكنكم الآن تسجيل فيديوهات عالية السرعة (مثل 120 أو 240 لقطة في الثانية) وتشفيرها مباشرةً في فيديو مذهل بالحركة البطيئة. بدلاً من ذلك، يمكنكم التسجيل بمعدّل الإطارات المرتفع نفسه لإنتاج فيديو سلس للغاية.
إنّ تنفيذ هذه الميزة بسيط إذا كنتم على دراية بواجهة برمجة التطبيقات VideoCapture API.
1. التحقّق من إمكانية استخدام السرعة العالية: استخدِموا الطريقة الجديدة Recorder.getHighSpeedVideoCapabilities() للاستعلام عمّا إذا كان الجهاز يتيح استخدام هذه الميزة.
val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)
val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)
if (highSpeedCapabilities == null) {
// This camera device does not support high-speed video.
return
}2. ضبط حالة الاستخدام وربطها: استخدِموا videoCapabilities التي تم عرضها (والتي تحتوي على معلومات عن جودة الفيديو المتوافقة) لإنشاء HighSpeedVideoSessionConfig. بعد ذلك، يجب الاستعلام عن نطاقات عدد اللقطات في الثانية المتوافقة من خلال cameraInfo.getSupportedFrameRateRanges() وضبط النطاق المطلوب. استدعوا setSlowMotionEnabled(true) لتسجيل فيديوهات بالتصوير البطيء، وإلا سيتم تسجيل فيديوهات بمعدّل إطارات مرتفع. الخطوة الأخيرة هي استخدام Recorder.prepareRecording().start() العادية لبدء تسجيل الفيديو.
val preview = Preview.Builder().build()
val quality = highSpeedCapabilities
.getSupportedQualities(DynamicRange.SDR).first()
val recorder = Recorder.Builder()
.setQualitySelector(QualitySelector.from(quality)))
.build()
val videoCapture = VideoCapture.withOutput(recorder)
val frameRateRange = cameraInfo.getSupportedFrameRateRanges(
HighSpeedVideoSessionConfig(videoCapture, preview)
).first()
val sessionConfig = HighSpeedVideoSessionConfig(
videoCapture,
preview,
frameRateRange = frameRateRange,
// Set true for slow-motion playback, or false for high-frame-rate
isSlowMotionEnabled = true
)
cameraProvider.bindToLifecycle(
lifecycleOwner, cameraSelector, sessionConfig)
// Start recording slow motion videos.
val recording = recorder.prepareRecording(context, outputOption)
.start(executor, {})التوافق والقيود
يتطلّب التسجيل عالي السرعة توفّر دعم معيّن لـ CameraConstrainedHighSpeedCaptureSession وCamcorderProfile. يجب دائمًا إجراء عملية التحقّق من الإمكانات، وتفعيل التسجيل عالي السرعة على الأجهزة المتوافقة فقط لمنع تجربة المستخدم السيئة. تتوفّر هذه الميزة حاليًا على الكاميرات الخلفية في جميع أجهزة Pixel تقريبًا ونماذج معيّنة من جهات تصنيع أخرى.
يمكنكم الاطّلاع على منشور المدوّنة لمزيد من التفاصيل.
الجمع بين الميزات بثقة: واجهة برمجة التطبيقات Feature Group API
تقدّم النسخة 1.5 من CameraX واجهة برمجة التطبيقات Feature Group API التي تزيل التخمينات بشأن توافق الميزات. استنادًا إلى واجهة برمجة التطبيقات للاستعلام عن مجموعات الميزات في Android 15، يمكنكم الآن تفعيل ميزات متعددة معًا بثقة، ما يضمن توفير جلسة كاميرا مستقرة. تتضمّن مجموعة الميزات حاليًا: النطاق العالي الديناميكية (HLG) و60 لقطة في الثانية و"تثبيت المعاينة" ودقة HDR الفائقة. على سبيل المثال، يمكنكم تفعيل النطاق العالي الديناميكية و60 لقطة في الثانية و"تثبيت المعاينة" في الوقت نفسه على سلسلتي Pixel 10 وGalaxy S25. من المخطط إجراء تحسينات مستقبلية لتضمين التسجيل بدقة 4K والتكبير/التصغير بزاوية فائقة الاتساع.
تتيح واجهة برمجة التطبيقات Feature Group API حالتَي استخدام أساسيتَين:
حالة الاستخدام 1: منح الأولوية لأفضل جودة
إذا أردتم التقاط الصور باستخدام أفضل مجموعة ممكنة من الميزات، يمكنكم تقديم قائمة مرتّبة حسب الأولوية. سيحاول CameraX تفعيلها بالترتيب، واختيار المجموعة الأولى التي يتيحها الجهاز بالكامل.
val sessionConfig = SessionConfig(
useCases = listOf(preview, videoCapture),
preferredFeatureGroup = listOf(
GroupableFeature.HDR_HLG10,
GroupableFeature.FPS_60,
GroupableFeature.PREVIEW_STABILIZATION
)
).apply {
// (Optional) Get a callback with the enabled features to update your UI.
setFeatureSelectionListener { selectedFeatures ->
updateUiIndicators(selectedFeatures)
}
}
processCameraProvider.bindToLifecycle(activity, cameraSelector, sessionConfig)في هذا المثال، يحاول CameraX تفعيل الميزات بهذا الترتيب:
- النطاق العالي الديناميكية + 60 لقطة في الثانية + "تثبيت المعاينة"
- النطاق العالي الديناميكية + 60 لقطة في الثانية
- النطاق العالي الديناميكية + "تثبيت المعاينة"
- النطاق العالي الديناميكية
- 60 لقطة في الثانية + "تثبيت المعاينة"
- 60 لقطة في الثانية
- "تثبيت المعاينة"
- بدون
حالة الاستخدام 2: إنشاء واجهة مستخدم للإعدادات يمكن للمستخدمين التفاعل معها
يمكنكم الآن عرض مجموعات الميزات المتوافقة بدقة في واجهة مستخدم الإعدادات في تطبيقكم، وإيقاف أزرار التبديل للخيارات غير المتوافقة، مثل الصورة أدناه.
لتحديد ما إذا كان يجب تعتيم زر التبديل، استخدِموا الرموز التالية للتحقّق من إمكانية استخدام مجموعة الميزات. في البداية، استعلموا عن حالة كل ميزة فردية. بعد تفعيل ميزة، أعيدوا الاستعلام عن الميزات المتبقية باستخدام الميزات المفعّلة لمعرفة ما إذا كان يجب تعتيم أزرار التبديل الخاصة بها الآن بسبب قيود التوافق.
fun disableFeatureIfNotSuported(
enabledFeatures: Set<GroupableFeature>,
featureToCheck:GroupableFeature
) {
val sessionConfig = SessionConfig(
useCases = useCases,
requiredFeatureGroup = enabledFeatures + featureToCheck
)
val isSupported = cameraInfo.isFeatureGroupSupported(sessionConfig)
if (!isSupported) {
// disable the toggle for featureToCheck
}
}يُرجى الرجوع إلى منشور المدوّنة Feature Group لمزيد من المعلومات.
تحسينات إضافية على الفيديو
- تحسينات على الكاميرا المتزامنة: باستخدام CameraX 1.5.1، يمكنكم الآن ربط حالات استخدام "المعاينة" وImageCapture وVideoCapture في الوقت نفسه لكل SingleCameraConfig في وضع عدم التركيب. بالإضافة إلى ذلك، في وضع التركيب (حالات الاستخدام نفسها مع CompositionSettings)، يمكنكم الآن ضبط
CameraEffectالذي يتم تطبيقه على نتيجة التركيب النهائية. - كتم الصوت ديناميكيًا: يمكنكم الآن بدء التسجيل في حالة كتم الصوت باستخدام
PendingRecording.withAudioEnabled(boolean initialMuted)والسماح للمستخدم بإلغاء كتم الصوت لاحقًا باستخدامRecording.mute(boolean muted). - معالجة محسّنة لمشكلة عدم توفّر مساحة تخزين كافية: يرسل CameraX الآن بشكلٍ موثوق الخطأ
VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE، ما يسمح لتطبيقكم بمعالجة حالات انخفاض مساحة التخزين بشكلٍ سلس وإعلام المستخدم. - تحسين الإضاءة المنخفضة: على الأجهزة المتوافقة (مثل سلسلة Pixel 10)، يمكنكم تفعيل CameraControl.enableLowLightBoostAsync لتفتيح المعاينة وفيديوهات البث تلقائيًا في البيئات المظلمة.
التقاط صور احترافي
تقدّم النسخة 1.5 من CameraX ترقيات كبيرة إلى ImageCapture للمطوّرين الذين يطلبون أقصى قدر من الجودة والمرونة.
إطلاق العنان للتحكّم الإبداعي باستخدام ميزة التقاط صور بتنسيق DNG (RAW)
للحصول على تحكّم كامل في مرحلة ما بعد المعالجة، تتيح CameraX الآن التقاط الصور بتنسيق DNG (RAW). يمنحكم ذلك إمكانية الوصول إلى بيانات الصور غير المعالَجة وغير المضغوطة مباشرةً من مستشعر الكاميرا، ما يتيح إجراء عمليات تعديل وتصحيح ألوان احترافية. تتيح واجهة برمجة التطبيقات التقاط ملف DNG وحده، أو التقاط مخرجات JPEG وDNG في الوقت نفسه. يمكنكم الاطّلاع على نموذج الرمز أدناه لمعرفة كيفية التقاط ملفات JPEG وDNG في الوقت نفسه.
val capabilities = ImageCapture.getImageCaptureCapabilities(cameraInfo)
val imageCapture = ImageCapture.Builder().apply {
if (capabilities.supportedOutputFormats
.contains(OUTPUT_FORMAT_RAW_JPEG)) {
// Capture both RAW and JPEG formats.
setOutputFormat(OUTPUT_FORMAT_RAW_JPEG)
}
}.build()
// ... bind imageCapture to lifecycle ...
// Provide separate output options for each format.
val outputOptionRaw = /* ... configure for image/x-adobe-dng ... */
val outputOptionJpeg = /* ... configure for image/jpeg ... */
imageCapture.takePicture(
outputOptionRaw,
outputOptionJpeg,
executor,
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(results: OutputFileResults) {
// This callback is invoked twice: once for the RAW file
// and once for the JPEG file.
}
override fun onError(exception: ImageCaptureException) {}
}
)دقة HDR الفائقة لإضافات الكاميرا
يمكنكم الاستفادة من أفضل الميزات: التصوير الفوتوغرافي الحسابي المذهل لإضافات الكاميرا (مثل "الوضع الليلي") جنبًا إلى جنب مع الألوان الرائعة والنطاق الديناميكي لدقة HDR الفائقة. تتوفّر هذه الميزة الآن على العديد من هواتف Android المميّزة الحديثة، مثل سلسلتي Pixel 9/10 وSamsung S24/S25.
// Support UltraHDR when Extension is enabled.
val extensionsEnabledCameraSelector = extensionsManager
.getExtensionEnabledCameraSelector(
CameraSelector.DEFAULT_BACK_CAMERA, ExtensionMode.NIGHT)
val imageCapabilities = ImageCapture.getImageCaptureCapabilities(
cameraProvider.getCameraInfo(extensionsEnabledCameraSelector)
val imageCapture = ImageCapture.Builder()
.apply {
if (imageCapabilities.supportedOutputFormats
.contains(OUTPUT_FORMAT_JPEG_ULTRA_HDR) {
setOutputFormat(OUTPUT_FORMAT_JPEG_ULTRA_HDR)
}
}.build()تحسينات على واجهة برمجة التطبيقات الأساسية وسهولة الاستخدام
طريقة جديدة للضبط: SessionConfig
كما هو موضّح في الأمثلة أعلاه، SessionConfig هو مفهوم جديد في CameraX 1.5. تُركّز هذه الميزة عملية الضبط وتُبسّط واجهة برمجة التطبيقات بطريقتَين رئيسيتَين:
- لا حاجة إلى إجراء طلبات
unbind()يدويًا: تتوافق واجهات برمجة تطبيقات CameraX مع مراحل النشاط. ستؤدي إلى "إلغاء ربط" حالات الاستخدام ضمنيًا عند إيقاف النشاط أوLifecycleOwnerآخر. ولكن لا يزال عليكم استدعاءunbind()أوunbindAll()قبل إعادة الربط لتعديل حالات الاستخدام أو تبديل الكاميرات. باستخدام CameraX 1.5، عند ربطSessionConfigجديد، يحدّث CameraX الجلسة بسلاسة نيابةً عنكم، ما يزيل الحاجة إلى طلبات إلغاء الربط. - التحكّم في عدد اللقطات في الثانية بشكلٍ محدّد: تقدّم واجهة برمجة التطبيقات الجديدة
SessionConfigAPI طريقة محدّدة لإدارة عدد اللقطات في الثانية. على عكسsetTargetFrameRateالسابقة التي كانت مجرد إشارة، تضمن هذه الطريقة الجديدة تطبيق نطاق معدّل الإطارات المحدّد عند نجاح عملية الضبط. لضمان الدقة، يجب الاستعلام عن معدّلات الإطارات المتوافقة باستخدامCameraInfo.getSupportedFrameRateRanges(SessionConfig). من خلال تمريرSessionConfigالكامل، يمكن لـ CameraX تحديد النطاقات المتوافقة بدقة استنادًا إلى إعدادات البث.
أصبحت مكتبة Camera-Compose مستقرة الآن
نعرف مدى إعجابكم بـ Jetpack Compose، ويسرّنا أن نعلن أنّ camera-composeمكتبة أصبحت مستقرة الآن في الإصدار 1.5.1! يتضمّن هذا الإصدار إصلاحات مهمة للأخطاء المتعلقة باستخدام CameraXViewfinder مع ميزات Compose، مثل moveableContentOf وPager، بالإضافة إلى حلّ مشكلة تمدّد المعاينة. سنواصل إضافة المزيد من الميزات إلى camera-compose في الإصدارات المستقبلية.
تحسينات على ImageAnalysis وCameraControl
- ضبط قوة المصباح اليدوي: يمكنكم التحكّم بدقة في المصباح اليدوي للجهاز باستخدام واجهات برمجة التطبيقات الجديدة. يمكنكم الاستعلام عن الحد الأقصى للقوة المتوافقة باستخدام CameraInfo.getMaxTorchStrengthLevel()، ثم ضبط المستوى المطلوب باستخدام CameraControl.setTorchStrengthLevel().
- إمكانية استخدام تنسيق NV21 في
ImageAnalysis: يمكنكم الآن طلب تنسيق صورة NV21 مباشرةً منImageAnalysis، ما يُبسّط عملية التكامل مع المكتبات وواجهات برمجة التطبيقات الأخرى. يتم تفعيل ذلك من خلال استدعاءImageAnalysis.Builder.setOutputImageFormat(OUTPUT_IMAGE_FORMAT_NV21).
ابدأ اليوم
عدِّلوا التبعيات إلى CameraX 1.5 اليوم واستكشِفوا الميزات الجديدة الرائعة. نحن متشوّقون لرؤية ما ستنشئونه.
لاستخدام CameraX 1.5، يُرجى إضافة التبعيات التالية إلى libs.versions.toml. (ننصح باستخدام الإصدار 1.5.1 الذي يتضمّن العديد من إصلاحات الأخطاء المهمة والتحسينات على الكاميرا المتزامنة.)
[versions]
camerax = "1.5.1"
[libraries]
..
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "camerax" }
androidx-camera-compose = { module = "androidx.camera:camera-compose", version.ref = "camerax" }
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "camerax" }
androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "camerax" }
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camerax" }
androidx-camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "camerax" }بعد ذلك، أضيفوا هذه التبعيات إلى ملف build.gradle.kts الخاص بالوحدة:
dependencies {
..
implementation(libs.androidx.camera.core)
implementation(libs.androidx.camera.lifecycle)
implementation(libs.androidx.camera.camera2)
implementation(libs.androidx.camera.view) // for PreviewView
implementation(libs.androidx.camera.compose) // for compose UI
implementation(libs.androidx.camera.extensions) // For Extensions
}هل لديكم أسئلة أو تريدون التواصل مع فريق CameraX؟ انضموا إلى مجموعة مناقشة المطوّرين في CameraX أو أبلغوا عن خطأ:
-
أخبار المنتجاتإنّ توفير تجربة آمنة على الإنترنت وحماية المستخدمين من الأذى من أهم الأولويات في Google Play.
Paul Feng • مدّة القراءة: دقيقتان -
أخبار المنتجاتنحتفل اليوم رسميًا بمرور خمسة أعوام على إطلاق Jetpack Compose 1.0. من الإصدار 1.0 الذي تم الإعلان عنه في 28 يوليو 2021 إلى أحدث إصدار 1.11، شهدنا تطورًا كبيرًا في واجهات برمجة التطبيقات على مرّ السنين، ونحن نأخذ لحظة للاحتفال.
Rebecca Franks, Nick Butcher, Loryn Hairston • مدّة القراءة: 5 دقائق -
أخبار المنتجاتأصبح استوديو Android Quail 2 مستقرًا ومتاحًا لكم لاستخدامه في الإصدار العلني، ما يغيّر بيئة التطوير المتكاملة (IDE) من خلال سير عمل الوكيل المتزامن، وإمكانية إنشاء ملفات تعريف لتتبُّع تسرّب الذاكرة بشكلٍ مدمج، وإمكانية إصلاح الأعطال التي تراعي السياق.
Amman Asfaw • مدّة القراءة: 3 دقائق
يمكنكم تلقّي أحدث الإحصاءات حول تطوير تطبيقات Android في بريدكم الوارد أسبوعيًا.