בדרך כלל מערכת צילום וידאו מקליטה וידאו ואודיו, דוחסת אותם, מאחזרת את שני הזרמים, ואז כותבת את הזרם שנוצר בדיסק.
ב- CameraX, הפתרון לצילום וידאו הוא
VideoCapture
תרחיש לדוגמה:
VideoCapture.כפי שמוצג באיור 2, צילום הווידאו של CameraX כולל מספר רכיבים ארכיטקטוניים:
SurfaceProviderלמקור הסרטון.AudioSourceלמקור האודיו.- שני מקודדים לקידוד ולדחיסה של וידאו/אודיו.
- מיקסר מדיה שמשלב בין שני השידורים.
- שומר קבצים לכתיבה של התוצאה.
VideoCapture API מפשט את מנוע הצילום המורכב ומספק באמצעות ממשק API פשוט ופשוט יותר.
סקירה כללית על VideoCapture API
VideoCapture הוא תרחיש לדוגמה של CameraX שפועל היטב בפני עצמו או כאשר
בשילוב עם תרחישים לדוגמה אחרים. השילובים הנתמכים הספציפיים תלויים
יכולות של חומרת מצלמה, אבל Preview ו-VideoCapture הם
שילוב תקין של תרחישי שימוש בכל המכשירים.
VideoCapture API מורכב מהאובייקטים הבאים שמתקשרים עם אפליקציות:
VideoCaptureהוא ברמה העליונה של תרחיש לדוגמה.VideoCaptureמקושר אלLifecycleOwnerעםCameraSelectorו- CameraX אחר תרחישים לדוגמה. למידע נוסף על המושגים והשימושים האלה, ראו ארכיטקטורת CameraX.Recorderהוא של VideoOutput בשילוב עםVideoCapture. האפליקציהRecorderמשמשת לצילום וידאו ואודיו. האפליקציה יוצרת הקלטות מ-Recorder.PendingRecordingמגדיר הקלטה, ומספק אפשרויות כמו הפעלת אודיו והגדרות האזנה לאירועים. כדי ליצור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. - הכנות והגדרת הקלטה.
- איך מתחילים את ההקלטה של סביבת זמן הריצה ושולטים בה.
בקטעים הבאים מפורט מה אפשר לעשות בכל שלב כדי לקבל צילום סרטון מקצה לקצה.
קישור צילום וידאו
כדי לקשר את התרחיש לדוגמה VideoCapure:
- יוצרים אובייקט
Recorder. - יצירת אובייקט
VideoCapture. - קישור ל-
Lifecycle.
CameraX VideoCapture API תואם לדפוס העיצוב של ה-builder. הגשת מועמדות
יש להשתמש ב-Recorder.Builder כדי ליצור Recorder. אפשר גם להגדיר
רזולוציית הסרטון של Recorder דרך אובייקט QualitySelector.
CameraX Recorder תומך בתקנים הבאים המוגדרים מראש Qualities
לרזולוציות של סרטונים:
Quality.UHDלצילום וידאו באיכות 4K ultra HD (2160p)Quality.FHDלסרטון באיכות 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.FHD, Quality.HD, Quality.SD), FallbackStrategy.lowerQualityOrHigherThan(Quality.SD))קודם כול צריך להריץ שאילתות על יכולות המצלמה ולבחור אחת מבין האפשרויות הנתמכות רזולוציות באמצעות
QualitySelector::from():val cameraInfo = cameraProvider.availableCameraInfos.filter { Camera2CameraInfo .from(it) .getCameraCharacteristic(CameraCharacteristics.LENS\_FACING) == CameraMetadata.LENS_FACING_BACK } val supportedQualities = QualitySelector.getSupportedQualities(cameraInfo[0]) val filteredQualities = arrayListOf (Quality.UHD, Quality.FHD, Quality.HD, Quality.SD) .filter { supportedQualities.contains(it) } // Use a simple ListView with the id of simple_quality_list_view viewBinding.simpleQualityListView.apply { adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, filteredQualities.map { it.qualityToString() }) // Set up the user interaction to manually show or hide the system UI. setOnItemClickListener { _, _, position, _ -> // Inside View.OnClickListener, // convert Quality.* constant to QualitySelector val qualitySelector = QualitySelector.from(filteredQualities[position]) // Create a new Recorder/VideoCapture for the new quality // and bind to lifecycle val recorder = Recorder.Builder() .setQualitySelector(qualitySelector).build() // ... } } // A helper function to translate Quality to a string fun Quality.qualityToString() : String { return when (this) { Quality.UHD -> "UHD" Quality.FHD -> "FHD" Quality.HD -> "HD" Quality.SD -> "SD" else -> throw IllegalArgumentException() } }שימו לב שהיכולת שהוחזרה
QualitySelector.getSupportedQualities()פועל בתרחיש לדוגמה שלVideoCaptureאו שילוב של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()כדי לרשוםVideoRecordEventListener, והתחילו לצלם את הסרטון.
הפונקציה 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(). - רישום מאזינים כדי לקבל אירועים של הקלטת וידאו
עם
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_מצב_ON ו
MIRROR_מצב_ON_FRONT_ONLY. כדי ליישר עם
תצוגה מקדימה של המצלמה, Google ממליצה להשתמש ב-MIROR_מצב_ON_FRONT_ONLY.
ש
שיקוף מסך לא מופעל במצלמה האחורית, אבל הוא מופעל בחזית
מצלמה. למידע נוסף על MirrorMode, יש לעיין
MirrorMode constants
קטע הקוד הזה מראה איך להתקשר
VideoCapture.Builder.setMirrorMode() באמצעות MIRROR_MODE_ON_FRONT_ONLY. עבור
למידע נוסף, ראו setMirrorMode().
Kotlin
val recorder = Recorder.Builder().build() val videoCapture = VideoCapture.Builder(recorder) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build() useCases.add(videoCapture);
Java
Recorder.Builder builder = new Recorder.Builder(); if (mVideoQuality != QUALITY_AUTO) { builder.setQualitySelector( QualitySelector.from(mVideoQuality)); } VideoCapture<Recorder> videoCapture = new VideoCapture.Builder<>(builder.build()) .setMirrorMode(MIRROR_MODE_ON_FRONT_ONLY) .build(); useCases.add(videoCapture);
שליטה בהקלטה פעילה
ניתן להשהות, להמשיך ולהפסיק 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.
מקורות מידע נוספים
למידע נוסף על CameraX, ניתן לעיין במשאבים הנוספים הבאים:
- תחילת העבודה עם CameraX Codelab
- אפליקציה רשמית לדוגמה של CameraX
- רשימת ממשקי ה-API האחרונים של צילום וידאו של CameraX
- נתוני הגרסה של CameraX
- קוד המקור של CameraX