یک سیستم ضبط معمولاً جریانهای ویدیویی و صوتی را ضبط میکند، آنها را فشرده میکند، دو جریان را با هم ترکیب میکند و سپس جریان حاصل را روی دیسک مینویسد.

در CameraX، راهکار ضبط ویدیو، مورد استفاده VideoCapture است:

VideoCapture را مدیریت میکند.همانطور که در شکل 2 نشان داده شده است، ضبط ویدیوی CameraX شامل چند مؤلفه معماری سطح بالا است:
-
SurfaceProviderبرای منبع ویدیو. -
AudioSourceبرای منبع صوتی. - دو انکودر برای انکود و فشردهسازی ویدیو/صدا.
- یک میکسر رسانهای برای ترکیب دو جریان.
- یک فایل سیور برای نوشتن نتیجه.
رابط برنامهنویسی کاربردی (API) ضبط ویدیو، موتور ضبط پیچیده را کنار گذاشته و یک رابط برنامهنویسی کاربردی (API) بسیار سادهتر و سرراستتر را در اختیار برنامهها قرار میدهد.
مرور کلی API ضبط ویدیو
VideoCapture یک مورد استفاده CameraX است که به تنهایی یا در ترکیب با سایر موارد استفاده به خوبی کار میکند. ترکیبهای پشتیبانیشده خاص به قابلیتهای سختافزاری دوربین بستگی دارند، اما Preview و VideoCapture یک ترکیب مورد استفاده معتبر در همه دستگاهها هستند.
رابط برنامهنویسی کاربردی (API) ضبط ویدیو (VideoCapture) شامل اشیاء زیر است که با برنامهها ارتباط برقرار میکنند:
-
VideoCaptureکلاس مورد استفاده سطح بالا است.VideoCaptureبه یکLifecycleOwnerبا یکCameraSelectorو سایر UseCases های CameraX متصل میشود. برای اطلاعات بیشتر در مورد این مفاهیم و کاربردها، به معماری CameraX مراجعه کنید. -
Recorderیک پیادهسازی از VideoOutput است که به طور تنگاتنگی باVideoCaptureجفت شده است.Recorderبرای انجام ضبط ویدیو و صدا استفاده میشود. یک برنامه، ضبطها را ازRecorderایجاد میکند . - یک
PendingRecordingیک ضبط را پیکربندی میکند و گزینههایی مانند فعال کردن صدا و تنظیم شنونده رویداد را ارائه میدهد. برای ایجاد یکPendingRecordingباید از یکRecorderاستفاده کنید.PendingRecordingچیزی را ضبط نمیکند. - یک
Recordingضبط واقعی را انجام میدهد. برای ایجاد یکRecordingباید ازPendingRecordingاستفاده کنید.
شکل ۳ روابط بین این اشیاء را نشان میدهد:

افسانه:
- با
QualitySelectorیکRecorderایجاد کنید. -
Recorderبا یکی ازOutputOptionsپیکربندی کنید. - در صورت نیاز، صدا را با
withAudioEnabled()فعال کنید. - برای شروع ضبط، تابع
start()را با یک شنوندهیVideoRecordEventفراخوانی کنید. - برای کنترل ضبط،
pause()/resume()/stop()درRecordingاستفاده کنید. - به
VideoRecordEventsدرون شنونده رویداد خود پاسخ دهید.
لیست دقیق API در فایل current.txt درون کد منبع قرار دارد.
استفاده از API ضبط ویدیو
برای ادغام مورد استفاده CameraX VideoCapture در برنامه خود، موارد زیر را انجام دهید:
-
VideoCaptureمقید کنید. - آماده سازی و پیکربندی ضبط.
- ضبط در زمان اجرا را شروع و کنترل کنید.
بخشهای زیر شرح میدهند که در هر مرحله چه کاری میتوانید انجام دهید تا یک جلسه ضبط سرتاسری داشته باشید.
ضبط ویدیو را متصل کنید
برای اتصال مورد استفاده VideoCapture ، موارد زیر را انجام دهید:
- یک شیء
Recorderایجاد کنید. - شیء
VideoCaptureرا ایجاد کنید. - اتصال به یک
Lifecycle.
رابط برنامهنویسی کاربردی CameraX VideoCapture از الگوی طراحی سازنده پیروی میکند. برنامهها Recorder.Builder برای ایجاد یک Recorder استفاده میکنند. همچنین میتوانید وضوح تصویر را برای Recorder از طریق یک شیء QualitySelector پیکربندی کنید.
Recorder CameraX از Qualities از پیش تعریف شده زیر برای وضوح تصویر ویدیو پشتیبانی میکند:
-
Quality.UHDبرای اندازه ویدیوی 4K ultra HD (2160p) -
Quality.FHDبرای اندازه ویدیوی فول اچدی (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 ، برنامه میتواند اشیاء ضبط را برای انجام ضبط ویدیو و صدا ایجاد کند. برنامهها با انجام موارد زیر ضبطها را ایجاد میکنند:
- با استفاده از تابع
prepareRecording()OutputOptions) را پیکربندی کنید. - (اختیاری) ضبط صدا را فعال کنید.
-
start()برای ثبت یک شنوندهVideoRecordEventاستفاده کنید و ضبط ویدیو را شروع کنید.
Recorder هنگام فراخوانی تابع start() یک شیء Recording object) برمیگرداند. برنامه شما میتواند از این شیء Recording برای اتمام ضبط یا انجام اقدامات دیگر، مانند مکث یا از سرگیری، استفاده کند.
یک Recorder در هر زمان از یک شیء Recording پشتیبانی میکند. میتوانید پس از فراخوانی Recording.stop() یا Recording.close() روی شیء Recording قبلی، یک ضبط جدید را شروع کنید.
بیایید این مراحل را با جزئیات بیشتری بررسی کنیم. ابتدا، برنامه، OutputOptions را برای یک Recorder با Recorder.prepareRecording() پیکربندی میکند. یک Recorder از انواع OutputOptions زیر پشتیبانی میکند:
-
FileDescriptorOutputOptionsبرای ثبت در یکFileDescriptor. -
FileOutputOptionsبرای ضبط در یکFile. -
MediaStoreOutputOptionsبرای ضبط درMediaStore.
همه انواع OutputOptions به شما امکان میدهند حداکثر اندازه فایل را با setFileSizeLimit() تنظیم کنید. گزینههای دیگر مختص نوع خروجی خاص هستند، مانند ParcelFileDescriptor برای FileDescriptorOutputOptions .
prepareRecording() یک شیء PendingRecording برمیگرداند که یک شیء میانی است و برای ایجاد شیء Recording مربوطه استفاده میشود. PendingRecording یک کلاس گذرا است که در بیشتر موارد باید نامرئی باشد و به ندرت توسط برنامه ذخیره میشود.
برنامهها میتوانند ضبط را بیشتر پیکربندی کنند، مانند:
- صدا را با استفاده از
withAudioEnabled()فعال کنید. - یک شنونده (listener) ثبت کنید تا رویدادهای ضبط ویدیو را با
start(Executor, Consumer<VideoRecordEvent>)دریافت کند. - با استفاده از
PendingRecording.asPersistentRecording()، به یک ضبط اجازه دهید تا به طور مداوم ضبط کند در حالی که VideoCapture که به آن متصل است به دوربین دیگری منتقل میشود.
برای شروع ضبط، 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. برای تراز کردن با پیشنمایش دوربین، گوگل استفاده از 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);
جاوا
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