أخبار المنتجات

إطلاق الإصدار 1.5 من CameraX: تسجيل فيديوهات قوي وإمكانات التقاط صور احترافية

قراءة لمدة 7 دقائق
Scott Nien
Software Engineer

يسرّ فريق CameraX الإعلان عن طرح الإصدار 1.5. يركّز هذا التحديث الأخير على توفير إمكانات احترافية بين يديك مع تسهيل عملية ضبط إعدادات جلسة الكاميرا أكثر من أي وقت مضى.

بالنسبة إلى تسجيل الفيديو، يمكن للمستخدمين الآن تسجيل فيديوهات مذهلة بالحركة البطيئة أو بمعدل لقطات مرتفع بسهولة. والأهم من ذلك، تتيح لك Feature Group API الجديدة تفعيل مجموعات معقّدة مثل HDR بمعدل 10 بت و60 لقطة في الثانية بثقة، ما يضمن الحصول على نتائج متّسقة على جميع الأجهزة المتوافقة.

في ما يتعلق بالتقاط الصور، يمكنك الاستفادة من أقصى قدر من المرونة من خلال إمكانية التقاط ملفات DNG (RAW) غير معالَجة وغير مضغوطة. بالإضافة إلى ذلك، يمكنك الآن الاستفادة من دقة HDR فائقة حتى عند استخدام "إضافات الكاميرا" القوية.

تستند هذه الميزات إلى SessionConfig API الجديدة التي تسهّل عملية إعداد الكاميرا وإعادة ضبطها. لنستعرض الآن تفاصيل هذه الميزات الجديدة الرائعة.

تسجيل فيديو فعّال: سرعة عالية ومجموعات من الميزات

توسّع الإصدار 1.5 من CameraX بشكل كبير إمكانات تسجيل الفيديو، ما يتيح تجارب تسجيل أكثر إبداعًا وقوة.

فيديو التصوير البطيء ومعدّل اللقطات المرتفع في الثانية

أصبحت الآن ميزة "الفيديو بالتقاط بطيء" متاحة، وهي إحدى الميزات الأكثر انتظارًا. يمكنك الآن تسجيل فيديو عالي السرعة (مثل 120 أو 240 لقطة في الثانية) وترميزه مباشرةً في فيديو بطيء الحركة. يمكنك بدلاً من ذلك التسجيل بعدد اللقطات المرتفع نفسه في الثانية لإنتاج فيديو سلس للغاية.

يمكن تنفيذ ذلك بسهولة إذا كنت على دراية بواجهة برمجة التطبيقات VideoCapture.

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 والتكبير/التصغير الفائق. 

تتيح واجهة برمجة التطبيقات لمجموعات الميزات حالتَي استخدام أساسيتَين:

حالة الاستخدام 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 تفعيل الميزات بهذا الترتيب:

  1. ‫HDR + 60 لقطة في الثانية + تثبيت المعاينة
  2. النطاق الديناميكي العالي + 60 لقطة في الثانية
  3. تثبيت حركة الفيديو أثناء المعاينة باستخدام تقنية HDR
  4. نطاق عالي الديناميكية
  5. ‫60 لقطة في الثانية + تثبيت المعاينة
  6. 60 لقطة في الثانية
  7. تثبيت المعاينة
  8. بدون

حالة الاستخدام 2: إنشاء واجهة مستخدم للإعدادات

يمكنك الآن توضيح مجموعات الميزات المتوافقة في واجهة مستخدم إعدادات تطبيقك، وإيقاف أزرار التبديل للخيارات غير المتوافقة، كما هو موضّح في الصورة أدناه. 

unsupported-features-disabled.gif

لتحديد ما إذا كان يجب إيقاف زر التبديل، استخدِم الرموز التالية للتحقّق من إمكانية استخدام مجموعة من الميزات. في البداية، استعلم عن حالة كل ميزة على حدة. بعد تفعيل إحدى الميزات، أعِد طلب الميزات المتبقية مع الميزات المفعّلة لمعرفة ما إذا كان يجب الآن إيقافها بسبب قيود التوافق.

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
 }
}

يُرجى الرجوع إلى منشور مدونة "مجموعة الميزات" للحصول على مزيد من المعلومات. 

تحسينات إضافية على الفيديو

  • تحسينات على استخدام الكاميرا بشكل متزامن: باستخدام CameraX 1.5.1، يمكنك الآن ربط حالات استخدام "المعاينة" و"التقاط الصور" و"التقاط الفيديو" بشكل متزامن لكل 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. تعمل هذه الواجهة على مركزية الإعدادات وتبسّط واجهة برمجة التطبيقات بطريقتَين أساسيتَين:

  1. لا حاجة إلى إجراء عمليات استدعاء unbind() يدويًا: تتوافق واجهات برمجة التطبيقات في CameraX مع مراحل النشاط. سيتم تلقائيًا "إلغاء ربط" حالات الاستخدام عند إيقاف النشاط أو LifecycleOwner الأخرى. ومع ذلك، يتطلّب تعديل حالات الاستخدام أو تبديل الكاميرات الاتصال بـ unbind() أو unbindAll() قبل إعادة الربط. باستخدام CameraX 1.5، عند ربط SessionConfig جديد، تعمل CameraX على تعديل الجلسة بسلاسة، ما يلغي الحاجة إلى طلبات إلغاء الربط.
  2. التحكّم الحتمي في عدد اللقطات في الثانية: تقدّم واجهة برمجة التطبيقات SessionConfig الجديدة طريقة حتمية لإدارة عدد اللقطات في الثانية. على عكس setTargetFrameRate السابق الذي كان مجرد تلميح، تضمن هذه الطريقة الجديدة تطبيق نطاق عدد اللقطات في الثانية المحدّد عند إعدادها بنجاح. لضمان الدقة، يجب طلب معدّلات اللقطات المتوافقة باستخدام CameraInfo.getSupportedFrameRateRanges(SessionConfig). من خلال تمرير SessionConfig الكامل، يمكن لـ CameraX تحديد النطاقات المتوافقة بدقة استنادًا إلى إعدادات البث.

أصبحت مكتبة Camera-Compose ثابتة الآن

نعلم مدى إعجابك بإطار عمل Jetpack Compose، ويسرّنا الإعلان عن أنّ مكتبة camera-compose أصبحت الآن إصدارًا ثابتًا 1.5.1! يتضمّن هذا الإصدار إصلاحات لأخطاء فادحة متعلّقة باستخدام CameraXViewfinder مع ميزات Compose، مثل moveableContentOf وPager، بالإضافة إلى حلّ مشكلة تمديد المعاينة. سنواصل إضافة المزيد من الميزات إلى camera-compose في الإصدارات المستقبلية.

تحسينات على "تحليل الصور" و"التحكّم بالكاميرا"

  • تعديل قوة المصباح اليدوي: يمكنك التحكّم بدقة في المصباح اليدوي للجهاز باستخدام واجهات برمجة التطبيقات الجديدة. يمكنك طلب الحد الأقصى لمستوى الإضاءة المتوافق باستخدام 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 أو تقديم تقرير خطأ:

متابعة القراءة