חדשות על מוצרים

השקת CameraX 1.5: הקלטת וידאו מתקדמת וצילום תמונות ברמה מקצועית

משך הקריאה: 7 דקות
Scott Nien
מהנדס תוכנה

צוות CameraX שמח להודיע על השקת גרסה 1.5! העדכון האחרון הזה מתמקד בהנגשת יכולות ברמה מקצועית, ובהקלה על הגדרת סשן המצלמה יותר מאי פעם.

בנוגע להקלטת סרטונים, המשתמשים יכולים עכשיו לצלם בקלות סרטונים מדהימים בהילוך איטי או עם קצב פריימים גבוה. חשוב מכך, Feature Group API החדש מאפשר לכם להפעיל בביטחון שילובים מורכבים כמו 10-bit HDR ו-60 FPS, וכך להבטיח תוצאות עקביות במכשירים נתמכים.

בנושא צילום תמונות, אתם נהנים מגמישות מקסימלית עם תמיכה בצילום קובצי DNG (RAW) לא מעובדים ולא דחוסים. בנוסף, עכשיו אפשר להשתמש בפלט Ultra HDR גם כשמשתמשים בתוספי מצלמה מתקדמים.

בבסיס התכונות האלה עומד SessionConfig API החדש, שמפשט את ההגדרה וההגדרה מחדש של המצלמה. עכשיו נפרט על התכונות החדשות והמרגשות האלה.

צילום וידאו מתקדם: מהירות גבוהה ושילובים של תכונות

גרסה CameraX 1.5 מרחיבה באופן משמעותי את יכולות הווידאו שלה, ומאפשרת חוויות צילום יצירתיות וחזקות יותר.

סרטון בהילוך איטי ובקצב פריימים גבוה

אחת התכונות שהכי ציפינו להן, סרטון בהילוך איטי, זמינה עכשיו. עכשיו אפשר לצלם סרטון במהירות גבוהה (למשל, 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

ב-CameraX 1.5 אנחנו מציגים את Feature Group API, שמבטל את הצורך לנחש אם תכונות מסוימות תואמות. על סמך שאילתת השילוב של התכונות API ב-Android 15, אתם יכולים עכשיו להפעיל כמה תכונות יחד בביטחון, וליהנות מהפעלה יציבה של המצלמה. קבוצת התכונות תומכת כרגע ב: HDR (HLG),‏ 60 פריימים לשנייה, ייצוב תצוגה מקדימה ו-Ultra HDR. לדוגמה, אפשר להפעיל בו-זמנית את התכונות HDR,‏ ‎60 FPS וייצוב בתצוגה מקדימה בסדרות 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 מנסה להפעיל תכונות בסדר הזה:

  1. HDR + 60 FPS + Preview Stabilization
  2. ‫HDR + 60 פריימים לשנייה
  3. HDR + ייצוב בתצוגה המקדימה
  4. HDR
  5. ‫60 FPS + ייצוב בתצוגה המקדימה
  6. 60 FPS
  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, אפשר עכשיו לקשר תרחישי שימוש של Preview + ImageCapture + VideoCapture בו-זמנית לכל SingleCameraConfig במצב שאינו קומפוזיציה. בנוסף, במצב יצירה (אותם תרחישי שימוש עם CompositionSettings),  אפשר עכשיו להגדיר את CameraEffect שמוחל על תוצאת היצירה הסופית.
  • השתקה דינמית: עכשיו אפשר להתחיל הקלטה במצב מושתק באמצעות PendingRecording.withAudioEnabled(boolean initialMuted) ולאפשר למשתמש לבטל את ההשתקה בהמשך באמצעות Recording.mute(boolean muted).
  • שיפור הטיפול במצב של אחסון לא מספיק: עכשיו CameraX שולח את השגיאה VideoRecordEvent.Finalize.ERROR_INSUFFICIENT_STORAGE באופן מהימן, וכך האפליקציה יכולה לטפל בצורה חלקה במצבים של אחסון נמוך ולעדכן את המשתמש.
  • שיפור האיכות בסרטונים בתנאי תאורה חלשים: במכשירים נתמכים (כמו סדרת Pixel 10), אפשר להפעיל את CameraControl.enableLowLightBoostAsync כדי להגביר אוטומטית את הבהירות בתצוגה המקדימה ובשידורי הווידאו בסביבות חשוכות.

צילום תמונות ברמה מקצועית

‫CameraX 1.5 כולל שדרוגים משמעותיים ל-ImageCapture למפתחים שרוצים איכות וגמישות מקסימליות.

חופש יצירתי עם צילום בפורמט DNG ‏ (RAW)

כדי לאפשר שליטה מלאה בעיבוד התמונה, CameraX תומכת עכשיו בצילום בפורמט DNG‏ (RAW). כך תוכלו לגשת לנתוני התמונה שלא עברו עיבוד או דחיסה ישירות מחיישן המצלמה, ולערוך ולשנות את הצבעים ברמה מקצועית. ה-API תומך בצילום קובץ 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) {}
    }
)

‫Ultra HDR לתוספי מצלמה

אתם יכולים ליהנות מהיתרונות של שני העולמות: צילום חישובי מדהים באמצעות תוספים למצלמה (כמו מצב לילה) בשילוב עם צבעים מבריקים וטווח דינמי של Ultra 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()

שיפורים בממשק ה-API ובנוחות השימוש

דרך חדשה להגדרה: SessionConfig

כפי שאפשר לראות בדוגמאות שלמעלה, SessionConfig הוא מושג חדש ב-CameraX 1.5. הוא מרכז את ההגדרות ומפשט את ה-API בשתי דרכים עיקריות:

  1. אין יותר קריאות ידניות: ממשקי ה-API של CameraX מודעים למחזור החיים.unbind() הוא יבטל באופן מרומז את הקישור של תרחישי השימוש כשהפעילות או LifecycleOwner אחרים יושמדו. אבל כדי לעדכן תרחישי שימוש או להחליף מצלמות, עדיין צריך להתקשר אל unbind() או אל unbindAll() לפני הקישור מחדש. מעכשיו, ב-CameraX 1.5, כשמבצעים binding של SessionConfig חדש, המערכת מעדכנת את הסשן בצורה חלקה, כך שלא צריך לבצע קריאות unbind.
  2. שליטה דטרמיניסטית בקצב הפריימים: ב-SessionConfig API החדש יש דרך דטרמיניסטית לנהל את קצב הפריימים. בניגוד לשיטה הקודמת setTargetFrameRate, שהייתה רק רמז, השיטה החדשה הזו מבטיחה שטווח קצב הפריימים שצוין יוחל אחרי שההגדרה תתבצע בהצלחה. כדי לוודא שהתכונה תפעל בצורה מדויקת, צריך לשלוח שאילתה לגבי קצבי פריימים נתמכים באמצעות CameraInfo.getSupportedFrameRateRanges(SessionConfig). העברת SessionConfig מלאה מאפשרת ל-CameraX לקבוע במדויק את הטווחים הנתמכים על סמך הגדרות הזרם.

התכונה 'הצעות להרכבת תמונה' במצלמה יציבה עכשיו

אנחנו יודעים שאתם מאוד אוהבים את Jetpack Compose, ולכן אנחנו שמחים להודיע שספריית camera-compose יציבה עכשיו בגרסה 1.5.1! הגרסה הזו כוללת תיקוני באגים קריטיים שקשורים לשימוש ב-CameraXViewfinder עם תכונות של Compose כמו moveableContentOf ו-Pager, וגם פתרון לבעיה של מתיחת התצוגה המקדימה. נמשיך להוסיף תכונות נוספות ל-camera-compose בגרסאות עתידיות.

שיפורים ב-ImageAnalysis וב-CameraControl

  • התאמת עוצמת הפנס: ממשקי API חדשים מאפשרים שליטה מדויקת בפנס של המכשיר. אפשר לשלוח שאילתה לגבי עוצמת ההארה המקסימלית הנתמכת באמצעות CameraInfo.getMaxTorchStrengthLevel(), ואז להגדיר את הרמה הרצויה באמצעות CameraControl.setTorchStrengthLevel().
  • תמיכה ב-NV21 ב-ImageAnalysis: עכשיו אפשר לבקש את פורמט התמונה NV21 ישירות מ-ImageAnalysis, וכך לפשט את השילוב עם ספריות וממשקי API אחרים. כדי להפעיל את האפשרות הזו, צריך להשתמש בפקודה 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 או דיווח על באג:

נכתב על ידי:

להמשך הקריאה