2009-06-23 15 views
21

Me gustaría crear un grabador de video y hasta ahora no he descubierto cómo configurar los parámetros para pasar con éxito el método MediaRecorder.prepare().Android: ¿Alguien sabe cómo capturar video?

Ejecutando el siguiente método

public void start() throws IOException{ 
    String state = android.os.Environment.getExternalStorageState(); 
    if(!state.equals(Environment.MEDIA_MOUNTED)) 
    { 
     throw new IOException("SD card is not mounted. It is " + state + "."); 
    } 
    File directory = new File(path).getParentFile(); 
    if(!directory.exists() && !directory.mkdirs()) 
    { 
     throw new IOException("Path to file could not be created."); 
    } 

    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
    recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
    recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); 
    recorder.setVideoFrameRate(15); 
    recorder.setVideoSize(176, 144); 
    recorder.setOutputFile(path); 
    recorder.prepare(); 
    recorder.start(); 
    this.state = VideoRecorderState.STATE_RECORDING; 
} 

lanza una excepción en la línea recorder.prepare().

¿Alguien sabe cómo configurar los parámetros con el fin de ser capaz de capturar vídeo?

Gracias!

+0

No sé, pero me siento a gusto. Acabo de salir de algunos J2ME en esta área. ¡Temperamental por decir lo menos! –

+3

¿Cuál es la excepción? –

Respuesta

2

Quizás la aplicación de la cámara source te ayude a depurar esto.

1

Esto podría ser un error de permisos. ¿Tiene el permiso android.permission.CAMERA establecido en su archivo AndroidManifest?

13

Aquí hay un fragmento que funciona:

m_recorder = new MediaRecorder(); 
m_recorder.setPreviewDisplay(m_BeMeSurface); 
m_recorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
m_recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT); 
m_recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
m_recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
m_recorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); 
m_recorder.setMaxDuration((int) MAX_TIME); 
m_recorder.setOnInfoListener(m_BeMeSelf); 
m_recorder.setVideoSize(320, 240); 
m_recorder.setVideoFrameRate(15); 
m_recorder.setOutputFile(m_path); 

m_recorder.prepare(); 
m_recorder.start(); 

Lo más importante es la superficie. No lo tienes, entonces sin él falla.

Saludos

BeMeCollective

+1

He hecho una pregunta sobre el requisito de Superficie. . –

2

Ha comprobado esto?

http://code.google.com/p/android/issues/detail?id=5050

Estos chicos sugieren que se trata de un problema de tiempo, y que la máquina de estados MediaRecorder puede requerir un cierto retraso (dependiente del hardware?) Entre los estados.

Sería bueno si hubiera devoluciones de llamada para cuando cada estado se logró por completo, entonces podríamos simplemente prepararnos para eso.

0

En mi caso, copiar y pegar los ejemplos anteriores no funcionó. Luego, viendo los métodos en MediaRecorder, encontré setPreviewDisplay. Llamé a este método para pasar la superficie utilizada en Camera.setPreviewDisplay, la IOException en .prepare desapareció y pude grabar video. Pruébela y publique sus resultados.

4

Tenía la misma pregunta. Iba desde un servicio de grabación de audio en segundo plano y esperaba crear un servicio de grabación de video en segundo plano. No puede grabar realmente el video de fondo, pero puede hacer que la vista previa del video sea muy pequeña en su interfaz de usuario existente. Seguí el tutorial: http://integratingstuff.wordpress.com/2010/10/18/writing-code-that-captures-videos-on-android/ y la muestra de demostración de la cámara de muestra. Pero en última instancia, el código de muestra en http://www.apress.com/downloadable/download/sample/sample_id/39/ fue lo suficientemente simple como para navegar por Internet, pero también lo suficientemente completo como para funcionar con setCamera. Voy a publicar mi solución aquí para ahorrarles tiempo a otros en su progresión de ejemplos de juguetes, a un ejemplo complejo con buena calidad de grabación de video de fondo (usando la cámara frontal si es necesario).

Esta es la fuente para un grabador de video Android con "no" vista previa (la vista previa es un píxel de 1x1 que simula una grabación discreta), para grabar videos sin distraer a los usuarios. Para usar su propia IU, simplemente cambie el video_recorder.xml a su diseño (asegúrese de mantener VideoView). Fue probado en dispositivos Android 2.2 y 3.0.

casos de uso adecuados: biblioteca de seguimiento

  • ojo mirada para que los usuarios utilizan los ojos como un ratón para navegar por una página web
  • cámara (s) el uso de la tableta para reemplazar la cámara de vídeo en experimentos de laboratorio/clínica (psycholingusitics o patología del habla)

Layout XML:

<?xml version="1.0" encoding="utf-8"?> 
<!-- This file is /res/layout/video_recorder.xml based on listing 9-6 in Pro Android 2 --> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:orientation="vertical" android:layout_width="fill_parent" 
     android:layout_height="fill_parent"> 

    <RelativeLayout android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:gravity="center"> 

      <VideoView android:id="@+id/videoView" android:layout_width="1px" 
        android:layout_height="1px" /> 

    </RelativeLayout> 
</LinearLayout> 

clase de Java:

import java.io.File; 
import android.app.Activity; 
import android.hardware.Camera; 
import android.media.MediaRecorder; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 
import android.widget.Toast; 
import android.widget.VideoView; 
/** 
* Android video recorder with "no" preview (the preview is a 1x1 pixel which 
* simulates an unobtrusive recording led). Based on Pro Android 2 2010 (Hashimi 
* et al) source code in Listing 9-6. 
* 
* Also demonstrates how to use the front-facing and back-facing cameras. 
* A calling Intent can pass an Extra to use the front facing camera if available. 
* 
* Suitable use cases: 
* A: eye gaze tracking library to let users use eyes as a mouse to navigate a web page 
* B: use tablet camera(s) to replace video camera in lab experiments 
* (psycholingusitics or other experiments) 
* 
* Video is recording is controlled in two ways: 
* 1. Video starts and stops with the activity 
* 2. Video starts and stops on any touch 
* 
* To control recording in other ways see the try blocks of the onTouchEvent 
* 
* To incorporate into project add these features and permissions to 
* manifest.xml: 
* 
* <uses-feature android:name="android.hardware.camera"/> 
* <uses-feature android:name="android.hardware.camera.autofocus"/> 
* 
* <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
* <uses-permission android:name="android.permission.CAMERA" /> 
* <uses-permission android:name="android.permission.RECORD_AUDIO" /> 
* 
* Tested Date: October 2 2011 with manifest.xml 
* <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="11"/> 
*/ 
public class VideoRecorderSubExperiment extends Activity implements 
     SurfaceHolder.Callback { 
    public static final String EXTRA_USE_FRONT_FACING_CAMERA ="frontcamera"; 
    private static final String OUTPUT_FILE = "/sdcard/videooutput"; 
    private static final String TAG = "RecordVideo"; 
    private Boolean mRecording = false; 
    private Boolean mUseFrontFacingCamera = false; 
    private VideoView mVideoView = null; 
    private MediaRecorder mVideoRecorder = null; 
    private Camera mCamera; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.video_recorder); 
     mVideoView = (VideoView) this.findViewById(R.id.videoView); 

     //mUseFrontFacingCamera = getIntent().getExtras().getBoolean(
     //  EXTRA_USE_FRONT_FACING_CAMERA, true); 
     if(mUseFrontFacingCamera){ 
      // If caller wants to use front facing camera, then make sure the device has one... 
      // Hard coded to only open front facing camera on Xoom (model MZ604) 
      // For more universal solution try: 
      // http://stackoverflow.com/questions/2779002/how-to-open-front-camera-on-android-platform 
      String deviceModel = android.os.Build.MODEL; 
      if (deviceModel.contains("MZ604")) { 
       mUseFrontFacingCamera = true; 
      } else { 
       Toast.makeText(
         getApplicationContext(), 
         "The App isn't designed to use this Android's front facing camera.\n " + 
         "The device model is : " + deviceModel, Toast.LENGTH_LONG).show(); 
       mUseFrontFacingCamera = false; 
      } 
     } 

     final SurfaceHolder holder = mVideoView.getHolder(); 
     holder.addCallback(this); 
     holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public boolean onTouchEvent(MotionEvent event) { 
     // can use the xy of the touch to start and stop recording 
     float positionX = event.getX(); 
     float positionY = event.getY(); 

     switch (event.getAction()) { 
     case MotionEvent.ACTION_DOWN: 
      // Screen is pressed for the first time 
      break; 
     case MotionEvent.ACTION_MOVE: 
      // Screen is still pressed, float have been updated 
      break; 
     case MotionEvent.ACTION_UP: 
      // Screen is not touched anymore 
      if (mRecording) { 
       // To stop recording attach this try block to another event listener, 
       // button etc 
       try { 
        stopRecording(); 
       } catch (Exception e) { 
        Log.e(TAG, e.toString()); 
        e.printStackTrace(); 
       } 
      } else { 
       // To begin recording attach this try block to another event listener, 
       // button etc 
       try { 
        beginRecording(mVideoView.getHolder()); 
       } catch (Exception e) { 
        Log.e(TAG, e.toString()); 
        e.printStackTrace(); 
       } 
      } 
      break; 
     } 
     return super.onTouchEvent(event); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     try { 
      beginRecording(holder); 
     } catch (Exception e) { 
      Log.e(TAG, e.toString()); 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
     Log.v(TAG, "Width x Height = " + width + "x" + height); 
    } 

    private void stopRecording() throws Exception { 
     mRecording = false; 
     if (mVideoRecorder != null) { 
      mVideoRecorder.stop(); 
      mVideoRecorder.release(); 
      mVideoRecorder = null; 
     } 
     if (mCamera != null) { 
      mCamera.reconnect(); 
      mCamera.stopPreview(); 
      mCamera.release(); 
      mCamera = null; 
     } 
    } 

    @Override 
    protected void onDestroy() { 
     try { 
      stopRecording(); 
     } catch (Exception e) { 
      Log.e(TAG, e.toString()); 
      e.printStackTrace(); 
     } 
     super.onDestroy(); 

    } 

    /** 
    * Uses the surface defined in video_recorder.xml 
    * Tested using 
    * 2.2 (HTC Desire/Hero phone) -> Use all defaults works, records back facing camera with AMR_NB audio 
    * 3.0 (Motorola Xoom tablet) -> Use all defaults doesn't work, works with these specs, might work with others 
    * 
    * @param holder The surfaceholder from the videoview of the layout 
    * @throws Exception 
    */ 
    private void beginRecording(SurfaceHolder holder) throws Exception { 
     if (mVideoRecorder != null) { 
      mVideoRecorder.stop(); 
      mVideoRecorder.release(); 
      mVideoRecorder = null; 
     } 
     if (mCamera != null) { 
      mCamera.reconnect(); 
      mCamera.stopPreview(); 
      mCamera.release(); 
      mCamera = null; 
     } 

     String uniqueOutFile = OUTPUT_FILE + System.currentTimeMillis() + ".3gp"; 
     File outFile = new File(uniqueOutFile); 
     if (outFile.exists()) { 
      outFile.delete(); 
     } 

     try { 
      if (mUseFrontFacingCamera) { 
       //hard coded assuming 1 is the front facing camera 
       mCamera = Camera.open(1); 
      } else { 
       mCamera = Camera.open(); 
      } 

      // Camera setup is based on the API Camera Preview demo 
      mCamera.setPreviewDisplay(holder); 
      Camera.Parameters parameters = mCamera.getParameters(); 
      parameters.setPreviewSize(640, 480); 
      mCamera.setParameters(parameters); 
      mCamera.startPreview(); 
      mCamera.unlock(); 

      mVideoRecorder = new MediaRecorder(); 
      mVideoRecorder.setCamera(mCamera); 

      // Media recorder setup is based on Listing 9-6, Hashimi et all 2010 
      // values based on best practices and good quality, 
      // tested via upload to YouTube and played in QuickTime on Mac Snow Leopard 
      mVideoRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
      mVideoRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
      mVideoRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);// THREE_GPP 
                                      // is big-endian, 
                                      // storing and 
                                      // transferring 
                                      // the most 
                                      // significant 
                                      // bytes first. 
                                      // MPEG_4 as another option 
      mVideoRecorder.setVideoSize(640, 480);// YouTube recommended size: 320x240, 
                      // OpenGazer eye tracker: 640x480 
                      // YouTube HD: 1280x720 
      mVideoRecorder.setVideoFrameRate(20); //might be auto-determined due to lighting 
      mVideoRecorder.setVideoEncodingBitRate(3000000);// 3 megapixel, or the max of 
                           // the camera 
      mVideoRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// MPEG_4_SP 
                                   // Simple Profile is 
                                   // for low bit 
                                   // rate and low 
                                   // resolution 
                                   // H264 is MPEG-4 Part 10 
                                   //is commonly referred to 
                                   // as H.264 or AVC 
      int sdk = android.os.Build.VERSION.SDK_INT; 
      // Gingerbread and up can have wide band ie 16,000 hz recordings 
      // (Okay quality for human voice) 
      if (sdk >= 10) { 
       mVideoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB); 
       mVideoRecorder.setAudioSamplingRate(16000); 
      } else { 
       // Other devices only have narrow band, ie 8,000 hz 
       // (Same quality as a phone call, not really good quality for any purpose. 
       // For human voice 8,000 hz means /f/ and /th/ are indistinguishable) 
       mVideoRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
      } 
      mVideoRecorder.setMaxDuration(30000); // limit to 30 seconds 
      mVideoRecorder.setPreviewDisplay(holder.getSurface()); 
      mVideoRecorder.setOutputFile(uniqueOutFile); 
      mVideoRecorder.prepare(); 
      mVideoRecorder.start(); 
      mRecording = true; 
     } catch (Exception e) { 
      Log.e(TAG, e.toString()); 
      e.printStackTrace(); 
     } 
    } 
} 
+0

el código que has publicado trabajos, que acababa de crear un comentario en 'mUseFrontFacingCamera = getIntent() getExtras() getBoolean ( EXTRA_USE_FRONT_FACING_CAMERA, true).; 'para que funcione. Probado en SGS2 ICS 4.0.3 y Samsung Tablet GTP1000 en 2.3.6. Tks para compartir, 1up. –

+0

hecho. gracias @Tuga! – cesine

+0

Este es el mejor código que he encontrado hasta ahora. Excepto un problema. Cuando lo llamo con resolución codificada, funciona perfecto. Pero tengo que llamarlo como un método y pasar una resolución diferente cada vez que se toma del usuario. Cuando lo llamo con diferentes resoluciones, me da error: 'start failed: -19' -' 06-28 19: 41: 07.338: E/MediaRecorder (25092): intente eliminar el archivo roto:/storage/sdcard0/Chimp_0160/recording.3gp' –

Cuestiones relacionadas