Android使用MediaRecorder进行录像,暂停和继续录像的VideoUtils
使用MediaRecorder
进行录像,要注意再设置MediaRecorder的参数的时候设置,这里也是查了网上很多代码都没有一个完整能实现的,或多或少都有点问题。
还有再暂停/继续录制的时候要注意将Camera
的预览关闭camera.stopPreview()
不然预览的界面还是会继续动给人暂停了还在录制的错觉。
还有camera再使用之前记得要unlock
一下。至于设置MediaRecorder的参数,也是尝试了好多次,最后选择了使用profile
选择视频质量来进行配置,这样最简单,可以考虑到视频大小的要求选择默认的 720P等,但是注意要硬件适配的大小。
所以如果出现media start failed,那么可以尝试降低视频录制参数来重新尝试。
完整的VideoUtils
代码如下:
import android.hardware.Camera
import android.media.CamcorderProfile
import android.media.MediaRecorder
import android.os.Build
import android.view.Surface
import android.view.TextureView
import com.blankj.utilcode.util.PathUtils
import com.blankj.utilcode.util.PermissionUtils
import com.blankj.utilcode.util.ToastUtils
import java.io.File
import java.io.IOException
import java.lang.Exception
// 签署时候,录制视频的工具,包含录制和播放
class VideoUtils {
companion object {
private var instance: VideoUtils ?= null
fun getInstance(): VideoUtils {
if (instance == null) {
instance = VideoUtils()
}
return instance!!
}
}
private var camera: Camera? = null
// 是否正在录制
var isRecording: Boolean = false
// 是否开启了录制,初始化并开启录制,之后是暂停
var started: Boolean = false
private var mMediaRecorder: MediaRecorder ?= null
init {
mMediaRecorder = MediaRecorder()
}
private fun configMediaRecorder(textureView: TextureView){
val videoFile = File(PathUtils.getExternalDownloadsPath(),"record.mp4")
if (videoFile.exists()){
videoFile.delete()
}
camera = Camera.open(0)
camera?.stopPreview()
camera?.unlock()
val profile = CamcorderProfile.get( 0, CamcorderProfile.QUALITY_480P )
// val sizeList = camera.parameters.supportedVideoSizes
// val videoSize = sizeList.first()
mMediaRecorder?.setCamera(camera)
mMediaRecorder?.setAudioSource(MediaRecorder.AudioSource.CAMCORDER)//设置音频输入源 也可以使用 MediaRecorder.AudioSource.MIC
mMediaRecorder?.setVideoSource(MediaRecorder.VideoSource.CAMERA)//设置视频输入源
mMediaRecorder?.setOutputFormat(profile.fileFormat)//音频输出格式
mMediaRecorder?.setAudioEncoder(profile.audioCodec)//设置音频的编码格式
mMediaRecorder?.setVideoEncoder(profile.videoCodec)//设置图像编码格式
mMediaRecorder?.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight)
mMediaRecorder?.setVideoFrameRate(profile.videoFrameRate)
mMediaRecorder?.setVideoEncodingBitRate(profile.videoBitRate)
mMediaRecorder?.setAudioEncodingBitRate(profile.audioBitRate)
mMediaRecorder?.setAudioSamplingRate(profile.audioSampleRate)
mMediaRecorder?.setAudioChannels(profile.audioChannels)
// mMediaRecorder?.setVideoFrameRate(20)//要录制的视频帧率 帧率越高视频越流畅 如果设置设备不支持的帧率会报错 按照注释说设备会支持自动帧率所以一般情况下不需要设置
// mMediaRecorder?.setVideoSize(1080,780)//设置录制视频的分辨率 如果设置设备不支持的分辨率会报错
// mMediaRecorder?.setVideoEncodingBitRate(5 * 100 * 100) //设置比特率,比特率是每一帧所含的字节流数量,比特率越大每帧字节越大,画面就越清晰,算法一般是 5 * 选择分辨率宽 * 选择分辨率高,一般可以调整5-10,比特率过大也会报错
// mMediaRecorder?.setOrientationHint(360)//设置视频的摄像头角度 只会改变录制的视频文件的角度(对预览图像角度没有效果)
val surface = Surface(textureView.getSurfaceTexture())
mMediaRecorder?.setOutputFile(videoFile.getAbsolutePath())//MP4文件保存路径
mMediaRecorder?.setPreviewDisplay(surface)//设置拍摄预览
}
fun startRecorder(textureView: TextureView) {
try {
MyPermissionUtils.requestMicrophonePermissions(object: PermissionUtils.SimpleCallback{
override fun onGranted() {
MyPermissionUtils.requestCameraPermissions(object: PermissionUtils.SimpleCallback{
override fun onGranted() {
try {
configMediaRecorder(textureView) //配置MediaRecorder 因为每一次停止录制后调用重置方法后都会取消配置,所以每一次开始录制都需要重新配置一次
mMediaRecorder!!.prepare() //准备
mMediaRecorder!!.start() //开启
isRecording = true
started = true
} catch (e: Exception) {
ToastUtils.showShort(e.message)
e.printStackTrace()
}
}
override fun onDenied() {
ToastUtils.showShort("请开启录像权限")
}
})
}
override fun onDenied() {
ToastUtils.showShort("请开启录音权限")
}
})
} catch (e: IOException) {
e.printStackTrace()
}
}
fun stopRecorder() {
mMediaRecorder!!.stop() //暂停
mMediaRecorder!!.reset() //重置 重置后将进入空闲状态,再次启动录制需要重新配置MediaRecorder
camera?.stopPreview()
camera?.release()
camera?.lock()
isRecording = false
started = false
}
fun pauseRecorder() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mMediaRecorder!!.pause() //暂停
camera?.stopPreview()
isRecording = false
}
}
fun resumeRecorder() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mMediaRecorder!!.resume() //恢复
camera?.startPreview()
isRecording = true
}
}
fun destroy() {
if (mMediaRecorder != null) {
mMediaRecorder!!.stop()
mMediaRecorder!!.release() //释放 释放之前需要先调用stop()
// 摄像头关闭预览和释放
camera?.stopPreview()
camera?.release()
mMediaRecorder = null
}
instance = null
}
}