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

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

ההטמעה פשוטה אם אתם מכירים את API‏ 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, שמבטל את הצורך לנחש אם תכונות מסוימות תואמות. על סמך ה-API של שאילתת שילוב התכונות של Android 15, אתם יכולים עכשיו להפעיל כמה תכונות יחד בביטחון, ולהבטיח הפעלה יציבה של המצלמה. נכון לעכשיו, קבוצת התכונות תומכת ב: HDR (HLG),‏ 60fps, ‏ ייצוב תצוגה מקדימה ו-Ultra HDR. לדוגמה, אפשר להפעיל בו-זמנית את ההגדרות HDR,‏ 60fps וייצוב התצוגה המקדימה בסדרות Pixel 10 ו-Galaxy S25. אנחנו מתכננים להוסיף בעתיד שיפורים נוספים, כולל הקלטה באיכות 4K וזום רחב במיוחד. 

ממשק ה-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 + ייצוב בתצוגה המקדימה
  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/25.

// 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. שליטה דטרמיניסטית בקצב הפריימים: ה-API החדש‏ SessionConfig מציג דרך דטרמיניסטית לניהול קצב הפריימים. בניגוד ל-setTargetFrameRate הקודם, שהיה רק רמז, השיטה החדשה הזו מבטיחה שטווח קצב הפריימים שצוין יוחל אחרי שההגדרה תתבצע בהצלחה. כדי לוודא שהתכונה תפעל בצורה מדויקת, צריך לשלוח שאילתה לגבי קצבי פריימים נתמכים באמצעות CameraInfo.getSupportedFrameRateRanges(SessionConfig). על ידי העברת SessionConfig מלא, CameraX יכול לקבוע במדויק את הטווחים הנתמכים על סמך הגדרות הזרם.

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

אנחנו יודעים שאתם מאוד אוהבים את Jetpack פיתוח נייטיב, ולכן אנחנו שמחים להודיע שספריית 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 או דיווח על באג:

נכתב על ידי:

להמשך הקריאה