前言
话接上文,接着我们来学习下如何使用CameraX自带的录制视频功能
增加录像功能(Android 11)
布局文件
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/takeP"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="拍照" />
<Button
android:layout_marginStart="10dp"
android:id="@+id/openRecord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始录像" />
<Button
android:layout_marginStart="10dp"
android:id="@+id/disableRecord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="结束录像" />
</LinearLayout>
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
对比上一篇文章,我们新增了开始录像和结束录像按钮,PreviewView用于预览,其他没有变化
获取ProcessCameraProvider,它的作用是将相机的生命周期绑定到应用程序,它是一个单例类。
private fun initCamera() {
cameraProviderFuture = ProcessCameraProvider.getInstance(this)
//请求 CameraProvider 后,请验证它能否在视图创建后成功初始化。以下代码展示了如何执行此操作:
cameraProviderFuture.addListener(Runnable {
val cameraProvider = cameraProviderFuture.get()
bindPreview(cameraProvider)
}, ContextCompat.getMainExecutor(this))
}
获取camera
@SuppressLint("RestrictedApi", "UnsafeOptInUsageError")
fun bindPreview(cameraProvider: ProcessCameraProvider) {
//预览
var preview: Preview = Preview.Builder()
.setTargetResolution(Size(1280, 720)) //设置分辨率
.build()
// 拍照
imageCapture = ImageCapture.Builder()
.setCaptureMode(CAPTURE_MODE_MAXIMIZE_QUALITY) //优先考虑图片质量,速度略低
.setBufferFormat(ImageFormat.JPEG)
.build()
// 选择相机
var cameraSelector: CameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK) //后置
.build()
// 提供previewView预览控件
preview.setSurfaceProvider(previewView.surfaceProvider)
//录像
videoCapture = VideoCapture.Builder()
.setMaxResolution(Size(1280, 720))
.build()
// 在绑定之前 你应该先解绑
cameraProvider.unbindAll()
var camera = cameraProvider.bindToLifecycle(
this as LifecycleOwner,
cameraSelector,
videoCapture,
preview
)
}
VideoCapture提供了对录制视频参数的控制,如比特率、帧率、分辨率等,当然你可以不设置,有默认参数:
现在运行,你将看到可以正常显示预览界面,如果没有显示,请检查是否处理危险权限CAMERA。
对了,你需要申请一下RECORD_AUDIO权限,录制视频需要用到
添加开始录制的事件
@SuppressLint("UnsafeOptInUsageError", "MissingPermission", "RestrictedApi")
private fun startRecording() {
val file = File(
getExternalFilesDir(Environment.DIRECTORY_MOVIES)!!.path,
"${System.currentTimeMillis()}.mp4"
)
val options = VideoCapture.OutputFileOptions.Builder(file).build()
videoCapture?.apply {
startRecording(options, mainExecutor, object : VideoCapture.OnVideoSavedCallback {
/**
* 录像保存成功,结束录像时调用
*/
override fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {
Log.d(TAG, "onVideoSaved: 录像")
}
//开始录像失败。有错误原因
override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
Log.d(TAG, "onVideoSaved: 录像:$message")
}
})
}
}
我将录制相关的代码写在了一个函数内,下面是停止录制的代码,你在点击事件中调用他们即可。
@SuppressLint("RestrictedApi")
private fun stopRecording() {
videoCapture?.stopRecording()
}
停止录制后,你可以在外部存储storage/emulated/0/android/data/packageName/看到录制的mp4文件的视频,当然地址你可以写其他位置,如果你不是Android10,你还需要处理文件读写权限,
她的默认格式为H.264/AAC组成,如果你感兴趣可以在VideoCapture的源码中看到他们,如默认的比特率、帧率、分辨率等。
现在可以感受到CameraX给我们提供的一些便利了,否则我们需要自己去处理相关的H.264/AAC编码、合并音视频的操作。当然这是简单的场景,如果我们需要将预览的流推到流媒体服务器怎么办,下一篇我们学习获取预览流编码为其他格式。