یک سیستم ضبط به طور کلی جریان های ویدئویی و صوتی را ضبط می کند، آنها را فشرده می کند، دو جریان را به هم متصل می کند، سپس جریان حاصل را روی دیسک می نویسد.
در CameraX، راه حل برای فیلم برداری، استفاده از VideoCapture
است:
همانطور که در شکل 2 نشان داده شده است، فیلمبرداری CameraX شامل چند جزء معماری سطح بالا است:
-
SurfaceProvider
برای منبع ویدیو. -
AudioSource
برای منبع صوتی. - دو رمزگذار برای رمزگذاری و فشرده سازی ویدئو/صوت.
- مخزن رسانه ای برای مخلوط کردن دو جریان.
- ذخیرهکننده فایل برای نوشتن نتیجه.
VideoCapture API موتور پیچیده تصویربرداری را خلاصه می کند و برنامه های کاربردی را با API بسیار ساده تر و ساده تر ارائه می دهد.
نمای کلی VideoCapture API
VideoCapture
یک کیس استفاده CameraX است که به تنهایی یا زمانی که با موارد استفاده دیگر ترکیب می شود، به خوبی کار می کند. ترکیبهای خاص پشتیبانی شده به قابلیتهای سختافزار دوربین بستگی دارد، اما Preview
و VideoCapture
یک ترکیب مورد استفاده معتبر در همه دستگاهها هستند.
VideoCapture API از اشیاء زیر تشکیل شده است که با برنامه ها ارتباط برقرار می کنند:
-
VideoCapture
کلاس کاربری سطح بالایی است.VideoCapture
با یکCameraSelector
و سایر موارد استفاده CameraX بهLifecycleOwner
متصل می شود. برای اطلاعات بیشتر در مورد این مفاهیم و کاربردها، به معماری CameraX مراجعه کنید. -
Recorder
پیاده سازی VideoOutput است که به شدت باVideoCapture
همراه است.Recorder
برای انجام فیلمبرداری و ضبط صدا استفاده می شود. یک برنامه ازRecorder
ضبط ایجاد می کند . - یک
PendingRecording
یک ضبط را پیکربندی می کند و گزینه هایی مانند فعال کردن صدا و تنظیم شنونده رویداد را ارائه می دهد. برای ایجادPendingRecording
باید از یکRecorder
استفاده کنید. یکPendingRecording
چیزی را ضبط نمی کند. - A
Recording
ضبط واقعی را انجام می دهد. برای ایجاد یکRecording
باید از یکPendingRecording
استفاده کنید.
شکل 3 روابط بین این اشیاء را نشان می دهد:
افسانه:
- با
QualitySelector
یکRecorder
ایجاد کنید. -
Recorder
با یکی ازOutputOptions
پیکربندی کنید. - در صورت نیاز صدا را با
withAudioEnabled()
فعال کنید. - برای شروع ضبط، با یک شنونده
VideoRecordEvent
start()
بگیرید. - از
pause()
/resume()
/stop()
درRecording
برای کنترل ضبط استفاده کنید. - به
VideoRecordEvents
در شنونده رویداد خود پاسخ دهید.
فهرست دقیق API در current.txt داخل کد منبع موجود است.
با استفاده از VideoCapture API
برای ادغام کیس استفاده CameraX VideoCapture
در برنامه خود، موارد زیر را انجام دهید:
- Bind
VideoCapture
- ضبط را آماده و پیکربندی کنید.
- ضبط زمان اجرا را شروع و کنترل کنید.
بخشهای زیر به تشریح کارهایی که میتوانید در هر مرحله برای دریافت یک جلسه ضبط سرتاسر انجام دهید، میپردازد.
Bind VideoCapture
برای اتصال کیس استفاده VideoCapure
، موارد زیر را انجام دهید:
- یک شی
Recorder
ایجاد کنید. - شی
VideoCapture
ایجاد کنید. - به یک
Lifecycle
متصل شوید.
CameraX VideoCapture API از الگوی طراحی سازنده پیروی می کند. برنامه ها از Recorder.Builder
برای ایجاد یک Recorder
استفاده می کنند. همچنین میتوانید وضوح تصویر را برای Recorder
از طریق یک شی QualitySelector
پیکربندی کنید.
CameraX Recorder
از 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
، برنامه می تواند اشیاء ضبط را برای انجام ضبط ویدیو و صدا ایجاد کند. برنامه ها با انجام کارهای زیر ضبط ایجاد می کنند:
-
OutputOptions
را باprepareRecording()
پیکربندی کنید. - (اختیاری) ضبط صدا را فعال کنید.
- از
start()
برای ثبت شنوندهVideoRecordEvent
و شروع فیلمبرداری استفاده کنید.
هنگامی که تابع start()
را فراخوانی می کنید، Recorder
یک شی Recording
برمی گرداند. برنامه شما می تواند از این شیء 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_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);
جاوا
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()
برای بی صدا کردن یا لغو صدای ضبط فعلی.
توجه داشته باشید که میتوانید برای پایان دادن به یک Recording
بدون توجه به اینکه ضبط در حالت ضبط موقت یا فعال است stop()
را فراخوانی کنید.
اگر یک EventListener
با PendingRecording.start()
ثبت کرده باشید، Recording
با استفاده از VideoRecordEvent
ارتباط برقرار می کند.
-
VideoRecordEvent.EVENT_TYPE_STATUS
برای ضبط آماری مانند اندازه فایل فعلی و بازه زمانی ثبت شده استفاده می شود. -
VideoRecordEvent.EVENT_TYPE_FINALIZE
برای نتیجه ضبط استفاده می شود و شامل اطلاعاتی مانند URI فایل نهایی به همراه هرگونه خطای مرتبط است.
هنگامی که برنامه شما یک EVENT_TYPE_FINALIZE
دریافت کرد که نشان دهنده یک جلسه ضبط موفقیت آمیز است، سپس می توانید از مکان مشخص شده در OutputOptions
به ویدیوی ضبط شده دسترسی داشته باشید.
منابع اضافی
برای کسب اطلاعات بیشتر در مورد CameraX، به منابع اضافی زیر مراجعه کنید:
- شروع کار با CameraX Codelab
- برنامه رسمی CameraX نمونه
- آخرین لیست API CameraX Video Capture
- یادداشت های انتشار CameraX
- کد منبع CameraX