android - 从已经运行的预览中录制视频

标签 android camera mediarecorder

各位 Android 开发者大家好。我正在开发一个应用程序,它使用相机来显示连续预览,并且当用户愿意时,从该源录制视频并保存。

我已经设置了第一部分,但我在录音工作时遇到问题。我遵循了各种指南和答案来解决我遇到的问题,但我似乎总是遇到“无效状态”问题(当前 setCamera 在无效状态下调用(4))。

这是我的完整代码。感谢您的浏览!

Camera camera;
SurfaceView preview;
SurfaceHolder previewHolder;
MediaRecorder recorder;
boolean recording = false;
boolean cameraConfigured = false;
private Button camera_button;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    //Remove title bar
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);

    //Remove notification bar
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

    //Keep screen awake
    this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    setContentView(R.layout.activity_fullscreen);

    preview = (SurfaceView)findViewById(R.id.camerapreview);        
    previewHolder = preview.getHolder();
    previewHolder.addCallback(surfaceCallback);
    previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    camera_button = (Button) findViewById(R.id.camera_button);

    camera_button.setOnClickListener(new OnClickListener()
    {
        @Override
        public void onClick(View view)
        {
            if (recording) 
            {
                recorder.stop();
                recording = false;

                initRecorder();
                prepareRecorder();

                camera_button.setText("Record");
            } 
            else 
            {
                recording = true;
                recorder.start();

                camera_button.setText("Stop");
            }
        }
    });

    // Wake screen
    WakeLock screenLock = ((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(
             PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");
    screenLock.acquire();
    screenLock.release();
}

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

    if (camera == null) 
    {
        camera = Camera.open();         
    }

    preview.setVisibility(View.VISIBLE);
    startPreview();
}

@Override
public void onPause() 
{       
    if(camera != null)
    {           
        camera.stopPreview();
        camera.release();
        camera = null;
        cameraConfigured = false;           
    }

    preview.setVisibility(View.INVISIBLE);

    super.onPause();
}

SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() 
{
    public void surfaceCreated(SurfaceHolder holder) 
    {
        initRecorder();
        prepareRecorder();          
    }

    public void surfaceChanged(SurfaceHolder holder, int format,
                               int width, int height)
    {
        initPreview(width, height);
        startPreview();
    }

    public void surfaceDestroyed(SurfaceHolder holder) 
    {
        if (recording) 
        {
            recorder.stop();
            recording = false;
        }
        recorder.release();
    }
};


private void initRecorder() 
{
    recorder = new MediaRecorder();     

    recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
    recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);

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

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    recorder.setOutputFile("/sdcard" + File.separator + "testVideo_" + timeStamp + ".mp4");  

    camera.unlock();
    recorder.setCamera(camera);
}

private void prepareRecorder() 
{
    recorder.setPreviewDisplay(previewHolder.getSurface());

    try 
    {
        recorder.prepare();
    } 
    catch (IllegalStateException e) 
    {
        e.printStackTrace();

    } 
    catch (IOException e) 
    {
        e.printStackTrace();

    }
}

private void initPreview(int width, int height) 
{
    if (camera != null && previewHolder.getSurface() != null) 
    {
        try 
        {
            camera.setPreviewDisplay(previewHolder);
        }
        catch (Throwable t) 
        {
            Log.e("CameraTest","");
        }

        if (!cameraConfigured)
        {
            Camera.Parameters parameters=camera.getParameters();
            Camera.Size size = getBestPreviewSize(width, height, parameters);
            Camera.Size pictureSize = getSmallestPictureSize(parameters);

            if (size != null && pictureSize != null) 
            {
                parameters.setPreviewSize(size.width, size.height);
                parameters.setPictureSize(pictureSize.width,
                                            pictureSize.height);

                parameters.set("cam_mode", 1 );
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
                parameters.setPictureFormat(ImageFormat.JPEG);
                camera.setParameters(parameters);
                cameraConfigured=true;
            }
        }
    }           
}

private void startPreview() 
{
    if (cameraConfigured && camera != null) 
    {
        camera.startPreview();
    }
}

public Camera.Size getBestPreviewSize(int width, int height,
        Camera.Parameters parameters) 
{       
    Camera.Size result=null;

    for (Camera.Size size : parameters.getSupportedPreviewSizes()) 
    {
        if ((size.width <= width && size.height <= height) || (size.height <= width && size.width <= height)) 
        {
            if (result == null) 
            {
                result=size;
            }
            else 
            {
                int resultArea=result.width * result.height;
                int newArea=size.width * size.height;

                    if (newArea > resultArea) 
                    {
                        result=size;
                    }
            }
        }
    }

    return(result);


}

public Camera.Size getSmallestPictureSize(Camera.Parameters parameters) 
{
    Camera.Size result=null;

    for (Camera.Size size : parameters.getSupportedPictureSizes()) 
    {
        if (result == null) 
        {
            result=size;
        }
        else 
        {
            int resultArea=result.width * result.height;
            int newArea=size.width * size.height;

            if (newArea < resultArea) 
            {
                result=size;
            }
        }
    }
    return(result);
}

最佳答案

查看 android video recording sample code ,android需要一个非常特定的顺序来配置mediaRecorder。在我看来,你应该按如下方式安排你的 initRecorder() :

private void initRecorder() 
{
    recorder = new MediaRecorder();
    // The following two lines should precede setAudioSource line
    camera.unlock();
    recorder.setCamera(camera);

    recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
    recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);

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

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    recorder.setOutputFile("/sdcard" + File.separator + "testVideo_" + timeStamp + ".mp4");  
}

关于android - 从已经运行的预览中录制视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22055450/

相关文章:

java - 如何发送带有 HTML 标签的短信?

c++ - EDSDK 3.4.0 on OS X 10.12.1 with Rebel t6i : `kEdsObjectEvent_DirItemCreated` event is not received for up to 30 seconds after photo is taken

android - 如何使用 MediaRecorder 获取每个录音频率?

android - 如何设置带缺口显示的媒体记录器的大小

android - 使用 MAJOR.MINOR.PATCH 转换为 Android Manifest 中版本代码的整数

android - 单击按钮时无法取消异步任务

android - 为 SearchView 设置 setOnQueryTextListener 会给出空指针异常

Swift 相机应用程序 - 启用横向模式右/左

java - 如何将播放器置于 libgDX 相机的中心

android:在模拟器上使用 MediaPlayer 录制音频