【问题标题】:MediaRecorder video capturing in portrait modeMediaRecorder 以纵向模式拍摄视频
【发布时间】:2012-08-13 03:42:46
【问题描述】:

我正在尝试制作自定义视频应用。我使用清单中的设置仅 2.2 (API 8)。

一切顺利,但我不明白为什么纵向模式视频与横向模式没有区别。

为了检测设备改变方向,我在 surfaceChanged() 中使用此代码

        if (mCamera != null) {

        Camera.Parameters p = mCamera.getParameters();

        try {
            mCamera.stopPreview();
        } catch (Exception e) {
            // TODO: handle exception
        }

        int previewWidth = 0;
        int previewHeight = 0;

        if (mPreviewSize != null) {
            Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            int rotation = display.getRotation();

            switch (rotation) {
            case Surface.ROTATION_0:
                previewWidth = mPreviewSize.height;
                previewHeight = mPreviewSize.width;
                mCamera.setDisplayOrientation(90);
                break;

            case Surface.ROTATION_90:
                previewWidth = mPreviewSize.width;
                previewHeight = mPreviewSize.height;
                mCamera.setDisplayOrientation(0);
                break;

            case Surface.ROTATION_180:
                previewWidth = mPreviewSize.height;
                previewHeight = mPreviewSize.width;
                mCamera.setDisplayOrientation(270);
                break;

            case Surface.ROTATION_270:
                previewWidth = mPreviewSize.width;
                previewHeight = mPreviewSize.height;
                mCamera.setDisplayOrientation(180);
                break;
            }

            p.setPreviewSize(previewWidth, previewHeight);
            mCamera.setParameters(p);
        }
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        Log.d(TAG, "Cannot start preview.", e);
    }
}

像魅力一样工作。如果我旋转设备表面改变方向,调用surfaceChanged,其中相机设置为适当的DisplayRotation。

问题是以后如何确定视频是以横向模式还是纵向模式捕获的。正如我得到的所有视频都是以横向拍摄的。它不依赖于仅影响预览过程的 setDisplayOrientation。

在探索问题的同时,我注意到如果使用标准相机应用程序,它会将特殊标签写入视频文件(在 MediaInfo 中看到):Rotation : 90 用于拍摄人像视频。

但 MediaRecorder 类没有。

看来这就是问题所在。有人要解决这个问题吗?

【问题讨论】:

    标签: android video orientation mediarecorder


    【解决方案1】:

    camera.setDisplayOrientation(90) 不适用于所有设备。以下解决方案在不同设备中完美运行,并且还处理棉花糖运行时权限。

    查看 setCameraRotation 方法

    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private Camera mCamera;
        public static int rotate;
        private Context mContext;
    
        public CameraPreview(Context context, Camera camera) {
            super(context);
            mCamera = camera;
            mHolder = getHolder();
            mHolder.addCallback(this);
            // deprecated setting, but required on Android versions prior to 3.0
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            mContext = context;
        }
    
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                // create the surface and start camera preview
                if (mCamera != null) {
                    mCamera.setPreviewDisplay(holder);
                    mCamera.startPreview();
                }
            } catch (IOException e) {
                Log.d(VIEW_LOG_TAG, "Error setting camera preview: " + e.getMessage());
            }
        }
    
        public void refreshCamera(Camera camera) {
            if (mHolder.getSurface() == null) {
                // preview surface does not exist
                return;
            }
            // stop preview before making changes
            stopPreview();
            // set preview size and make any resize, rotate or
            // reformatting changes here
            setCamera(camera);
    
            // start preview with new settings
            startPreview();
        }
    
        public void stopPreview(){
            try {
                if(mCamera != null)
                mCamera.stopPreview();
            } catch (Exception e) {
                // ignore: tried to stop a non-existent preview
                e.printStackTrace();
            }
        }
    
        public void startPreview(){
            try {
                if(mCamera != null) {
                    mCamera.setPreviewDisplay(mHolder);
                    mCamera.startPreview();
                }else{
                    Log.d(VIEW_LOG_TAG, "Error starting camera preview: " );
                }
            } catch (Exception e) {
                Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
            }
        }
    
        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            // If your preview can change or rotate, take care of those events here.
            // Make sure to stop the preview before resizing or reformatting it.
            refreshCamera(mCamera);
        }
    
        public void setCamera(Camera camera) {
            //method to set a camera instance
            mCamera = camera;
            /**
             * add camera orientation and display rotation according to screen landscape or portrait
             */
            setCameraRotation();
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            // TODO Auto-generated method stub
            if(mCamera != null){
                mCamera.release();
            }
    
        }
    
        public void setCameraRotation() {
            try {
    
                Camera.CameraInfo camInfo = new Camera.CameraInfo();
    
                if (VideoCaptureActivity.cameraId == 0)
                    Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, camInfo);
                else
                    Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, camInfo);
                int cameraRotationOffset = camInfo.orientation;
                // ...
    
                Camera.Parameters parameters = mCamera.getParameters();
    
    
                int rotation = ((Activity)mContext).getWindowManager().getDefaultDisplay().getRotation();
                int degrees = 0;
                switch (rotation) {
                    case Surface.ROTATION_0:
                        degrees = 0;
                        break; // Natural orientation
                    case Surface.ROTATION_90:
                        degrees = 90;
                        break; // Landscape left
                    case Surface.ROTATION_180:
                        degrees = 180;
                        break;// Upside down
                    case Surface.ROTATION_270:
                        degrees = 270;
                        break;// Landscape right
                }
                int displayRotation;
                if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    displayRotation = (cameraRotationOffset + degrees) % 360;
                    displayRotation = (360 - displayRotation) % 360; // compensate
                    // the
                    // mirror
                } else { // back-facing
                    displayRotation = (cameraRotationOffset - degrees + 360) % 360;
                }
    
                mCamera.setDisplayOrientation(displayRotation);
    
    
                if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    rotate = (360 + cameraRotationOffset + degrees) % 360;
                } else {
                    rotate = (360 + cameraRotationOffset - degrees) % 360;
                }
    
                parameters.set("orientation", "portrait");
                parameters.setRotation(rotate);
                mCamera.setParameters(parameters);
    
            } catch (Exception e) {
    
            }
        }
    
    
    
    }
    

    现在准备正确旋转的媒体记录器,以便录制的视频以正确的方向播放。

    mediaRecorder.setOrientationHint(CameraPreview.rotate);

    私有布尔prepareMediaRecorder() {

        mediaRecorder = new MediaRecorder();
    
        mCamera.unlock();
        mediaRecorder.setCamera(mCamera);
    
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mediaRecorder.setOrientationHint(CameraPreview.rotate);
    
        mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
    
        mediaRecorder.setOutputFile(filePath);
        mediaRecorder.setMaxDuration(15000); // Set max duration 15 sec.
        mediaRecorder.setMaxFileSize(10000000); // Set max file size 1M
    
        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException e) {
            releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            releaseMediaRecorder();
            return false;
        }
        return true;
    
    }
    

    您可以下载完整的示例https://github.com/umesh-kushwaha/Android_Video_Recording_portrait

    【讨论】:

    • setOrientationHint 没有帮助 - 视频旋转(
    • 请编辑这部分 // 创建表面并开始相机预览 if (mCamera == null) { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } 它应该是 mCamera != null
    【解决方案2】:

    找到了! 确实,您可以更改预览,您可以标记视频,但是无法真正更改视频...(可能是速度问题或其他问题)

    camera.setDisplayOrientation(90);
    

    要旋转预览,然后

    recorder.setOrientationHint(90);
    

    将视频标记为 90° 旋转,然后手机会在阅读时自动旋转。

    所以你要做的就是

                camera = Camera.open();
            //Set preview with a 90° ortientation
            camera.setDisplayOrientation(90);
            camera.unlock();
    
            holder = getHolder();
            holder.addCallback(this);
            holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    
            recorder = new MediaRecorder();
            recorder.setCamera(camera);
            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
            recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
            recorder.setOutputFile(getVideoFolder()+rnd.nextString()+".mp4");
            recorder.setPreviewDisplay(holder.getSurface());
            //Tags the video with a 90° angle in order to tell the phone how to display it
            recorder.setOrientationHint(90);
    
            if (recorder != null) {
                try {
                    recorder.prepare();
                } catch (IllegalStateException e) {
                    Log.e("IllegalStateException", e.toString());
                } catch (IOException e) {
                    Log.e("IOException", e.toString());
                }
            }
    
            recorder.start();
    

    希望对你有帮助 ;-)

    【讨论】:

    • setOrientationHint 仅适用于 API 9。我有同样的问题,但需要 API 8 的解决方案。
    • 我花了几个小时试图找出这个愚蠢的预览方向问题。非常感谢@Taiko!这对我有用:在实现SurfaceHolder.Callback 的类的onCreate 方法中,我包含了以下代码:mCamera = Camera.open(); mCamera.setDisplayOrientation(90); mCamera.unlock();,后跟mediaRecorder = new MediaRecorder(); mediaRecorder.setCamera(mCamera);。像魅力一样工作!
    猜你喜欢
    • 2011-11-15
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多