Android Camera学习记录(一) 视频录制MediaRecorder

第一次写自己的技术博客,本人Android菜鸟一枚,写博客也只是为了记录自己学习过的东西,以便以后可以更容找到属于自己的资料。


最近一直在做Camera的开发,今天主要想将使用Camera录制视频的方法记录下来。

其实网上关于这方面的技术其实都有比较清晰的讲解,不过大部分都是讲一部分空一部分,所以就想着要整理综合一下。


   
   

   
   

    
    
    

    
    
    

    
    
    

    
    
    


   
   

这个布局基本上来说就是相对布局,只不过增加了一些显示功能而已~所以可以忽略不计,因为是功能测试的App,所以数据上也懒得用dimens来写了,就先将就这么看吧~哈哈~


好了,下面就可以进入主题,使用MediaRecorder进行视频的录制。

首先,我们需要使用Camera, 需要在AndroidManifest.xml中对使用权限进行申请,一般来说,使用camera功能都需要使用以下几个权限

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.HARDWARE" />

首先先是对Camera的设置,这里使用的是谷歌大大不推荐使用的Camera,而并非Camera2,童鞋们要注意咯~

public void preview() {
		try {
			camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); // 使用后置摄像头
			camera.setDisplayOrientation(90); // 镜头顺时旋转90度
			camera.setPreviewDisplay(VideoActivity.getHolder()); // 将SurfaceHolder给camera
			Camera.Parameters parameters = camera.getParameters();
			// 自动对焦
			List<String> focusModes = parameters.getSupportedFocusModes();
			if (focusModes != null) {
				for (String mode : focusModes) {
					mode.contains("continuous-video");
					parameters.setFocusMode("continuous-video");
				}
			}
			camera.setParameters(parameters);
			camera.startPreview();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}


这里需要注意的有三点

1:在我们使用Camera的时候,无论是预览还是最终得到的照片,都会逆时针的旋转90度,尤其是在预览模式下,预览的效果还是失真的效果,所以,我们需要用到

camera.setDisplayOrientation(90); // 将预览效果旋转90度
recorder.setOrientationHint(90); // 将获得的视频结果旋转90度
setOrientationHint()是针对MediaRecorder属性的设置,我们后面也会说到。

2:自动对焦的问题。我们发现如果不加这段代码,也是可以录制视频的,但是无论是预览还是最终得到的视频,都非常模糊。因此,你肯定会说,那就加上就好了。坑就在这里了,因为如果用了这段代码,某些手机得到的视频结果就会莫名其妙的产生马赛克,如果说一直保持一个位置还好,如果运动拍摄的话,这个问题就会非常的明显。因为我手头只有4款Android测试机,所以没有办法说到底哪几种机型会出现这样的结果,不过就现有测试的结果来说,小米的机器就会出现这个问题,不知道有没有大神可以帮忙解决这个蛋疼的问题呢?

// 自动对焦
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes != null) {
	for (String mode : focusModes) {
		mode.contains("continuous-video");
		parameters.setFocusMode("continuous-video");
	}

3:关于代码顺序的问题。在谷歌开发文档里面其实已经强调了这方面的问题,有关Camera属性设置,必须严格按照谷歌所给的顺序进行设置,否则会触发各种各样的BUG。


接下来就在Activity中将surfaceView设置好,并获得SurfaceHolder传给我们已经写好的函数中,完成Camera初始化。

具体的SurfaceHolder的设置这里就跳过了,不过还需要强调的一点是,我建议大家在设置SurfaceHolder的时候加入

holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);


加入这个之后,你就发现原本会卡顿的浏览界面变得流畅了很多。


之后就是在holder中添加CallBack,然后可以在surfaceChanged或者surfaceCreate中设置Camera的属性,即调用上方的函数即可。

private SurfaceHolder.Callback mSurfaceHolder = new SurfaceHolder.Callback() {
		
		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
		}
		
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
		}
		
		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			videoManager.preview();
		}
	};


OK,完事具备,只欠最后的录制了。过程中的设置控件监听啥基础的东西,宝宝我就直接跳过了哈~

总算是要讲到今天的主题MediaRecorder了

			recorder = new MediaRecorder();
			recorder.reset();
			recorder.setCamera(camera);
			// 选择角度(视频结果)
			recorder.setOrientationHint(90);
			// 设置采集图像
			recorder.setVideoSource(Camera.CameraInfo.CAMERA_FACING_BACK);
			// 设置视频的输出格式
			recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
			// 设置视频编码格式
			recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
			// 设置视频质量
			CamcorderProfile profile = CamcorderProfile
					.get(CamcorderProfile.QUALITY_HIGH);
			// 设置高质量录制, 改变码率
			recorder.setVideoEncodingBitRate(5 * 1024 * 1024);
			// 设置分辨率
			recorder.setVideoSize(profile.videoFrameWidth,
					profile.videoFrameHeight);
			// 设置帧率
			recorder.setVideoFrameRate(60);
			// 保存到文件中(路径)
			saveFile = new File(Environment.getExternalStorageDirectory()
					.getCanonicalFile()
					+ "/"
					+ System.currentTimeMillis()
					+ ".mp4");
			recorder.setOutputFile(saveFile.getAbsolutePath());
			// 设置预览显示区
			recorder.setPreviewDisplay(VideoActivity.getHolder().getSurface());
			recorder.prepare();
			recorder.start();


基本上来说,每一个API我都加上了注释,看的还是应该比较清晰的,不过这里还是需要提及几点需要注意的点:

1:之前在将Camera的时候就有强调过代码顺序的问题,这里同样也是需要注意这个问题的,尤其是编码格式后面的几个属性,最好是不要随意的修改代码的顺序;

2:我看到很多博主都有写到

// 设置分辨率
recorder.setVideoSize(profile.videoFrameWidth,profile.videoFrameHeight);
这个API的问题,后面跟着的两个宽高值不外乎都是640,480,我也试过写大于这两个数值的参数,均会报错,因此一开始也是默认认为这两个参数是一个最大可选参数,可是亲们也看到了,最后我并没有指定这两个参数,而是使用CamcorderProfile获取宽高。这是由于我在打印日志的时候发现,这两个值是可以到达1080或者1280的,因此可以极大的提高视频的质量,可是具体是为什么宝宝也没有搞明白,是否有哪个大神出来解释一下捏,嘿嘿~

3:另外,对于帧率和码率来说,其实并没有必要设置的这么高,只是由于宝宝的这个App适用于图像识别处理,所以对图像质量的要求比较高,因此设置的比较高。

最后,当我们停止录制的时候,要将MediaRecorder清空重置,便于下次的使用


public void stopVideo() {
		try {
			releaseMedioRecorder();
		} catch (Exception e) {
		}
	}

	private void releaseMedioRecorder() {
		if (recorder != null) {
			recorder.reset();
			recorder.release();
			recorder = null;
			camera.lock();
		}
	}

当然在整个程序关闭的时候,我们还需要将Camera释放,便于其他进程的使用

public void releaseCamera() {
		if (camera != null) {
			camera.release();
			camera = null;
		}
	}


第一次写东西哈,有什么问题希望各位大大指正哈~嘿嘿~以后应该也是会不定期更新博客,希望可以多多和大家交流Android开发的经验~么么哒


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值