Je voudrais créer un enregistreur vidéo et jusqu'à présent, je n'ai pas trouvé comment définir des paramètres afin de passer avec succès par la méthode MediaRecorder.prepare ().
Exécuter la méthode suivante
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;
}
il jette une exception sur la ligne recorder.prepare().
Comment définir les paramètres afin de pouvoir capturer une vidéo?
Voici un extrait qui fonctionne:
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();
La chose la plus importante est la surface. Vous ne l'avez pas, alors sans elle, cela échoue.
Cordialement
BeMeCollective
Je réponds exactement à cette question dans le tutoriel suivant: http://integratingstuff.wordpress.com/2010/10/18/writing-code-that-captures-videos-on-Android/
La raison pour laquelle votre code échoue sur prepare () est que vous n'avez pas défini toutes les propriétés nécessaires. Par exemple, vous devez également définir maxDuration.
J'ai eu la même question. Je passais d'un service d'enregistrement audio en arrière-plan dans l'espoir de créer un service d'enregistrement vidéo en arrière-plan. Vous ne pouvez pas vraiment enregistrer une vidéo d'arrière-plan, mais vous pouvez réduire la prévisualisation de la vidéo dans votre interface utilisateur existante. J'ai suivi le didacticiel: http://integratingstuff.wordpress.com/2010/10/18/writing-code-that-captures-videos-on-Android/ et l'exemple de démonstration de Camera Preview. Mais finalement, l'exemple de code dans http://www.apress.com/downloadable/download/sample/sample_id/39/ était assez simple pour être tweek, mais également suffisamment complet pour fonctionner avec setCamera. Je publierai ma solution ici pour faire gagner du temps aux autres dans leur progression d’exemples de jouets à un exemple complexe avec un enregistrement vidéo en arrière-plan de bonne qualité (avec caméra frontale si nécessaire).
C’est la source d’un enregistreur vidéo Android avec prévisualisation "non" (la prévisualisation est un pixel 1x1 simulant un enregistrement non intrusif), pour enregistrer de la vidéo sans distraire l’utilisateur. Pour utiliser votre propre interface utilisateur, modifiez simplement le fichier video_recorder.xml en fonction de votre présentation (veillez à conserver VideoView). Il a été testé sur les appareils Android 2.2 et 3.0.
Cas d'utilisation appropriés:
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>
Classe 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();
}
}
}
Avez-vous vérifié cela?
http://code.google.com/p/Android/issues/detail?id=5050
Ces personnes suggèrent qu'il s'agit d'un problème de synchronisation et que la machine à états de MediaRecorder peut nécessiter un délai (dépendant du matériel?) Entre les états.
Ce serait bien s'il y avait des rappels pour le moment où chaque État était pleinement réalisé - alors nous pourrions simplement nous préparer.
Peut-être que l'application source de l'application Camera vous aide à résoudre ce problème.
Cela pourrait être une erreur d'autorisations. Avez-vous l'autorisation Android.permission.CAMERA définie dans votre fichier AndroidManifest?
Dans mon cas, copier et coller les exemples ci-dessus ne fonctionnait pas. Puis, en visualisant les méthodes dans MediaRecorder, j'ai trouvé setPreviewDisplay. J'ai appelé cette méthode en passant la surface utilisée dans Camera.setPreviewDisplay, l'IOException dans .prepare est parti et j'ai pu enregistrer une vidéo. Essayez par vous-même et publiez vos résultats.