【多媒体开发】Android视频全屏录制遇到的一些问题

最近写了个demo,有个功能是全屏录制视频,录视频的基本功能不算难,demo通过SurfaceView + MediaRecorder的方法, 这里不上代码了,只总结下一些问题:

1.Parameters参数问题
想通过getParameters获取Camera的参数,必须在Camera.unlock()方法前调用,否则会报错。

2.全屏录制
看了下网上的代码,大多数都是非全屏的,想要设置全屏,可以通过 MediaRecorder.setVideoSize(w, h)这个方法。但在使用时出现了挺多问题的。
1、如果设置的宽和高不是设备具备的尺寸时,一般会报错,提示说RuntimeException:start failed,所以在设置前先看下设备支持的尺寸。

2、查看设备尺寸可以通过getSupportedPreviewSizes的方法

Camera.Parameters parameters = mCamera.getParameters();
        List.Size> sizeList = parameters.getSupportedPreviewSizes();
        int width = sizeList.get(0).width;
        int height = sizeList.get(0).height;

得到的是一串列表,从测试上看,只有使用里面的宽高才不会报错,不同设备得到的列表排列不尽相同,下面是按width&height格式输出来的列表数据,
从小到大排列; 从大到小排列; 最后多了个莫名项排列;
这里写图片描述 这里写图片描述 这里写图片描述
从输出结果可以看出一个问题,我要以宽&高的输出,理论上讲应该是宽比高小,但图片上看是宽比高大。这是因为摄像头默认捕获的画面是横向的,由于手机上一般想竖屏使用,所以一般在调用系统相机时,预览时会设置setDisplayOrientation(90)来保持竖屏预览,录制时使用setOrientationHint来保持竖屏录制

if (mCurrentCamera == BACE_CAMERA) {
            mMediaRecorder.setOrientationHint(90);// 如果是后置摄像头,输出旋转90度,保持竖屏录制
        } else {
            mMediaRecorder.setOrientationHint(270);// 如果是前置摄像头,输出旋转270度,保持竖屏录制
        }

所以在使用setVideoSize (int width, int height)时,width也应该是使用默认的,也就是说全屏录制时,width应该是屏幕的高度,height是屏幕宽度。

3、所以要全屏录制,使用哪个参数呢?当然是用系统分辨率相同的宽高。测试的时候发现,基本上测试到的手机都支持系统分辨率的尺寸录制。我在application里已经先获取到设备的宽高了,所以在这里直接使用就行了。这里有个问题,我获取的宽高都是竖屏时的宽高,所以在用setVideoSize时,要互换一下,否则会报错,一般报start failed的错,但也会有手机是MediaRecorder的OnErrorListener里报error100的错误。

3.顺序问题
在初始化MediaRecorder时,设置参数需要按照一定的顺序。比说setVideoSize这个方法,看网上有些说要在setVideoEncoder之前调用,但我这样写时,会发现有些手机会直接卡死。这里放上我调用的顺序,测试上看暂时没发现什么问题

     if (mCamera == null) {
            return;
        }
        if (mMediaRecorder != null) {
            return;
        }

        mMediaRecorder = new MediaRecorder();
        mMediaRecorder.reset();
        mMediaRecorder.setCamera(mCamera);
        mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);      // 视频源
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);         // 音频源
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);    // 视频输出格式
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);    // 音频格式
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); // 视频录制格式
        mMediaRecorder.setVideoEncodingBitRate(5 * Constant.WIDTH_OF_SCREEN * Constant.WIDTH_OF_SCREEN);// 设置帧频率
        mMediaRecorder.setVideoFrameRate(30);   // 视频帧频率
        mMediaRecorder.setVideoSize(Constant.HEIGHT_OF_SCREEN, Constant.WIDTH_OF_SCREEN);  // 视频分辨率
        if (mCurrentCamera == BACE_CAMERA) {
            mMediaRecorder.setOrientationHint(90);// 如果是后置摄像头,输出旋转90度,保持竖屏录制
        } else {
            mMediaRecorder.setOrientationHint(270);// 如果是前置摄像头,输出旋转270度,保持竖屏录制
        }

        mMediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
            @Override
            public void onError(MediaRecorder mr, int what, int extra) {
                if (mr != null) {
                    mr.reset();
                }
                mListener.onFailed("MediaRecorder Error: what = " + what + ", extra = " + extra);
            }
        });
        mMediaRecorder.setOutputFile(mRecordFile.getAbsolutePath());          // 输出文件

        try {
            mMediaRecorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
            mListener.onFailed("MediaRecorder Error: " + e.toString());
        }
        mMediaRecorder.start();

录制出来的视频如果不清晰的话,可以通过setVideoEncodingBitRate这个方法,把参数调高就清晰了。
有些6.0的手机可能打不开录制界面,可以换成下面的方法。

  CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
        mMediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight); 

4.适配问题
适配问题一向有点难弄,这里只说全屏的适配。当我调用系统分辨率当做录制尺寸时,发现在一些大部分测试机上没问题,录制出来的都是全屏的视频,查了下视频分辨率,也和系统分辨率一样,但在一台乐视机和一台魅蓝上,却只录制出640 x 480的视频。最开始我以为是代码问题,于是用Nexus测试了下,测试用的Nexus分辨率是2392 x 1440,没想到录制出的视频是1920 x 1080的。于是又研究了好一会,最后发现Nexus的支持列表里没有2392 x 1440的,但它竟然没有报错!所以我猜想是它有可能是当不匹配支持的数据时,会向下取一个宽高比相似的进行录制,个人想法。
所以这也暴露了一个问题,有可能设备不支持屏幕分辨率的尺寸,也不能指望其它手机也能像Nexus一样不报错。所以这里最好做一下最优适配,也就是拿屏幕分辨率和设备支持的尺寸进行比对,如果找不到屏幕分辨率的尺寸,那就向下取宽高比最相似的一个。

至于有些手机上没能录制出全屏视频的这个问题,暂时还没想出什么办法解决。

5.其它
录制完成后想用MediaMetadataRetriever拿视频的数据,结果死活都拿不到,在播放页面又没问题,最后发现是调用顺序错了。忘了先把MediaRecorder关掉再拿数据。

你可能感兴趣的:(多媒体)