Grabar vídeo con Android de vista de superficie

Tengo que crear una aplicación para Android en la que estoy tratando de grabar vídeo y capturar la imagen con la vista de la superficie. Hasta ahora soy capaz de capturar vídeo pero frente a problemas en el video de grabación. Mi código para la grabación de vídeo es –

onCreate(){ .. surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); startRecording(); . . } protected void startRecording() throws IOException { if(mCamera==null) mCamera = Camera.open(); String filename; String path; path= Environment.getExternalStorageDirectory().getAbsolutePath().toString(); Date date=new Date(); filename="/rec"+date.toString().replace(" ", "_").replace(":", "_")+".mp4"; File file=new File(path,filename); mrec = new MediaRecorder(); mCamera.lock(); mCamera.unlock(); mrec.setCamera(mCamera); mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA); mrec.setAudioSource(MediaRecorder.AudioSource.MIC); mrec.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mrec.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); mrec.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mrec.setPreviewDisplay(surfaceHolder.getSurface()); mrec.setOutputFile(path+filename); mrec.setMaxDuration(10000); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) { Camera.Parameters parameters = mCamera.getParameters(); parameters.setPreviewSize(width, height); try { mCamera.setPreviewDisplay(surfaceHolder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } mCamera.setParameters(parameters); mCamera.startPreview(); } 

Pero la aplicación se cierra cuando el código del método onSurfaceChange se llama en la línea – mCamera.setPreviewDisplay (surfaceHolder); Con excepción java.lang.RuntimeException: setParameters failed

Así que cómo puedo manejarlo así que puedo comenzar la grabación video. Gracias por adelantado.

Compruebe este código, ojalá que funcione.

 import java.io.IOException; import android.app.Activity; import android.content.pm.ActivityInfo; import android.hardware.Camera; import android.media.MediaRecorder; import android.os.Bundle; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.ToggleButton; public class MediaRecorderRecipe extends Activity implements SurfaceHolder.Callback { private final String VIDEO_PATH_NAME = "/mnt/sdcard/VGA_30fps_512vbrate.mp4"; private MediaRecorder mMediaRecorder; private Camera mCamera; private SurfaceView mSurfaceView; private SurfaceHolder mHolder; private View mToggleButton; private boolean mInitSuccesful; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.media_recorder_recipe); // we shall take the video in landscape orientation setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView); mHolder = mSurfaceView.getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mToggleButton = (ToggleButton) findViewById(R.id.toggleRecordingButton); mToggleButton.setOnClickListener(new OnClickListener() { @Override // toggle video recording public void onClick(View v) { if (((ToggleButton)v).isChecked()) { mMediaRecorder.start(); try { Thread.sleep(10 * 1000); // This will recode for 10 seconds, if you don't want then just remove it. } catch (Exception e) { e.printStackTrace(); } finish(); } else { mMediaRecorder.stop(); mMediaRecorder.reset(); try { initRecorder(mHolder.getSurface()); } catch (IOException e) { e.printStackTrace(); } } } }); } /* 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.DEFAULT); // mMediaRecorder.setOutputFormat(8); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mMediaRecorder.setVideoEncodingBitRate(512 * 1000); mMediaRecorder.setVideoFrameRate(30); mMediaRecorder.setVideoSize(640, 480); mMediaRecorder.setOutputFile(VIDEO_PATH_NAME); 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 surfaceDestroyed(SurfaceHolder holder) { shutdown(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {} 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; } 

Permisos

 <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-feature android:name="android.hardware.camera.autofocus" /> 

ARCHIVO XML

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ToggleButton android:id="@+id/toggleRecordingButton" android:layout_width="fill_parent" android:textOff="Start Recording" android:textOn="Stop Recording" android:layout_height="wrap_content" /> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent"> <SurfaceView android:id="@+id/surfaceView" android:layout_width="fill_parent" android:layout_height="fill_parent"></SurfaceView> </FrameLayout> </LinearLayout> 

Crear un archivo para guardar una imagen o un vídeo

 private static File getOutputMediaFile(int type){ // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp"); // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ Log.d("MyCameraApp", "failed to create directory"); return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; if (type == MEDIA_TYPE_IMAGE){ mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg"); } else if(type == MEDIA_TYPE_VIDEO) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4"); } else { return null; } return mediaFile; } 

Puede obtener una lista de tamaños de vista previa disponibles llamando a getSupportedPreviewSizes en el objeto Camera.Parameters devuelto por Camera.getParameters. Compruebe aquí

Agregue estos código debajo del método surfaceChanged

 Camera.Parameters parameters = camera.getParameters(); List<Camera.Size> sizes = parameters.getSupportedPreviewSizes(); Camera.Size cs = sizes.get(0); // You need to choose the most appropriate previewSize for your app. So select one from the list parameters.setPreviewSize(cs.width, cs.height); camera.setParameters(parameters); camera.startPreview(); 

EDIT Cambiar el método surfaceChanged como a continuación y comprobar

 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. Log.d("Function", "surfaceChanged"); if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.