其实录像和拍照的区别并不大,没有看过上一篇拍照的可以先看一下,下文就不会详细说明,文末会附上全代码
录像会使用MediaRecorder作为输出Surface,为了与拍照区别,新创建一个录像用的CaptureRequest.Builder
//录像输出Surface
private lateinit var mediaRecorder: MediaRecorder
//录像CaptureRequest.Builder
private lateinit var videoCaptureRequest:CaptureRequest.Builder
开启录像
通过长按事件开启录像
//长按录像
video.setOnLongClickListener {
videoStart()
return@setOnLongClickListener true
}
录像前需要结束预览和拍照的Session,然后需要创建一个录像Session
/**
* 开始录像
*/
private fun videoStart() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.RECORD_AUDIO
) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
) {
cameraCaptureSession.close()
video.text = "停止"
//获取录制视频的surface
mediaRecorder = CameraUtil.getMediaRecorder(surface, size)
//创建一个录像的CaptureRequest
videoCaptureRequest = CameraUtil.createVideoCaptureRequest(
cameraDevice,
surface,
mediaRecorder.surface
)
//创建一个录像Session
cameraDevice.createCaptureSession(
arrayListOf(surface, mediaRecorder.surface),
videoSessionCallback,
CameraUtil.getBackgroundHandler()
)
} else {
val dialog = AlertDialog.Builder(this)
dialog.setTitle("无法录制视频").setMessage("缺少录音权限或SD卡权限").setCancelable(false)
dialog.setNegativeButton("退出") { _, _ ->
finish()
}
dialog.setPositiveButton("授权") { _, _ ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.parse("package:$packageName")
startActivity(intent)
}
dialog.show()
}
}
}
/**
* 创建录像Session的回调
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private val videoSessionCallback = object : CameraCaptureSession.StateCallback(){
//
override fun onConfigured(session: CameraCaptureSession) {
cameraCaptureSession = session
// 开始录像
cameraCaptureSession.setRepeatingRequest(videoCaptureRequest.build(), captureCallback, CameraUtil.getBackgroundHandler())
mediaRecorder.start()
}
//创建失败
override fun onConfigureFailed(session: CameraCaptureSession) {
}
}
工具类
/**
* 获取录制视频的surface
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
fun getMediaRecorder(surface:Surface,size: Size): MediaRecorder {
val mediaRecorder = MediaRecorder()
//Initialized状态
//设置声音来源,一般传入 MediaRecorder. AudioSource.MIC参数指定录制来自麦克风的声音。
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC)
//设置用于录制的视频来源surface。
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
//设置所录制的音视频文件的格式。进入DataSourceConfigured状态
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
//设置所录制的声音的编码格式。
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
//设置录制的音频文件的保存位置。
mediaRecorder.setOutputFile(getFilePath("${System.currentTimeMillis()}.mp4"))
//设置所录制视频的编码位率。
mediaRecorder.setVideoEncodingBitRate(10000000)
//设置录制视频的捕获帧速率。
mediaRecorder.setVideoFrameRate(30)
//设置要拍摄的宽度和视频的高度。
mediaRecorder.setVideoSize(size.width, size.height)
//设置所录制视频的编码格式。
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
//设置录制视频的方向
setVideoOrientation(mediaRecorder)
//设置使用哪个SurfaceView来显示视频预览。
mediaRecorder.setPreviewDisplay(surface)
//准备录制。
mediaRecorder.prepare()
return mediaRecorder
}
/**
* 设置录制视频的方向
*/
fun setVideoOrientation(mediaRecorder: MediaRecorder) {
if (index == 0) {
//设置输出的视频播放的方向提示。
mediaRecorder.setOrientationHint(90)
} else {
//设置输出的视频播放的方向提示。
mediaRecorder.setOrientationHint(90 * 3)
}
}
/**
* 创建一个录像的CaptureRequest
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
fun createVideoCaptureRequest(
cameraDevice: CameraDevice,
surface: Surface,
mediaRecorderSurface: Surface
): CaptureRequest.Builder {
//创建一个拍照的CaptureRequest
val captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)
// 设置拍照输出的 Surface
captureRequestBuilder.addTarget(surface)
captureRequestBuilder.addTarget(mediaRecorderSurface)
return captureRequestBuilder
}
结束录像
长按结束关闭录像
//松开结束录像
video.setOnTouchListener { _, event ->
val action = event.action
if (action == MotionEvent.ACTION_UP) { // 松开
videoStop()
}
return@setOnTouchListener false
}
结束录像要切换会预览界面,也需要关闭录像Session,然后重新创建预览Session
/**
* 停止录制
*/
private fun videoStop(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
video.text = "长按录制"
mediaRecorder.stop()
//将MediaRecorder设为空闲状态,即Initial状态。
mediaRecorder.reset()
cameraCaptureSession.close()
setPreview()
}
}
/**
* 设置预览
*/
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private fun setPreview(){
//