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

    xiaoxiao2021-04-16  32

    第一次写自己的技术博客,本人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开发的经验~么么哒

    转载请注明原文地址: https://ju.6miu.com/read-672085.html

    最新回复(0)