MediaRecorder 保存与 SurfaceView 大小相同的视频

Posted

技术标签:

【中文标题】MediaRecorder 保存与 SurfaceView 大小相同的视频【英文标题】:MediaRecorder saving video the same size as the SurfaceView 【发布时间】:2017-02-03 01:03:21 【问题描述】:

您好,我正在尝试在我的应用中实现录制。我可以录制视频并保存,但宽高比和分辨率完全搞砸了。我怎样才能知道以可用的最高质量注册?

这是我的代码

public class VideoFragment extends Fragment implements SurfaceHolder.Callback
    private ToggleButton mToggleButton;
    private SurfaceHolder mHolder;
    private SurfaceView mSurfaceView;
    private MediaRecorder mMediaRecorder;
    private Camera mCamera;
    private boolean mInitSuccesful;

    public static VideoFragment newInstance() 
        Bundle args = new Bundle();
        VideoFragment fragment = new VideoFragment();
        fragment.setArguments(args);
        return fragment;
    

    public VideoFragment()

    @Override
    public void onStart() 
        super.onStart();
        getActivity().setTitle(R.string.video);
    

    @Override
    public void onResume() 
        super.onResume();


    

    @Override
    public void onPause() 
        super.onPause();
        shutdown();
    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
        View rootView = inflater.inflate(R.layout.fragment_content, container, false);

        Button yo = (Button) rootView.findViewById(R.id.pic);
        yo.setVisibility(View.GONE);


        mSurfaceView = (SurfaceView) rootView.findViewById(R.id.cameraView);
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        mToggleButton = (ToggleButton) rootView.findViewById(R.id.toggleRecordingButton);
        mToggleButton.setOnClickListener(new View.OnClickListener() 
            @Override
            // toggle video recording
            public void onClick(View v) 

                if (((ToggleButton)v).isChecked())
                    if(mMediaRecorder == null) 
                        try 
                            initRecorder(mHolder.getSurface());
                         catch (IOException e) 
                            e.printStackTrace();
                        
                    else
                        try 
                            mMediaRecorder.start();
                        catch (NullPointerException e)
                            e.printStackTrace();
                            try 
                                initRecorder(mHolder.getSurface());
                             catch (IOException ex) 
                                ex.printStackTrace();
                            
                        
                    
                else 
                    mMediaRecorder.stop();
                    mMediaRecorder.reset();
                    try 
                        initRecorder(mHolder.getSurface());
                     catch (IOException e) 
                        e.printStackTrace();
                    
                


            
        );

        return rootView;
    

    /* Init the MediaRecorder, the order the methods are called is vital to
     * its correct functioning.
     */
    private void initRecorder(Surface surface) throws IOException 
        // It is very important to unlock the camera before doing setCamera
        // or it will results in a black preview
        if(mCamera == null) 
            mCamera = Camera.open();
            mCamera.unlock();
        

        if(mMediaRecorder == null)
            mMediaRecorder = new MediaRecorder();

        mMediaRecorder.setPreviewDisplay(surface);
        mMediaRecorder.setCamera(mCamera);

        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
        File file = new File(Environment
                .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                Utils.getVideoFilename());
        // "touch" the file
        if(!file.exists()) 
            File parent = file.getParentFile();
            if(parent != null)
                if(!parent.exists())
                    if(!parent.mkdirs())
                        throw new IOException("Cannot create " +
                                "parent directories for file: " + file);

            file.createNewFile();
        

        mMediaRecorder.setOutputFile(file.getAbsolutePath());

        // No limit. Don't forget to check the space on disk.
        mMediaRecorder.setMaxDuration(-1);
        mMediaRecorder.setVideoFrameRate(15);

        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);

        try 
            mMediaRecorder.prepare();
         catch (IllegalStateException e) 
            // This is thrown if the previous calls are not called with the
            // proper order
            e.printStackTrace();
        

        mInitSuccesful = true;
    

    @Override
    public void surfaceCreated(SurfaceHolder holder) 
        try 
            if(!mInitSuccesful)
                initRecorder(mHolder.getSurface());
         catch (IOException e) 
            e.printStackTrace();
        
    

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) 

    

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) 
        shutdown();
    



    private void shutdown() 
        // Release MediaRecorder and especially the Camera as it's a shared
        // object that can be used by other applications
        mMediaRecorder.reset();
        mMediaRecorder.release();
        mCamera.release();

        // once the objects have been released they can't be reused
        mMediaRecorder = null;
        mCamera = null;
    

谢谢

编辑: 解决方案感谢接受的答案

CamcorderProfile cpHigh = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
mMediaRecorder.setProfile(cpHigh);

【问题讨论】:

【参考方案1】:

先尝试使用CamcorderProfile 设置所有MediaRecorder 分辨率和质量设置;您当前没有设置许多值,例如大小。一方面,MediaRecorder 不会关注 SurfaceView 的尺寸。

【讨论】:

以上是关于MediaRecorder 保存与 SurfaceView 大小相同的视频的主要内容,如果未能解决你的问题,请参考以下文章

Android 10 源码MediaRecorder 录像流程:MediaRecorder 配置

Surface 视图显示黑屏以进行视频预览

网页录像录音功能的实现之MediaRecorder的使用

将Surface保存到位图并在C#中优化DirectX屏幕捕获

使用 MediaRecorder 将音频和视频流合并为一个文件 [重复]

如何使用 mediaRecorder 流式传输 android 的内部音频+屏幕?