Using android MediaRecorder

jacobianism picture jacobianism · Jul 23, 2013 · Viewed 19k times · Source

Below is the structure of my working code to record video and audio:

Questions: 1) Why is the CamcorderProfile needed? setProfile(...) appears to set the dimensions to whatever QUALITY_HIGH gives, but later I set the dimensions I want with setVideoSize(...), which overrides this. However, when I remove the two CamcorderProfile lines, the app crashes at setVideoSize(...) with LogCat E/MediaRecorder(19526): setVideoSize called in an invalid state: 2.

2) How do I not record audio? The documentation states that if setAudioSource(...) is not called, there will be no audio track. However, when I remove that line the app crashes at setProfile(...) with LogCat E/MediaRecorder(19946): try to set the audio encoder without setting the audio source first.

3) If I remove both CamcorderProfile lines and the setAudioSource(...) line, it crashes as in 1).

4) I have also tried adding the line

recorder.setOutputFormat(OutputFormat.DEFAULT);

instead of the CamcorderProfile lines. But now it crashes at perpare(). If setAudioSource(...) is called the LogCat is: E/MediaRecorder(20737): audio source is set, but audio encoder is not set if it isn't called the LogCat is: E/MediaRecorder(20544): video source is set, but video encoder is not set

I have looked allover the internet and I can't find a good example of the correct way to setup the MediaRecorder. Here it implies after API 8 you should use the CamcorderProfile class, but it seems to me that it is causing problems.

Any help would be great! Thanks!

Code (which works when run as it is below):

recorder = new MediaRecorder();
recorder.setCamera(<<camera>>);
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);

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

recorder.setOutputFile(<<Path String>>);
recorder.setVideoSize(<<Width>>, <<Height>>);

recorder.setPreviewDisplay(<<Surface>>);

recorder.setOrientationHint(0); 
recorder.setMaxDuration(10000);
recorder.setOnInfoListener(this);

try
{
    recorder.prepare();
    recorder.start();
} catch ...

Answer

Thomas H. picture Thomas H. · Jul 23, 2013

I don't have a lot of experience with MediaRecorder but I was reading some related topics and I will try to answer your questions:

1, 3 and 4) CamcorderProfile sets more than just the resolution, it also sets things as output format and encoders (for both audio and video). You are getting the error because you probably need to use setOutputFormat before calling setVideoSize and you have to call setVideoEncoder and setAudioEncoder after it, if you do not want to use CamcorderProfile. [According to this answer]

2) Again, CamcorderProfile also sets audio properties (such as Codec, BitRate, SampleRate,...) so you need to set an Audio Source before calling it, that's why the app crashed. If you don't want to record audio try the next code: (I didn't test it so I don't actually know if it works, but I am pretty sure it does)

recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
recorder.setVideoSize(WIDTH, HEIGHT);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
recorder.setOutputFile(PATH);
recorder.setPreviewDisplay(SURFACE);

recorder.prepare();
recorder.start();

Also be aware that if you do not want to use CamcorderProfile (meaning that you want to record audio or video only) you may have to set additional parameters to assure you have the quality you want. Take a look at the following example code:

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

// Following code does the same as getting a CamcorderProfile (but customizable)
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// Video Settings 
recorder.setVideoSize(WIDTH, HEIGHT);
recorder.setVideoFrameRate(FRAME_RATE);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
recorder.setVideoEncodingBitRate(VIDEO_BITRATE);
// Audio Settings
recorder.setAudioChannels(AUDIO_CHANNELS);
recorder.setAudioSamplingRate(SAMPLE_RATE);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); 
recorder.setAudioEncodingBitRate(AUDIO_BITRATE);

// Customizable Settings such as:
//   recorder.setOutputFile(PATH);
//   recorder.setPreviewDisplay(SURFACE);
//   etc...

// Prepare and use the MediaRecorder
recorder.prepare();
recorder.start();
...
recorder.stop();
recorder.reset();
recorder.release();

I hope this helps you.