I am working on a application where I need to record video on a button click of predefined lenth say 15 sec. After 15 sec I want to reset the MediaRecorder automatically without manual intervation My code is here.
public void initMediaRecorder(){
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
mRecorder.setPreviewDisplay(mHolder.getSurface());
mRecorder.setMaxDuration(15000);
mRecorder.setOutputfile("blahblah On SD card")
mRecorder.setOutputFile(mOutputFile);
}
Now the recording is getting done but after 15sec my UI is getting freeze and I need to reset manually the recorder. I need to know the event on which I should reset the recorder after 15sec time is done.
I found out the solution.
Maybe this answer will help some one.
Use the following listener
recorder.setOnInfoListener(new medialistener());
class medialistener implements MediaRecorder.OnInfoListener {
public void onInfo(MediaRecorder recorder, int what, int extra)
{
if(what==MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED)
{
}
// Log.i("video test", "Video Info: "+what+", "+extra);
}
}
cheers.
Related
I want to see the video that I'm currently recording in a SurfaceView and if the recodring finished I wanto to replay the video in the same SurfaceView.
Even though I thought it would be a common feature in Apps, I couldn't find any example and couldn't make my code work.
private void prepareRecorder() {
try {
recorder = new MediaRecorder();
recorder.setPreviewDisplay(holder.getSurface());
camera.unlock();
recorder.setCamera(camera);
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW);
recorder.setProfile(camcorderProfile);
File newFile = new File(videoFilePath);
recorder.setOutputFile(newFile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}catch(Exception e){
releaseCamera();
}
}
//
public void onClick(View v) {
if(mediaPlayer!=null) {
mediaPlayer.reset();
mediaPlayer.release();
}
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(videoFile.getAbsolutePath());
SurfaceView surfaceView = (SurfaceView) getView().findViewById(R.id.videoInvitationFragSurfaceView);
mediaPlayer.setSurface(surfaceView.getHolder().getSurface());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
If I just record the video my code works, if just play the video it works as well. Any ideas?
Thanks in advance
Edit: As a current workaround I use two SurfaceViews and "hide" them (set size to 0) if needed
If I just record the video my code works, if just play the video it works as well. Any ideas?
As much I understand, you can reuse same surface view only after it is destroyed and regenerated, i.e you can reuse same SurfaceView only after surfaceDestroyed() is called and then surfaceCreated() is called only after this destroy and create cycle you can reuse SurfaceView.
To achive this all you have to do is: after video recording is done set SurfaceView visibility to GONE which will ensure surfaceDestroyed() call back and again set SurfaceView visibility to VISIBLE which will call surfaceCreated() after that start video playback.
This is very cumbersome process so I used same SurfaceView for recording and playback in following way:
when Activity is created check if VideoFile is available in Intent
if yes use SurfaceView for playback
now if user deletes video restart activity
As VideoFile is not found in intent use SurfaceView for recording
Once recording is done and user want to playback video restart
Activity with VideoFile information attached in Intent
I am creating a MediaRecorder and using it to generate a video clip. It works perfectly the first time. I end the video shooting process by setting the maximum file size to 5MB, after which it enters the onInfo method and the completely that particular video snap.
Now I want to generate 5 such clips, one after the other. For which I add the following to the onInfo method:
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
// TODO Auto-generated method stub
//System.out.println("Reached onInfoListener");
if(what==android.media.MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED)
{
Toast.makeText(getApplicationContext(), "Video clip "+video_count+" recorded", Toast.LENGTH_SHORT).show();
recorder.stop(); //recorder is an object of type MediaRecorder
recorder.reset();
initRecorder(); //Reinitializing for subsequent video generation
prepareRecorder(); //Re preparing for subsequent video generation
}
}
private void initRecorder() {
recorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
recorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),"/FOLDERNAME");
if(!dir.exists())
{
dir.mkdir();
}
CamcorderProfile cpHigh = CamcorderProfile
.get(CamcorderProfile.QUALITY_HIGH);
recorder.setProfile(cpHigh);
recorder.setOutputFile("/sdcard/FOLDERNAME/video"+video_count+".mp4");
recorder.setMaxDuration(50000); // 50 seconds
recorder.setMaxFileSize(5*1048576); // Approximately 5 megabytes
}
private void prepareRecorder() {
recorder.setPreviewDisplay(cameraView.getHolder().getSurface());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
finish();
} catch (IOException e) {
e.printStackTrace();
finish();
}
}
NOTE: videocount is a variable used to give a distinct name to each generated video clip.
However after successfully capturing the first video clip, and just before the second clip an start recording, a IllegalStateException is encountered when I try to start the recorder object again. Since I am using recorder.reset() API, I thought that I would be able to reuse the recorder object for subsequent iterations. But it is giving this problem.
How to solve this issue? Is it neccessary to provide some delay after reinitializing the recorder object?
EDIT: If I keep the recorder.start() inside a button click, this works, that is, on every button click, a separate video is taken. But if I ask it to take say, 5 videos, on a single button click, the app crashes before it starts taking the second video, that is, it works only once. How to overcome this non-uniformity?
Going by the official documentation you need to call the setOutputFormat() method before you can call prepare(), like this:
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
I'm developing on a Nitro HD with Gingerbread. I want to record audio and I experience an infinite hang while calling MediaRecorder.stop().
I know that my phone can record sound because I have an application that does it exactly.
I read the book "Android for programmers" from Deitel et al. and there is the example VoiceRecorder in chapter 16. Everything seems fine but the app hangs forever when it calls MediaRecorder.stop(). Also, the resource is not released and I have to reboot the phone to release it.
Here is the part of the code where the calls are done (see Deitel et al., "Android for Programmers", Prentice Hall, 2012, chap 16):
// starts/stops a recording
OnCheckedChangeListener recordButtonListener =
new OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked)
{
if (isChecked)
{
visualizer.clear(); // clear visualizer for next recording
saveButton.setEnabled(false); // disable saveButton
deleteButton.setEnabled(false); // disable deleteButton
viewSavedRecordingsButton.setEnabled(false); // disable
// create MediaRecorder and configure recording options
if (recorder == null)
recorder = new MediaRecorder(); // create MediaRecorder
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(
MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
recorder.setAudioEncodingBitRate(16);
recorder.setAudioSamplingRate(44100);
try
{
// create temporary file to store recording
File tempFile = File.createTempFile(
"VoiceRecorder", ".3gp", getExternalFilesDir(null));
// store File as tag for saveButton and deleteButton
saveButton.setTag(tempFile);
deleteButton.setTag(tempFile);
// set the MediaRecorder's output file
recorder.setOutputFile(tempFile.getAbsolutePath());
recorder.prepare(); // prepare to record
recorder.start(); // start recording
recording = true; // we are currently recording
handler.post(updateVisualizer); // start updating view
} // end try
catch (IllegalStateException e)
{
Log.e(TAG, e.toString());
} // end catch
catch (IOException e)
{
Log.e(TAG, e.toString());
} // end catch
} // end if
else
{
recorder.stop(); // stop recording
recorder.reset(); // reset the MediaRecorder
recording = false; // we are no longer recording
saveButton.setEnabled(true); // enable saveButton
deleteButton.setEnabled(true); // enable deleteButton
recordButton.setEnabled(false); // disable recordButton
} // end else
} // end method onCheckedChanged
}; // end OnCheckedChangedListener
In a debug session, the "else" scope is entered but it hangs on its first (stop()) line.
I repeat, I know the phone and its OS are correct because another app works correctly. So, do you have any idea on how to solve this problem, a work around maybe?
Thanks!
EDIT When the recorder is started(), there is a handler that is executed at each 50ms to display a graph of the amplitude of the sound. The method recorder.getMaxAmplitude() always returns 0. Maybe this is the symptom of a badly initialized MediaRecorder?
The argument of setAudioEncodingBitRate() might be too low.
what is good setAudioEncodingBitRate on record voice
Hope that's help.
You could have a null recorder at that spot. You're not creating a new MediaRecorder() if you enter the else case of isChecked.
So, 2 things:
The API docs state that if you call stop() before start you'll throw a RuntimeException And if you fail to record anything you'll throw an IllegalStateException.
Check recorder before calling stop:
if (recorder != null) {
recorder.stop();
// some recorder stuff here
}
I have set mEdiaRecorder.setMaxDuration(60 * 1000); (60 seconds) in my video recording app and I want to trigger a method when the time is expired of recording. Help me finding a way to do this.
Thank you.
mMediaRecorder.setOnInfoListener(new medialistener());
class medialistener implements MediaRecorder.OnInfoListener {
public void onInfo(MediaRecorder recorder, int what, int extra)
{
if(what==MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED)
{
// Do what you want to do...
}
// Log.i("video test", "Video Info: "+what+", "+extra);
}
}
According to the documentation, http://developer.android.com/reference/android/media/MediaRecorder.html#setMaxDuration(int)
the recording stops when the timer expires.
By stop, do they mean it calls internally recorder.stop() and then restores the state the app was in before calling recorder.start()?
I have found that I have to implement MediaRecorder.OnInfoListener and manually stop the recording at that point. Once that is done, the MediaRecorder goes back to the initial state and all of the normal setup has to be done again in order to start recording again.
public class VideoCapture extends Activity implements MediaRecorder.OnInfoListener {
public void startVideoRecording() {
// Normal MediaRecorder Setup
recorder.setMaxDuration(10000); // 10 seconds
recorder.setOnInfoListener(this);
}
public void onInfo(MediaRecorder mr, int what, int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
Log.v("VIDEOCAPTURE","Maximum Duration Reached");
mr.stop();
}
}
}
This is handled by OpenCore internally, and the state of the recorder after reaching max duration is uninitialized, as it called stop(). You have setup the recorder again to use it further.