Android MediaRecorder在纵向模式下捕获视频

Android MediaRecorder在纵向模式下捕获视频,android,video,orientation,mediarecorder,Android,Video,Orientation,Mediarecorder,我正在尝试制作自定义视频应用程序。我仅使用清单2.2(API 8)中的设置工作。 一切顺利,但我不明白为什么肖像模式视频和lanscape视频没有区别 为了检测设备改变的方向,我在surfaceChanged()中使用此代码 工作起来很有魅力。如果我旋转设备表面改变方向,调用surfaceChanged,其中相机设置为适当的DisplayRotation 问题是以后如何确定是在lanscape模式下还是在纵向模式下捕获视频。正如我得到的,所有的视频都是横向拍摄的。它不依赖于仅影响预览过程的set

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

一切顺利,但我不明白为什么肖像模式视频和lanscape视频没有区别

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

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

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

在探索这个问题时,我注意到,如果使用标准摄像头应用程序,它会将特殊标记写入视频文件(见MediaInfo):旋转:90,用于拍摄人像视频

但MediaRecorder类没有

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

找到了! 事实上,你可以改变预览,你可以标记视频,但没有办法真正改变视频。。。(可能是速度问题或其他问题)

要旋转预览,请执行以下操作:

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();

希望有帮助;-)

camera.setDisplayOrientation(90)不能在所有设备中工作。下面的解决方案在不同的设备上可以完美地工作,还可以处理marshmallow运行时权限

请参见设置摄影机旋转方法

现在准备好正确旋转的媒体录像机,以便以正确的方向播放录制的视频

mediaRecorder.setOrientationHint(CameraPreview.rotate)

专用布尔值prepareMediaRecorder(){


您可以下载完整的示例

setOrientationHint仅适用于API 9。我也有同样的问题,但需要API 8的解决方案。我花了几个小时试图解决这个愚蠢的预览方向问题。非常感谢@Taiko!以下是对我有效的方法:在实现
SurfaceHolder.Cal的类的
onCreate
方法中lback
我包括以下代码:
mCamera=Camera.open();mCamera.setDisplayOrientation(90);mCamera.unlock();
后跟
mediaRecorder=new mediaRecorder();mediaRecorder.setCamera(mCamera);
。效果很好!setOrientationHint没有帮助-视频是旋转的(请编辑此零件//创建曲面并启动相机预览,如果(mCamera==null){mCamera.setPreviewDisplay(holder);mCamera.startPreview();}它应该是mCamera!=null)
recorder.setOrientationHint(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();
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 = 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;

}