מערכת צילום בדרך כלל מקליטה שידורי וידאו ואודיו, דוחסת אותם, משלבת את שני השידורים ואז כותבת את השידור שנוצר בדיסק.
ב-CameraX, הפתרון לצילום וידאו הוא תרחיש השימוש VideoCapture:
VideoCapture.כפי שמוצג באיור 2, צילום וידאו ב-CameraX כולל כמה רכיבים ארכיטקטוניים ברמה גבוהה:
SurfaceProviderלמקור הסרטון.AudioSourceלמקור האודיו.- שני מקודדים כדי לקודד ולדחוס וידאו/אודיו.
- ממקסר מדיה כדי למקסר את שני הסטרימים.
- כלי לשמירת קבצים כדי לכתוב את התוצאה.
VideoCapture API מסתיר את מנוע הצילום המורכב ומספק לאפליקציות API הרבה יותר פשוט וישיר.
סקירה כללית על VideoCapture API
VideoCapture הוא תרחיש לדוגמה של CameraX שפועל היטב בפני עצמו או בשילוב עם תרחישים אחרים לדוגמה. השילובים הספציפיים שנתמכים תלויים ביכולות החומרה של המצלמה, אבל Preview ו-VideoCapture הם שילוב תקין של תרחישי שימוש בכל המכשירים.
VideoCapture API מורכב מהאובייקטים הבאים שמתקשרים עם אפליקציות:
-
VideoCaptureהיא המחלקה ברמה העליונה של תרחיש השימוש. VideoCaptureנקשר ל-LifecycleOwnerעםCameraSelectorו-UseCases אחרים של CameraX. מידע נוסף על המושגים והשימושים האלה זמין במאמר ארכיטקטורת CameraX. -
Recorderהוא הטמעה של VideoOutput שמקושרת באופן הדוק ל-VideoCapture. Recorderמשמש לצילום הווידאו והקלטת האודיו. אפליקציה יוצרת הקלטות מ-Recorder. PendingRecordingמגדיר הקלטה, ומספק אפשרויות כמו הפעלת אודיו והגדרת רכיב event listener. כדי ליצורPendingRecording, צריך להשתמש ב-Recorder.PendingRecordingלא מקליט שום דבר.Recordingמבצע את ההקלטה בפועל. כדי ליצורRecording, צריך להשתמש ב-PendingRecording.
באיור 3 מוצגים הקשרים בין האובייקטים האלה:
מקרא:
- יצירת
RecorderעםQualitySelector. - מגדירים את
Recorderבאמצעות אחת מOutputOptions. - אם צריך, מפעילים את האודיו באמצעות
withAudioEnabled(). - כדי להתחיל להקליט, צריך להתקשר אל
start()עם מאזיןVideoRecordEvent. - אפשר להשתמש ב-
pause()/resume()/stop()ב-Recordingכדי לשלוט בהקלטה. - מגיבים ל-
VideoRecordEventsבתוך רכיב ה-event listener.
רשימת ה-API המפורטת נמצאת בקובץ current.txt בתוך קוד המקור.
שימוש ב-VideoCapture API
כדי לשלב את תרחיש השימוש VideoCapture של CameraX באפליקציה:
- כריכה של
VideoCapture. - מכינים ומגדירים את ההקלטה.
- הפעלה של הקלטת זמן הריצה ושליטה בה.
בקטעים הבאים מוסבר מה אפשר לעשות בכל שלב כדי לקבל סשן הקלטה מקצה לקצה.
קישור של VideoCapture
כדי לקשר את תרחיש השימוש VideoCapture:
- יוצרים אובייקט
Recorder. - יוצרים אובייקט
VideoCapture. - כבילה אל
Lifecycle.
CameraX VideoCapture API פועל לפי תבנית העיצוב של ה-builder. אפליקציות משתמשות ב-Recorder.Builder כדי ליצור Recorder. אפשר גם להגדיר את רזולוציית הווידאו של Recorder באמצעות אובייקט QualitySelector.
CameraX Recorder תומך ב-Qualities המוגדרים מראש הבאים לרזולוציות וידאו:
Quality.UHDלסרטון באיכות 4K Ultra HD (2160p)Quality.QHDלגודל וידאו Quad HD (1440p), שהוצג ב-CameraX1.7.0-alpha02-
Quality.FHDלסרטון בגודל Full HD (1080p) Quality.HDלסרטון באיכות HD (720p)-
Quality.SDלסרטון בגודל SD (480p)
חשוב לזכור ש-CameraX יכולה לבחור גם רזולוציות אחרות אם האפליקציה מאשרת זאת.
גודל הסרטון המדויק של כל אפשרות תלוי ביכולות של המצלמה והמקודד. מידע נוסף זמין במאמרי העזרה של CamcorderProfile.
כדי להגדיר את הרזולוציה באפליקציות, צריך ליצור QualitySelector.
אפשר ליצור QualitySelector באחת מהשיטות הבאות:
כדי לספק כמה רזולוציות מועדפות, משתמשים ב-
fromOrderedListוכוללים אסטרטגיית חלופית למקרה שאף אחת מהרזולוציות המועדפות לא נתמכת.CameraX יכולה להחליט מהי ההתאמה החלופית הטובה ביותר על סמך היכולת של המצלמה שנבחרה. פרטים נוספים זמינים ב-
FallbackStrategy specificationשלQualitySelector. לדוגמה, הקוד הבא מבקש את הרזולוציה הגבוהה ביותר שנתמכת להקלטה, ואם אף אחת מהרזולוציות של הבקשה לא נתמכת, מאשר ל-CameraX לבחור את הרזולוציה שהכי קרובה לרזולוציה Quality.SD:val qualitySelector = QualitySelector.fromOrderedList( listOf(Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))קודם שולחים שאילתה לגבי יכולות המצלמה, ובוחרים מבין הרזולוציות הנתמכות באמצעות
QualitySelector.from:val cameraInfo = cameraProvider.availableCameraInfos.filter { it.cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_BACK } // Filter to SDR resolutions supported by both the camera sensor and Recorder // encoder so the UI picker only displays valid options. val supportedQualities = Recorder.getVideoCapabilities(cameraInfo[0]).getSupportedQualities(DynamicRange.SDR) val filteredQualities = arrayListOf (Quality.UHD, Quality.QHD, Quality.FHD, Quality.HD, Quality.SD) .filter { supportedQualities.contains(it) } viewBinding.simpleQualityListView.apply { adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, filteredQualities.map { it.qualityToString() }) setOnItemClickListener { _, _, position, _ -> // QualitySelector is configured at Recorder build time, so selecting // a new resolution requires building a new Recorder instance. val qualitySelector = QualitySelector.from(filteredQualities[position]) val recorder = Recorder.Builder() .setQualitySelector(qualitySelector).build() // ... } } fun Quality.qualityToString() : String { return when (this) { Quality.UHD -> "UHD" Quality.QHD -> "QHD" Quality.FHD -> "FHD" Quality.HD -> "HD" Quality.SD -> "SD" else -> throw IllegalArgumentException() } }כל
Qualityשמוחזר על ידיVideoCapabilities.getSupportedQualities(מ-Recorder.getVideoCapabilitiesעבורDynamicRange.SDR) פועל עבור תרחיש השימושVideoCaptureבלבד או בשילוב עם תרחיש השימושPreview. אם אתם מקשרים גם אתImageCaptureאו אתImageAnalysis, יכול להיות שהקישור של CameraX ייכשל אם המצלמה לא תומכת בשילוב הזה.
אחרי שיש לכם QualitySelector, האפליקציה יכולה ליצור אובייקט VideoCapture ולבצע את הקישור. שימו לב שהקישור הזה זהה לתרחישי שימוש אחרים:
val recorder = Recorder.Builder() .setExecutor(cameraExecutor).setQualitySelector(qualitySelector) .build() val videoCapture = VideoCapture.withOutput(recorder) try { // Bind use cases to camera. cameraProvider.bindToLifecycle( this, CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture ) } catch (exc: Exception) { Log.e(TAG, "Use case binding failed", exc) }
שימו לב שהפונקציה bindToLifecycle() מחזירה אובייקט Camera. במדריך הזה מוסבר איך לשלוט בפלט של המצלמה, כמו זום וחשיפה.
Recorder בוחר את הפורמט הכי מתאים למערכת. קודק הווידאו הנפוץ ביותר הוא H.264 AVC, עם פורמט מאגר MPEG-4.
הגדרה ויצירה של הקלטה
מתוך Recorder, האפליקציה יכולה ליצור אובייקטים של הקלטה כדי לצלם את הווידאו ולהקליט את האודיו. כדי ליצור הקלטות באפליקציות:
- מגדירים את
OutputOptionsבאמצעותprepareRecording(). - (אופציונלי) מפעילים את הקלטת האודיו.
- משתמשים ב-
start()כדי לרשום מאזיןVideoRecordEvent, ומתחילים לצלם את הסרטון.
ה-Recorder מחזיר אובייקט Recording כשמפעילים את הפונקציה start().
האפליקציה יכולה להשתמש באובייקט Recording הזה כדי לסיים את הצילום או לבצע פעולות אחרות, כמו השהיה או המשך.
Recorder תומך באובייקט Recording אחד בכל פעם. אפשר להתחיל הקלטה חדשה אחרי שמפעילים את Recording.stop() או את Recording.close() באובייקט Recording הקודם.
בואו נבחן את השלבים האלה בפירוט. קודם כל, האפליקציה מגדירה את OutputOptions למכשיר הקלטה עם Recorder.prepareRecording().
Recorder תומך בסוגים הבאים של OutputOptions:
-
FileDescriptorOutputOptionsכדי לצלם בFileDescriptor. -
FileOutputOptionsכדי לתעד בFile. -
MediaStoreOutputOptionsכדי לצלם בMediaStore.
בכל סוגי ה-OutputOptions אפשר להגדיר גודל קובץ מקסימלי באמצעות setFileSizeLimit(). אפשרויות אחרות הן ספציפיות לסוג הפלט, כמו ParcelFileDescriptor עבור FileDescriptorOutputOptions.
prepareRecording() מחזירה אובייקט PendingRecording, שהוא אובייקט ביניים שמשמש ליצירת האובייקט Recording התואם. PendingRecording היא מחלקה זמנית שברוב המקרים לא אמורה להיות גלויה, והאפליקציה שומרת אותה במטמון רק לעיתים רחוקות.
האפליקציות יכולות להגדיר את ההקלטה, למשל:
- מפעילים את האודיו באמצעות
withAudioEnabled(). - רושמים פונקציית listener כדי לקבל אירועים של הקלטת סרטונים באמצעות
start(Executor, Consumer<VideoRecordEvent>). - אפשרות להקליט ברציפות בזמן שה-VideoCapture שאליו ההקלטה מצורפת מקושר מחדש למצלמה אחרת, באמצעות
PendingRecording.asPersistentRecording().
כדי להתחיל להקליט, צריך להתקשר אל PendingRecording.start(). CameraX הופך את ה-PendingRecording ל-Recording, מוסיף את בקשת ההקלטה לתור ומחזיר לאפליקציה את אובייקט ה-Recording החדש שנוצר.
אחרי שההקלטה מתחילה במכשיר המצלמה המתאים, CameraX שולח אירוע VideoRecordEvent.EVENT_TYPE_START.
בדוגמה הבאה אפשר לראות איך מקליטים וידאו ואודיו בקובץ MediaStore:
// Create MediaStoreOutputOptions for our recorder. val name = "CameraX-recording-" + SimpleDateFormat(FILENAME_FORMAT, Locale.US) .format(System.currentTimeMillis()) + ".mp4" val contentValues = ContentValues().apply { put(MediaStore.Video.Media.DISPLAY_NAME, name) } val mediaStoreOutput = MediaStoreOutputOptions.Builder( this.contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI ) .setContentValues(contentValues) .build() // 2. Configure Recorder and Start recording to the mediaStoreOutput. val recording = videoCapture.output .prepareRecording(context, mediaStoreOutput) .withAudioEnabled() .start(ContextCompat.getMainExecutor(this), captureListener)
כברירת מחדל, התצוגה המקדימה של המצלמה מוצגת בראי במצלמה הקדמית, אבל סרטונים שצולמו באמצעות VideoCapture לא מוצגים בראי כברירת מחדל. ב-CameraX 1.3 אפשר להפוך הקלטות וידאו כך שהתצוגה המקדימה של המצלמה הקדמית והסרטון המוקלט יהיו זהים.
יש שלוש אפשרויות ל-MirrorMode: MIRROR_MODE_OFF, MIRROR_MODE_ON ו-MIRROR_MODE_ON_FRONT_ONLY. כדי להתאים לתצוגה המקדימה של המצלמה, Google ממליצה להשתמש ב-MIROR_MODE_ON_FRONT_ONLY, כלומר שהשיקוף לא מופעל במצלמה האחורית, אבל מופעל במצלמה הקדמית. מידע נוסף על MirrorMode זמין במאמר MirrorMode constants.
בקטע הקוד הבא אפשר לראות איך להפעיל את VideoCapture.Builder.setMirrorMode() באמצעות MIRROR_MODE_ON_FRONT_ONLY. מידע נוסף זמין במאמר setMirrorMode().
val recorder = Recorder.Builder().build() val videoCapture = VideoCapture.Builder(recorder) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build() useCases.add(videoCapture)
טווח דינמי (סרטון HDR)
CameraX תומך בצילום וידאו בטווח דינמי גבוה (HDR) של 10 ביט, כמו HLG10, HDR10, HDR10+ או Dolby Vision, באמצעות DynamicRange.
כדי להשתמש בצילום וידאו ב-HDR, פועלים לפי השלבים הבאים:
- שולחים שאילתה לגבי הטווחים הדינמיים שהמצלמה תומכת בהם באמצעות
VideoCapabilities.getSupportedDynamicRanges(). - אופציונלי: אם מגדירים
QualitySelectorבהתאמה אישית, צריך לבדוק אילו איכויות נתמכות בטווח הדינמי הזה באמצעותgetSupportedQualities(DynamicRange). - מגדירים את
VideoCapture.BuilderבאמצעותsetDynamicRange().
בדוגמה הבאה, מופעלת הקלטת וידאו HDR באיכות 10 ביט בפורמט HLG כשהמצלמה תומכת בכך:
Kotlin
val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo) val supportedHdrRanges = videoCapabilities.supportedDynamicRanges .filter { it != DynamicRange.SDR } val recorder = Recorder.Builder().build() val videoCapture = VideoCapture.Builder(recorder) .apply { if (supportedHdrRanges.contains(DynamicRange.HLG_10_BIT)) { setDynamicRange(DynamicRange.HLG_10_BIT) } } .build()
Java
VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(cameraInfo); Set<DynamicRange> supportedRanges = videoCapabilities.getSupportedDynamicRanges(); Recorder recorder = new Recorder.Builder().build(); VideoCapture.Builder<Recorder> builder = new VideoCapture.Builder<>(recorder); if (supportedRanges.contains(DynamicRange.HLG_10_BIT)) { builder.setDynamicRange(DynamicRange.HLG_10_BIT); } VideoCapture<Recorder> videoCapture = builder.build();
ייצוב וידאו
CameraX תומך בייצוב וידאו כדי להפחית את הרעידות והתנודות של היד בזמן צילום סרטונים.
כדי להפעיל את ייצוב הסרטון, מבצעים את השלבים הבאים:
- בודקים אם המצלמה תומכת בייצוב באמצעות
VideoCapabilities.isStabilizationSupported(). - מפעילים אותה ב-
VideoCapture.BuilderבאמצעותsetVideoStabilizationEnabled(true).
בדוגמה הבאה, הייצוב מופעל כשהמצלמה תומכת בו:
Kotlin
val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo) val videoCapture = VideoCapture.Builder(recorder) .setVideoStabilizationEnabled(videoCapabilities.isStabilizationSupported) .build()
Java
VideoCapabilities videoCapabilities = Recorder.getVideoCapabilities(cameraInfo); VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(recorder) .setVideoStabilizationEnabled(videoCapabilities.isStabilizationSupported()) .build();
שליטה בהקלטה פעילה
אפשר להשהות, להמשיך ולעצור Recording פעילה באמצעות השיטות הבאות:
pauseכדי להשהות את ההקלטה הפעילה הנוכחית.resume()כדי להמשיך הקלטה פעילה שהושהתה.stop()כדי לסיים את ההקלטה ולמחוק את כל אובייקטי ההקלטה המשויכים.mute()כדי להשתיק או לבטל את ההשתקה של ההקלטה הנוכחית.
שימו לב שאפשר להפעיל את stop() כדי לסיים Recording, גם אם ההקלטה מושהית וגם אם היא פעילה.
אם רשמתם EventListener ב-PendingRecording.start(), ה-Recording מתקשר באמצעות VideoRecordEvent.
VideoRecordEvent.EVENT_TYPE_STATUSמשמש לתיעוד נתונים סטטיסטיים כמו גודל הקובץ הנוכחי ומשך הזמן שתועד.- השדה
VideoRecordEvent.EVENT_TYPE_FINALIZEמשמש לתוצאת ההקלטה וכולל מידע כמו ה-URI של הקובץ הסופי, וגם שגיאות קשורות.
אחרי שהאפליקציה מקבלת EVENT_TYPE_FINALIZE שמציין שסשן ההקלטה הצליח, אפשר לגשת לסרטון שצולם מהמיקום שצוין ב-OutputOptions.
עוצמת השמע והמצב בזמן אמת
במהלך ההקלטה, אירועי VideoRecordEvent.Status מספקים נתונים סטטיסטיים של אודיו בזמן אמת באמצעות AudioStats:
-
AudioStats.getAudioAmplitude()מחזירה את עוצמת הקול המקסימלית הנוכחית, בטווח שבין0.0ל-1.0. אפשר להשתמש בערך הזה כדי להפעיל מדידים בממשק המשתמש או רכיבים חזותיים של צורות גל של אודיו. -
AudioStats.getAudioState(): הסטטוס הנוכחי של שידור האודיו, למשלAUDIO_STATE_ACTIVE, AUDIO_STATE_MUTEDאוAUDIO_STATE_SOURCE_SILENCED.
בדוגמה הבאה, המערכת קוראת את עוצמת האודיו מאירוע סטטוס:
Kotlin
when (event) { is VideoRecordEvent.Status -> { val audioStats = event.recordingStats.audioStats if (audioStats.hasAudio()) { val amplitude = audioStats.audioAmplitude updateAudioWaveform(amplitude) } } // ... }
Java
if (event instanceof VideoRecordEvent.Status) { VideoRecordEvent.Status status = (VideoRecordEvent.Status) event; AudioStats audioStats = status.getRecordingStats().getAudioStats(); if (audioStats.hasAudio()) { double amplitude = audioStats.getAudioAmplitude(); updateAudioWaveform(amplitude); } }
סרטונים במהירות גבוהה ובהילוך איטי
CameraX תומך בצילום וידאו במהירות גבוהה, כמו 120, 240 או 480 פריימים לשנייה, מה שמאפשר שני תרחישי שימוש שונים:
- סרטון בקצב פריימים גבוה (הילוך איטי שמנוהל על ידי הנגן): CameraX מצלם ושומר פריימים בקצב פריימים גבוה (לדוגמה, 120fps). נגן הווידאו שולט במהירות ההפעלה, ומאפשר למשתמשים לעבור בין מהירות רגילה להילוך איטי או לבצע ניתוח פריים אחר פריים.
- סרטון בהילוך איטי שמוכן להפעלה: CameraX מעבד את הסטרימינג במהירות גבוהה ומוציא קובץ וידאו רגיל של 30fps עם חותמות זמן מותאמות של פריימים. אפקט ההילוך האיטי "מוטמע" בסרטון, כך שהוא מופעל בהילוך איטי באופן אוטומטי בכל נגן וידאו רגיל, בלי צורך בתמיכה מיוחדת של הנגן. לדוגמה, צילום בקצב של 120 פריימים לשנייה שמופעל בקצב של 30 פריימים לשנייה יוצר סרטון בהילוך איטי של 1/4x.
בדיקת היכולות של המהירות הגבוהה
כדי לצלם וידאו במהירות גבוהה, נדרשת תמיכה בחומרה והגדרות CamcorderProfile תואמות מיצרני המכשירים, כמו CamcorderProfile.QUALITY_HIGH_SPEED_1080P או QUALITY_HIGH_SPEED_720P.
לפני שמגדירים צילום במהירות גבוהה, צריך לשלוח שאילתה לגבי היכולות של המכשיר לצלם במהירות גבוהה באמצעות Recorder.getHighSpeedVideoCapabilities(CameraInfo):
Kotlin
val highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo) if (highSpeedCapabilities == null) { // Camera does not support high-speed video capture return } val supportedQualities = highSpeedCapabilities.getSupportedQualities(DynamicRange.SDR)
Java
VideoCapabilities highSpeedCapabilities = Recorder.getHighSpeedVideoCapabilities(cameraInfo); if (highSpeedCapabilities == null) { // Camera does not support high-speed video capture return; } List<Quality> supportedQualities = highSpeedCapabilities.getSupportedQualities(DynamicRange.SDR);
הגדרת HighSpeedVideoSessionConfig
כדי להשתמש בצילום במהירות גבוהה, צריך לשלב את תרחישי השימוש של VideoCapture ו-Preview ב-HighSpeedVideoSessionConfig. כדי להגדיר את הסשן, מבצעים את השלבים הבאים:
- יוצרים תרחיש שימוש אחד של
VideoCaptureותרחיש שימוש אחד שלPreview. - מאתחלים את
HighSpeedVideoSessionConfig.Builderעם תרחיש השימושVideoCaptureומצרפים אתPreview. - שולחים שאילתה לגבי טווחי קצב הפריימים הנתמכים באמצעות
CameraInfo.getSupportedFrameRateRanges(SessionConfig)ומגדירים את הטווח שנבחר. - בוחרים בין סרטון עם קצב פריימים גבוה לבין סרטון בהילוך איטי שמוכן להפעלה:
- כדי ליצור סרטון עם קצב פריימים גבוה, משאירים את הערך
setSlowMotionEnabled(false)(ברירת המחדל). - כדי ליצור סרטון בהילוך איטי שמוכן להפעלה, צריך להפעיל את
setSlowMotionEnabled(true).
- כדי ליצור סרטון עם קצב פריימים גבוה, משאירים את הערך
- מקשרים את הגדרת הסשן באמצעות
cameraProvider.bindToLifecycle().
בדוגמה הבאה מגדירים ומקשרים סשן של הילוך איטי שמוכן להפעלה:
Kotlin
val preview = Preview.Builder().build() val recorder = Recorder.Builder() .setQualitySelector(QualitySelector.from(supportedQualities.first())) .build() val videoCapture = VideoCapture.withOutput(recorder) // Build HighSpeedVideoSessionConfig val sessionConfigBuilder = HighSpeedVideoSessionConfig.Builder(videoCapture) .setPreview(preview) // Enable automatic slow-motion playback at 30 fps .setSlowMotionEnabled(true) // Query and set a supported high-speed frame rate range (such as 120 or 240 fps). // The set is non-empty because getHighSpeedVideoCapabilities() returned non-null earlier. val supportedFpsRanges = cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build()) sessionConfigBuilder.setFrameRateRange(supportedFpsRanges.first()) val sessionConfig = sessionConfigBuilder.build() // Bind session config to lifecycle cameraProvider.bindToLifecycle( lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, sessionConfig )
Java
Preview preview = new Preview.Builder().build(); Recorder recorder = new Recorder.Builder() .setQualitySelector(QualitySelector.from(supportedQualities.get(0))) .build(); VideoCapture<Recorder> videoCapture = VideoCapture.withOutput(recorder); HighSpeedVideoSessionConfig.Builder sessionConfigBuilder = new HighSpeedVideoSessionConfig.Builder(videoCapture) .setPreview(preview) .setSlowMotionEnabled(true); // The set is non-empty because getHighSpeedVideoCapabilities() returned non-null earlier. Set<Range<Integer>> supportedFpsRanges = cameraInfo.getSupportedFrameRateRanges(sessionConfigBuilder.build()); sessionConfigBuilder.setFrameRateRange(supportedFpsRanges.iterator().next()); HighSpeedVideoSessionConfig sessionConfig = sessionConfigBuilder.build(); cameraProvider.bindToLifecycle( lifecycleOwner, CameraSelector.DEFAULT_BACK_CAMERA, sessionConfig );
אפשר גם להשתמש ב-Kotlin DSL, שהוצג ב-CameraX 1.7.0-alpha02, כדי להגדיר סשנים במהירות גבוהה בצורה תמציתית:
val sessionConfig = highSpeedVideoSessionConfig(videoCapture) {
this.preview = preview
isSlowMotionEnabled = true
frameRateRange = supportedFpsRanges.first()
}
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
sessionConfig
)
איך מצלמים סרטונים במהירות גבוהה או בהילוך איטי
אחרי שמקשרים את HighSpeedVideoSessionConfig, מתחילים לצלם באמצעות VideoCapture באותו אופן שבו מצלמים סרטונים רגילים:
Kotlin
val recording = videoCapture.output .prepareRecording(context, mediaStoreOutput) .withAudioEnabled() .start(ContextCompat.getMainExecutor(context)) { event -> when (event) { is VideoRecordEvent.Start -> Log.d(TAG, "Recording started") is VideoRecordEvent.Finalize -> { if (!event.hasError()) { Log.d(TAG, "Video saved: ${event.outputResults.outputUri}") } } } }
Java
Recording recording = videoCapture.getOutput() .prepareRecording(context, mediaStoreOutput) .withAudioEnabled() .start(ContextCompat.getMainExecutor(context), event -> { if (event instanceof VideoRecordEvent.Start) { Log.d(TAG, "Recording started"); } else if (event instanceof VideoRecordEvent.Finalize) { VideoRecordEvent.Finalize finalize = (VideoRecordEvent.Finalize) event; if (!finalize.hasError()) { Log.d(TAG, "Video saved: " + finalize.getOutputResults().getOutputUri()); } } });
מקורות מידע נוספים
איפה אפשר למצוא מידע נוסף על CameraX?
- Codelab תחילת העבודה עם CameraX
- אפליקציה לדוגמה רשמית של CameraX
- רשימת ה-API העדכניים של CameraX Video Capture
- נתוני הגרסה של CameraX
- קוד המקור של CameraX
- צילום במהירות גבוהה וסרטונים בהילוך איטי באמצעות CameraX 1.5