关注公众号学习更多知识
本篇文章的内容是上一篇拍摄照片内容的延续
上一篇文章传送门: 嗖所用的工程代码也是和上一篇是相同的
概览
概念和简单的使用建议跳到上一篇文章去看https://juejin.cn/post/6968317886678958088
使用(简单拍摄一段视频并展示)
打开相机并设置相关参数
private fun openCamera() {
cameraProviderFuture = ProcessCameraProvider.getInstance(this)//获得provider实例
cameraProviderFuture.addListener({
cameraProvider = cameraProviderFuture.get()
bindPreview()
}, ContextCompat.getMainExecutor(this))
}
@SuppressLint("RestrictedApi")
private fun bindPreview(
) {
val preview: Preview = Preview.Builder()
.build()
val cameraSelector: CameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
preview.setSurfaceProvider(previdew.surfaceProvider)
videoCapture = VideoCapture.Builder()
.setBitRate(1024 * 1024)
.setVideoFrameRate(36)
.setTargetRotation(previdew.display.rotation)
.build()
var camera = cameraProvider?.bindToLifecycle(
this,
cameraSelector,
videoCapture,
preview
)
}
拍摄视频代码
@SuppressLint("RestrictedApi", "MissingPermission")
fun takeVideo() {
val faceVideoFile = getExternalFilesDir("videoFile")?.also {
if (it.exists()) {
it.mkdirs()
}
}
val destVideoFile = File(faceVideoFile, "${System.currentTimeMillis()}.mp4")
val outFileOption = VideoCapture.OutputFileOptions.Builder(destVideoFile).build()
videoCapture.startRecording(
outFileOption,
Executors.newSingleThreadExecutor(),
object : VideoCapture.OnVideoSavedCallback {
override fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {
lifecycleScope.launch(Dispatchers.Main) {
Toast.makeText(this@TakeVideoActivity, "拍摄成功", Toast.LENGTH_LONG).show()
startActivity(
Intent(
this@TakeVideoActivity,
ShowVideoActivity::class.java
).apply {
putExtra("path", destVideoFile.absolutePath)
})
}
}
override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
lifecycleScope.launch(Dispatchers.Main) {
Toast.makeText(this@TakeVideoActivity, "拍摄失败", Toast.LENGTH_LONG).show()
}
}
})
}
结束拍摄
videoCapture.stopRecording()
activity销毁的时候停止相机
@SuppressLint("RestrictedApi")
override fun onDestroy() {
super.onDestroy()
cameraProvider?.shutdown()//必备的一步调用
}
最终效果
重要api讲解
当我们构建VideoCapture的时候有一些重要的参数设置可以决定最终我们生成视频的结果
setBitRate设置视频的比特率
.setBitRate(1024 * 1024)
方法参数的单位是比特,表示我们生成的视频一秒钟的的比特大小
我亲测的结果是CameraX会尽量按照我们设置的比特率来做,如果设置的不合理CameraX会自动为我们调整以保证最终生成的视频的质量
setVideoFrameRate设置视频的帧率
.setVideoFrameRate(100)
相当于设置视频的帧率,不过参数的单位是毫秒,比如本例代码我们设置100ms,那么就表示1s内回输出10张视频帧
setTargetRotation设置相机的旋转角度
.setTargetRotation(previdew.display.rotation)
这个api没啥好说的,大家都熟悉
setAudioBitRate设置音频的码率
.setAudioBitRate(1024)
设置音频的码率,和setBitRate类似
setTargetResolution设置生成的视频的分辨率
.setTargetResolution(Size(300,200))
设置最终生成视频的宽高像素比,当我们想极限压缩视频大小的时候这个会非常有用,压缩收益会远大于控制帧率。
切换摄像头的方法
val cameraSelector: CameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)//设置后置摄像头,非自拍
// .requireLensFacing(CameraSelector.LENS_FACING_FRONT)//设置前置摄像头,自拍
.build()
这里必须说一下安卓前置摄像头坑爹的地方:使用前置摄像头拍摄出来的图像是左右颠倒的,使用CameraX因为无法自定义SurfaceView所以我们无法对视频方向进行处理