Android 纯原生视频录制 MediaRecorder+SurfaceView 采坑记录

最近因公司需求,在不依赖任何三方依赖的情况下,想到了用MediaRecorder+SurfaceView 来实现视频录制,虽然最后实现了,但是遇到的坑着实是多,如下:

坑1: 视频录制变形或者不清晰问题:

解决方法:   确保 parameters.setPreviewSize 和MediaRecorder类的setVideoSize 的尺寸一致,比例一致;

确保 setVideoSize 不能太小;   

这边我给出一个计算最佳分辨率的方法, 网上搜出来的方法排序是错误的,我这边给改了大小于号:

/*
     *作者:赵星海
     *时间:2019/4/30 11:53
     *用途:获取最佳分辨率
     */
    public void getXY() {
        //默认启动后置摄像头
        mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
        if (mCamera == null) {
            Toast.makeText(this, "未获取到相机!", Toast.LENGTH_SHORT).show();
            return;
        }
        Camera.Parameters parameter = mCamera.getParameters();
        List<Camera.Size> prviewSizeList = parameter.getSupportedPreviewSizes();
        List<Camera.Size> videoSizeList = parameter.getSupportedVideoSizes();

        //降序排列
        Collections.sort(videoSizeList, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size lhs, Camera.Size rhs) {
                if (lhs.width < rhs.width) {
                    return -1;
                } else if (lhs.width == rhs.width) {
                    return 0;
                } else {
                    return 1;
                }
            }
        });
        int index = 0;
        for (int i = 0; i < videoSizeList.size(); i++) {
            if (videoSizeList.get(i).width < prviewSizeList.get(0).width) {
                index = i;
            }
        }
        Video_W = videoSizeList.get(index).width;
        Video_H = videoSizeList.get(index).height;
        //parameter.setPreviewSize(prviewSizeList.get(0).width, prviewSizeList.get(0).height);
        parameter.setPreviewSize(Video_W, Video_H);

    }

log记录:

网上给出的计算方法结果:当前录制分辨率:176 - 144

我这边计算出来的结果:当前录制分辨率:1280 - 720    机型:小米note1

坑2: 前置摄像头预览为正向,输出的文件是倒立的图像:

解决方法:  

1.相机角度设置为90度 mCamera.setDisplayOrientation(90);

2.当前用后置摄像头录制的时候,mediaRecorder.setOrientationHint 设置成90度

   使用前置摄像头录制的时候,mediaRecorder.setOrientationHint 设置成270度

当然,要注意Hint 这个词!    这边只是给手机播放器一个角度标识,  其实物理角度看,前摄像头录的视频还是倒立的图像,

我这边用 mp4parser 这个三方库进行的视频合成,  当前后摄像头的视频混合合成的时候, 第一个视频的角度标识Orientation

会成为合成视频结果的角度标识,然后就会发现视频播放到前摄像头段落的时候是倒立的,反之亦然.

然后呢,深海和公司的CTO经过一番探索呢,想到了使用mp4parser的旋转功能,也就是如下代码

Movie movie = MovieCreator.build(ziPuth);
            movie.setMatrix(Matrix.ROTATE_90);

然并卵,最后去GItHub上看到这个三方框架作者的提问回答,作者这样说的:

There is an 'encoding' orientation. That's what the encoder thinks where
the top is. The mp4 container has an orientation as well which is basically
a matrix transforming (this case: rotating) the decoded picture. If your
two parts have different orientation on encoder level you cannot correct
that on mp4 level as this is applied globally to the full track.
Does that help you?

地址是:https://github.com/sannies/mp4parser/issues/130

最终我去看了movie.setMatrix(Matrix.ROTATE_90); 的源码,发现,底层也是改的OrientationHint  !    注意了啊,也就是说 这个旋转方式根本不是物理角度的旋转啊, 然并卵!!!    只是把你之前的OrientationHint270改成了90而已!

文章结尾,说一下终极的解决方案,但是太过麻烦,就是重写MediaRecorder相关的几大Android视频录像相关类!,然后用2D自己画,这是在GitHub上找到的方案:https://github.com/lumyus/FlexCam

发布了54 篇原创文章 · 获赞 212 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_39731011/article/details/89916909
今日推荐