מדריכים

צילום מהיר וסרטונים בהילוך איטי באמצעות CameraX 1.5

משך הקריאה: 6 דקות
Leo Huang
מהנדס תוכנה

תיעוד של פעולה מהירה בחדות הוא תכונה חשובה באפליקציות מצלמה מודרניות. האפקט הזה מושג באמצעות צילום במהירות גבוהה – תהליך של צילום פריימים בקצב של 120 או 240 פריימים לשנייה. אפשר להשתמש בצילום הזה ברמת דיוק גבוהה לשתי מטרות שונות: ליצור סרטון עם קצב פריימים גבוה לניתוח מפורט של כל פריימים, או ליצור סרטון בהילוך איטי שבו הפעולה מתרחשת בצורה דרמטית על המסך.

בעבר, הטמעה של התכונות האלה באמצעות Camera2 API הייתה תהליך מעשי יותר. עכשיו, עם ה-API החדש למהירות גבוהה ב-CameraX 1.5, התהליך כולו פשוט יותר, ואתם יכולים ליצור סרטונים אמיתיים בקצב פריימים גבוה או קטעי וידאו בהילוך איטי שמוכנים להפעלה. בפוסט הזה נסביר איך לשלוט בשני סוגי המודעות. אם אתם חדשים ב-CameraX, תוכלו לקרוא את הסקירה הכללית על CameraX כדי להכיר את הנושא.


העיקרון שמאחורי הילוך איטי

העיקרון הבסיסי של הילוך איטי הוא צילום סרטון בקצב פריימים גבוה בהרבה מזה שבו הוא מוצג. לדוגמה, אם מקליטים אירוע של שנייה אחת ב-120 פריימים לשנייה (fps) ואז מפעילים את ההקלטה הזו ב-30 fps רגילים, הסרטון יפעל במשך ארבע שניות. ההארכה הזו של הזמן היא מה שיוצר את אפקט ההילוך האיטי הדרמטי, ומאפשר לכם לראות פרטים שמהירים מדי בשביל העין הבלתי מזוינת.

כדי שהסרטון הסופי יהיה חלק וזורם, בדרך כלל צריך לעבד אותו בקצב של 30 פריימים לשנייה לפחות. כלומר, כדי ליצור סרטון בהילוך איטי פי 4, קצב הפריימים המקורי של הצילום צריך להיות לפחות 120fps (120fps של צילום חלקי 4 = 30fps של הפעלה).

אחרי שמצלמים את הצילומים בקצב פריימים גבוה, יש שתי דרכים עיקריות להשיג את התוצאה הרצויה:

  • הילוך איטי שמופעל על ידי הנגן (סרטון עם קצב פריימים גבוה): הצילום במהירות גבוהה (למשל, 120fps) נשמר ישירות כקובץ סרטון עם קצב פריימים גבוה. אחרי כן, נגן הווידאו מאט את מהירות ההפעלה. כך המשתמש יכול לעבור בקלות בין הפעלה רגילה להפעלה בהילוך איטי.
  • הילוך איטי מוכן להפעלה (סרטון שעבר קידוד מחדש): זרם הווידאו המהיר עובר עיבוד וקידוד מחדש לקובץ עם קצב פריימים רגיל (למשל, ‎30 fps). האפקט של ההילוך האיטי מוטמע על ידי שינוי חותמות הזמן של הפריים. הסרטון שיתקבל יופעל בהילוך איטי בכל נגן וידאו רגיל ללא צורך בטיפול מיוחד. הסרטון מופעל בהילוך איטי כברירת מחדל, אבל נגני וידאו עדיין יכולים לספק כפתורים לשינוי מהירות ההפעלה, שיאפשרו למשתמש להגביר את המהירות ולצפות בסרטון במהירות המקורית שלו.

‫CameraX API מפשט את התהליך הזה ומאפשר לכם לבחור את הגישה הרצויה בצורה אחידה, כמו שמוסבר בהמשך.


ה-API החדש של סרטונים מהירים

הפתרון החדש של CameraX מבוסס על שני רכיבים עיקריים:

  • Recorder#getHighSpeedVideoCapabilities(CameraInfo): השיטה הזו מאפשרת לבדוק אם המצלמה יכולה להקליט במהירות גבוהה, ואם כן, אילו רזולוציות (אובייקטים של Quality) נתמכות.
  • HighSpeedVideoSessionConfig: זהו אובייקט הגדרה מיוחד שמקבץ את תרחישי השימוש של VideoCapture ושל Preview, ומורה ל-CameraX ליצור סשן מאוחד של מצלמה מהירה. שימו לב: הסטרימינג של VideoCapture יפעל בקצב הפריימים הגבוה שהוגדר, אבל הסטרימינג של Preview בדרך כלל יוגבל לקצב רגיל של לפחות 30 FPS על ידי מערכת המצלמה, כדי להבטיח תצוגה חלקה במסך.

תחילת העבודה

לפני שמתחילים, מוסיפים את יחסי התלות הדרושים של CameraX לקובץ build.gradle.kts של האפליקציה. תצטרכו את ארטיפקט camera-video יחד עם ספריות הליבה של CameraX.

// build.gradle.kts (Module: app)

dependencies {

    val camerax_version = "1.5.1"


    implementation("androidx.camera:camera-core:$camerax_version")

    implementation("androidx.camera:camera-camera2:$camerax_version")

    implementation("androidx.camera:camera-lifecycle:$camerax_version")

    implementation("androidx.camera:camera-video:$camerax_version")

    implementation("androidx.camera:camera-view:$camerax_version")

}

הערה לגבי ממשקי API ניסיוניים

חשוב לציין שכרגע ממשקי ה-API להקלטה במהירות גבוהה הם ניסיוניים. כלומר, הם עשויים להשתנות בגרסאות עתידיות. כדי להשתמש בהם, צריך להוסיף את ההערה הבאה לקוד:

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

הטמעה

ההטמעה של שני התרחישים מתחילה באותם שלבי הגדרה. ההחלטה אם ליצור סרטון עם קצב פריימים גבוה או סרטון בהילוך איטי מסתכמת בהגדרה אחת.

1. הגדרת צילום במהירות גבוהה

קודם כול, לא משנה מה היעד שלכם, אתם צריכים לקבל את ProcessCameraProvider, לבדוק את היכולות של המכשיר וליצור את תרחישי השימוש.

בלוק הקוד הבא מציג את תהליך ההגדרה המלא בתוך פונקציית השהיה. אפשר להפעיל את הפונקציה הזו מההקשר של שגרת המשך (coroutine), כמו lifecycleScope.launch.

// Add the OptIn annotation at the top of your function or class

@kotlin.OptIn(ExperimentalSessionConfig::class, ExperimentalHighSpeedVideo::class)

private suspend fun setupCamera() {

    // Asynchronously get the CameraProvider

    val cameraProvider = ProcessCameraProvider.awaitInstance(this)



    // -- CHECK CAPABILITIES --

    val cameraInfo = cameraProvider.getCameraInfo(CameraSelector.DEFAULT_BACK_CAMERA)

    val videoCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo)

    if (videoCapabilities == null) {

        // This camera device does not support high-speed video.

        return

    }




    // -- CREATE USE CASES --

    val preview = Preview.Builder().build()    


    // You can create a Recorder with default settings.

    // CameraX will automatically select a suitable quality.

    val recorder = Recorder.Builder().build()


    // Alternatively, to use a specific resolution, you can configure the
    // Recorder with a QualitySelector. This is useful if your app has
    // specific resolution requirements or you want to offer user
    // preferences. 

    // To use a specific quality, you can uncomment the following lines.

    // Get the list of qualities supported for high-speed video. 

    // val supportedQualities = videoCapabilities.getSupportedQualities(DynamicRange.SDR)

    // Build the Recorder using the quality from the supported list.

    // val recorderWithQuality = Recorder.Builder()

    //     .setQualitySelector(QualitySelector.from(supportedQualities.first()))

    //     .build()



    // Create the VideoCapture use case, using either recorder or recorderWithQuality

    val videoCapture = VideoCapture.withOutput(recorder)

    // Now you are ready to configure the session for your desired output...

}

2. בחירת הפלט

עכשיו מחליטים איזה סוג של סרטון רוצים ליצור. הקוד הזה יפעל בתוך הפונקציה setupCamera() suspend שמוצגת למעלה.

אפשרות א': יצירת סרטון עם קצב פריימים גבוה

בוחרים באפשרות הזו אם רוצים שהקובץ הסופי יהיה עם קצב פריימים גבוה (למשל, סרטון עם 120 פריימים לשנייה).

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)


// Query and apply a supported frame rate. Common supported frame rates include 120 and 240 fps.

val supportedFrameRateRanges =

    cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())


sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

אפשרות ב': יצירת סרטון בהילוך איטי שמוכן להפעלה

מומלץ לבחור באפשרות הזו אם רוצים שסרטון יופעל אוטומטית בהילוך איטי בכל נגן וידאו רגיל.

// Create a builder for the high-speed session

val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture)

    .setPreview(preview)



// This is the key: enable automatic slow-motion!

sessionConfigBuilder.setSlowMotionEnabled(true)



// Query and apply a supported frame rate. Common supported frame rates include 120, 240, and 480 fps.

val supportedFrameRateRanges =

   cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build())

sessionConfigBuilder.setFrameRateRange(supportedFrameRateRanges.first())

הדגל הזה הוא המפתח ליצירת סרטון בהילוך איטי שמוכן להפעלה. אם הערך של setSlowMotionEnabled הוא true, ‏ CameraX מעבד את הזרם המהיר ושומר אותו כקובץ וידאו רגיל של 30fps. מהירות ההילוך האיטי נקבעת לפי היחס בין קצב הפריימים של הצילום לבין קצב הפריימים הסטנדרטי של ההפעלה.

לדוגמה:

  • הקלטה ב-120fps תיצור סרטון שיופעל במהירות של ‎1/4x (120 ÷ 30 = 4).
  • צילום ב-240fps ייצור סרטון שיופעל ב-1/8 מהמהירות (240 ÷ 30 = 8).

סיכום: הקלטת הסרטון

אחרי שמגדירים את HighSpeedVideoSessionConfig ומקשרים אותו למחזור החיים, השלב האחרון הוא להתחיל את ההקלטה. התהליך של הכנת אפשרויות הפלט, התחלת ההקלטה וטיפול באירועי וידאו זהה לתהליך של צילום וידאו רגיל.

הפוסט הזה מתמקד בהגדרה של מהירות גבוהה, ולכן לא נסביר בפירוט על תהליך ההקלטה. לקבלת מדריך מקיף בנושאים שונים, החל מהכנת אובייקט FileOutputOptions או MediaStoreOutputOptions ועד לטיפול בקריאות החוזרות (callback) של VideoRecordEvent, אפשר לעיין במסמכי התיעוד של VideoCapture.

// Bind the session config to the lifecycle

cameraProvider.bindToLifecycle(

    this as LifecycleOwner,

    CameraSelector.DEFAULT_BACK_CAMERA,

    sessionConfigBuilder.build() // Bind the config object from Option A or B

)



// Start the recording using the VideoCapture use case

val recording = videoCapture.output

    .prepareRecording(context, outputOptions) // See docs for creating outputOptions

    .start(ContextCompat.getMainExecutor(context)) { recordEvent ->

        // Handle recording events (e.g., Start, Pause, Finalize)

    }

תמיכה בסרטונים בהילוך איטי ב-Google Photos

כשמפעילים את setSlowMotionEnabled(true) ב-CameraX, קובץ הווידאו שנוצר מיועד להיות מזוהה וניתן להפעלה באופן מיידי כהילוך איטי בנגני וידאו רגילים ובאפליקציות גלריה. ב-Google Photos יש פונקציונליות משופרת לסרטונים בהילוך איטי, אם קצב הפריימים בצילום הוא 120,‏ 240,‏ 360,‏ 480 או 960fps:

  • זיהוי ממשק משתמש ייחודי בתמונה הממוזערת: בספרייה ב-Google Photos, אפשר לזהות סרטונים בהילוך איטי לפי רכיבים ספציפיים בממשק המשתמש, שמבדילים אותם מסרטונים רגילים.
normal.png
slowmotion.png
תמונה ממוזערת של סרטון רגילתמונה ממוזערת של סרטון בהילוך איטי
  • קטעים עם מהירות מתכווננת במהלך ההפעלה: כשמפעילים סרטון בהילוך איטי, Google Photos מספקת אמצעי בקרה לשינוי המהירות של חלקים שונים בסרטון. כך המשתמשים יכולים להחליט אילו חלקים יופעלו בהילוך איטי ואילו יופעלו במהירות רגילה, ולקבל שליטה יצירתית. אחרי העריכה, אפשר לייצא את הסרטון כקובץ סרטון חדש באמצעות הלחצן שיתוף, והקטעים שהוגדרו בהילוך איטי יישמרו.
normal2.png
slowmotion2.png
הפעלה רגילה של סרטוניםהפעלה של סרטונים בהילוך איטי 
עם אמצעי בקרה לעריכה 

הערה לגבי תמיכה במכשיר

‫API המהירות הגבוהה של CameraX מסתמך על מערכת CamcorderProfile הבסיסית של Android כדי לקבוע אילו רזולוציות וקצבי פריימים במהירות גבוהה נתמכים במכשיר. פרופילי מצלמת הווידאו מאומתים על ידי חבילת בדיקות התאימות (CTS) של Android, כך שאתם יכולים להיות בטוחים ביכולות צילום הווידאו שמדווחות על ידי המכשיר.

כלומר, היכולת של מכשיר להקליט סרטון בהילוך איטי באמצעות אפליקציית המצלמה המובנית שלו לא מבטיחה ש-CameraX API למהירות גבוהה יפעל. הפער הזה נוצר כי יצרני המכשירים אחראים לאכלוס הערכים של CamcorderProfile בקושחה של המכשיר, ולפעמים לא נכללים פרופילים נחוצים של מהירות גבוהה כמו CamcorderProfile.QUALITY_HIGH_SPEED_1080P ו-CamcorderProfile.QUALITY_HIGH_SPEED_720P. אם הפרופילים האלה חסרים, Recorder.getHighSpeedVideoCapabilities() יחזיר null.

לכן, חשוב להשתמש תמיד ב-Recorder.getHighSpeedVideoCapabilities() כדי לבדוק באופן פרוגרמטי אם התכונות נתמכות, כי זו הדרך הכי אמינה להבטיח חוויה עקבית במכשירים שונים. אם תנסו לקשור HighSpeedVideoSessionConfig במכשיר שבו Recorder.getHighSpeedVideoCapabilities() מחזיר ערך null, הפעולה תיכשל עם IllegalArgumentException. אפשר לוודא שיש תמיכה במכשירי Google Pixel, כי הם תמיד כוללים את פרופילי המהירות הגבוהה האלה. בנוסף, מכשירים שונים של יצרנים אחרים, כמו Motorola Edge 30,‏ OPPO Find N2 Flip ו-Sony Xperia 1 V, תומכים גם הם ביכולות של צילום וידאו במהירות גבוהה.


סיכום

ממשק ה-API של CameraX לצילום סרטונים במהירות גבוהה הוא גם עוצמתי וגם גמיש. אם אתם צריכים צילומים אמיתיים בקצב פריימים גבוה לניתוח טכני, או שאתם רוצים להוסיף לאפליקציה שלכם אפקטים של הילוך איטי קולנועי, HighSpeedVideoSessionConfig מספק פתרון פשוט ומאוחד. הבנה של התפקיד של הדגל setSlowMotionEnabled מאפשרת לתמוך בקלות בשני תרחישי השימוש ולתת למשתמשים יותר שליטה יצירתית.

נכתב על ידי:

להמשך הקריאה