安卓api提供了Camera类控制相机捕获图像,在api21以后,安卓也提供了Camera2,Camera变得过时了,但为了兼容性,这里还是使用Camera。
对于录制视频,可以使用MediaRecorder,这个可看安卓官方api文档
使用Camera进行拍照摄像前,你得先申请权限:
- <uses-permission android:name="android.permission.CAMERA" />
- <uses-permission android:name="android.permission.RECORD_AUDIO" />
- <uses-feature android:name="android.hardware.camera"/>
- <uses-feature android:name="android.hardware.camera.autofocus"/>
接着,是相机预览流程:
Camera.open(int)获取Camera实例
setParameters设置相机参数
setDisplayOrientation设置正确预览方向
关联SurfaceView,用于展示预览画面
startPreview开始预览,stopPreview停止预览
release释放相机资源
录像流程:
创建MediaRecorder对象,用于录制音频视频
关联MediaRecorder和Camera,捕获从Camera传来的画面
设置MediaRecorder相关参数,视频格式、编码、大小等等
setOrientationHint可设置视频最终旋转角度
start开始录制,stop停止录制
release释放资源
为了防止篇幅过长,我这里就不展示全部代码了,详细代码请可以留言
接下来我会就其中一些关键点列举出来:
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓
视频质量直接影响视频清晰度和文件大小,这个可以根据个人需求调整,码率不宜过小也不宜过大。
- /**
- * 获取适合的视频质量配置
- * 影响视频清晰度和文件大小,根据自身需要调整
- * @param cameraID 摄像头ID
- */
- fun getBestCamcorderProfile(cameraID: Int): CamcorderProfile? {
- var profile: CamcorderProfile? = null
- when {
- CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_1080P) -> { //1080P,优先
- profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_1080P)
- }
- CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_720P) -> { //720P
- profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_720P)
- }
- CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_480P) -> { //480P
- profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_480P)
- }
- CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_HIGH) -> {//高品质
- profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_HIGH)
- profile.videoBitRate /= 8
- return profile
- }
- CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_CIF) -> {
- profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_CIF)
- return profile
- }
- CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_QVGA) -> {
- profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_QVGA)
- }
- CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_LOW) -> {
- profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_LOW)
- }
- }
- if (profile != null) {
- //视频码率
- profile.videoBitRate = 6000000
- }
- return profile
- }
视频预览角度
- /**
- * 根据屏幕方向获取对应预览角度
- * setDisplayOrientation只能改变预览的角度,与视频最终结果角度无关
- * @param cameraID 相机ID
- */
- fun getCameraPreviewOrientation(cameraID: Int, activity: Activity): Int {
- val info = Camera.CameraInfo();
- Camera.getCameraInfo(cameraID, info);
- //屏幕选择角度
- val rotation = activity.windowManager.defaultDisplay.rotation
- var degrees = 0
- when (rotation) {
- Surface.ROTATION_0 ->
- degrees = 0
- Surface.ROTATION_90 ->
- degrees = 90
- Surface.ROTATION_180 ->
- degrees = 180
- Surface.ROTATION_270 ->
- degrees = 270
- }
- var result = 90
- if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
- result = (info.orientation + degrees) % 360
- result = (360 - result) % 360
- } else {
- result = (info.orientation - degrees + 360) % 360
- }
- return result;
- }
相机预览
- /**
- * 初始化相机设置并开启预览
- */
- private fun startPreview() {
- try {
- //开启后置摄像头
- camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK)
- //设置预览角度
- val rotation = CameraUtil.getCameraPreviewOrientation(Camera.CameraInfo.CAMERA_FACING_BACK,this)
- camera?.setDisplayOrientation(rotation)
- // 在SurfaceView上预览
- camera?.setPreviewDisplay(sv_camera.holder)
- val parameters = camera?.getParameters()
- //获取支持的预览大小,注意这里获取的宽高是根据横屏的
- val sizes = parameters?.supportedPreviewSizes
- //宽高建议根据横竖屏切换
- val previewSize =
- CameraUtil.findFitPreviewSize(sv_camera.height,sv_camera.width,sizes)
- if (previewSize != null) {
- //设置预览大小
- parameters?.setPreviewSize(previewSize.width, previewSize.height)
- }
- //设置自动对焦模式
- CameraUtil.setAutoFocusMode(parameters)
- camera?.setParameters(parameters)
- //开始预览
- camera?.startPreview()
- } catch (e: Exception) {
- Log.e("Test", "出错了", e)
- }
- }
视频录制
- /**
- * 开始录制
- * 注意方法调用的先后顺序
- */
- private fun startRecorder() {
- if (camera == null) {
- return
- }
- if (recorder != null) {
- stopRecord()
- }
- try {
- val videoSize = CameraUtil.findFitVideoSize(camera!!.parameters,
- sv_camera.height / sv_camera.width.toFloat()
- )
- //先停止camera预览,释放camera
- camera?.stopPreview()
- camera?.unlock()
- //创建MediaRecorder对象
- recorder = MediaRecorder()
- //关联camera
- recorder?.setCamera(camera)
- //设置视频角度;
- val rotation =
- CameraUtil.getCameraPreviewOrientation(Camera.CameraInfo.CAMERA_FACING_BACK, this)
- recorder?.setOrientationHint(rotation)
- //设置预览区域
- recorder?.setPreviewDisplay(sv_camera.holder.surface)
- //设置音频来源
- recorder?.setAudioSource(MediaRecorder.AudioSource.MIC)
- //设置视频来源,来自摄像头
- recorder?.setVideoSource(MediaRecorder.VideoSource.CAMERA)
-
- //设置输出格式
- // recorder?.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
- val profile = CameraUtil.getBestCamcorderProfile(Camera.CameraInfo.CAMERA_FACING_BACK)
- if (profile != null) {
- //设置视频码率
- recorder?.setProfile(profile)
- }
- //设置视频帧率,注意设备支持
- recorder?.setVideoFrameRate(30)
- //设置视频宽高
- recorder?.setVideoSize(videoSize.width, videoSize.height)
- val file =
- File(getExternalFilesDir(Environment.DIRECTORY_MOVIES)?.absolutePath, "test.mp4")
- //设置音频文件的存储位置 {
- recorder?.setOutputFile(file.absolutePath)
- //准备
- recorder?.prepare()
- //开始录制
- recorder?.start()
- ct_time.start()
- } catch (e: Exception) {
- Log.e("Test", e.message, e)
- }
- }
以上就是Camera+MediaRecord录制视频的方法!有问题大家提出来讨论一下。
如果你对音视频开发感兴趣,觉得文章对您有帮助,别忘了点赞、收藏哦!或者对本文的一些阐述有自己的看法,有任何问题,欢迎在下方评论区讨论!
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓