Thursday, April 7, 2011

A simple exercise of Video Capture using MediaRecorder

This exercise cannot run on Android 2.3 and higher, please refer A simple exercise of Video Capture using MediaRecorder, for Android 2.3 or higher for updated version.

------------------------------------------------------

It's a A simple exercise of Video Capture. Please note that it only show the simple steps to achieve video capture, without handle the various exception case. The app start with a video preview in a SurfaceView, and some initialization of MediaRecorder. When user click on the REC button, the video capture will be started, once user click on the STOP button, recording will be stopped, and the video will be save in "/sdcard/myvideo.mp4".

A simple exercise of Video Capture using MediaRecorder

First of all, modify AndroidManifest.xml to set screen orientation of landscape, and theme of fullscreen, such that we have more space for our preview. And also grant permission of "android.permission.RECORD_AUDIO", "android.permission.CAMERA" and "android.permission.WRITE_EXTERNAL_STORAGE".
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidVideoCapture"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />

<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidVideoCapture"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
</manifest>


main.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"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<SurfaceView
android:id="@+id/videoview"
android:layout_width="720px"
android:layout_height="480px"/>
<Button
android:id="@+id/mybutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="REC"
android:textSize="12dp"/>
</LinearLayout>
</LinearLayout>


package com.exercise.AndroidVideoCapture;

import java.io.IOException;

import android.app.Activity;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

public class AndroidVideoCapture extends Activity implements SurfaceHolder.Callback{

Button myButton;
MediaRecorder mediaRecorder;
SurfaceHolder surfaceHolder;
boolean recording;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

recording = false;

mediaRecorder = new MediaRecorder();
initMediaRecorder();

setContentView(R.layout.main);

SurfaceView myVideoView = (SurfaceView)findViewById(R.id.videoview);
surfaceHolder = myVideoView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

myButton = (Button)findViewById(R.id.mybutton);
myButton.setOnClickListener(myButtonOnClickListener);
}

private Button.OnClickListener myButtonOnClickListener
= new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(recording){
mediaRecorder.stop();
mediaRecorder.release();
finish();
}else{
mediaRecorder.start();
recording = true;
myButton.setText("STOP");
}
}};

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub

}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
prepareMediaRecorder();
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub

}

private void initMediaRecorder(){
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT);
CamcorderProfile camcorderProfile_HQ = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
mediaRecorder.setProfile(camcorderProfile_HQ);
mediaRecorder.setOutputFile("/sdcard/myvideo.mp4");
mediaRecorder.setMaxDuration(60000); // Set max duration 60 sec.
mediaRecorder.setMaxFileSize(5000000); // Set max file size 5M
}

private void prepareMediaRecorder(){
mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface());
try {
mediaRecorder.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


Download the files.


Related Articles:
- Start Video Recording using android.provider.MediaStore.ACTION_VIDEO_CAPTURE
- CamcorderProfile: predefined camcorder profile settings for camcorder applications

32 comments:

Blastdemo said...

Nice example.

Does it work in Android 2.3.3? I mean, you see anything in your video preview screen?

Android Er said...

hello Blastdemo,

I THINK it can run on 2.3.3. with preview.

But need to run on true device, not emulator.

Raj said...

Great example, I tried in Motorola Atrix & this code works great in "Debug" mode, but when using the "Run" mode[i'm using Eclipse], screen is blank, could you pls help me out on this

Raj said...

Great example, I tried in Motorola Atrix & this code works great in "Debug" mode, but when using the "Run" mode[i'm using Eclipse], screen is blank, could you pls help me out on this

chilltime said...

hey great example especially with the button. however I want my button to streach throught the whole parent but it doesnt, im not liking the little button on the side, would rather have it longer atleast. Also when I have an error when I run it because of the mybutton.setText "STOP". Can you tell me a way to fix this please. Also I would like to make a dialogue and a count down when it is recording the video to know how much time the user has left to record. Much appreciated in advance. Love the blog by the way, just became a member today.

chilltime said...

@Raj, sometimes you need to add

mediarecorder.reset();

at the beginning in your initRecorder();

For some reason that worked, lemme know

Android Er said...

Hello Raj,

I haven't Motorola Atrix, so I don't know the case. chilltime advise add mediarecorder.reset() at the beginning in your initRecorder(); You can try.

Android Er said...

hello chilltime,

If you want a bigger button, simple change android:layout_height="fill_parent" should be ok. I don't know if it's what you expect.

I haven't no error in mybutton.setText "STOP"! I don't know what happen.

I cannot find and method to read the recorded time during recording. I think the simplest way is to implement a Chronometer separately.

Raj said...

Thanks Chilltime, it worked fine

chilltime said...

Cant believe I just saw all the replies now. Thanks for replying androider. I still cant fix my stop button error, this is what it says when i press the record button.


06-20 15:47:40.602: ERROR/StagefrightRecorder(70): Failed to set frame rate to 24 fps. The actual frame rate is 15
06-20 15:47:40.612: ERROR/VENC_ENC(70): VENC_ERROR update_param_port_def::1647 Frame rate is for input port (refer to OMX IL spec)
06-20 15:47:40.612: ERROR/VENC_ENC(70): Bitrate 3000000
06-20 15:47:40.752: ERROR/QualcommCameraHardware(70): num_buffers = 4
06-20 15:47:40.752: ERROR/QualcommCameraHardware(70): num_buffers = 8
06-20 15:47:40.882: ERROR/mm-camera 8x vfe(70): vfe_util_updaterollofftbl: sensor doesn't support rolloff correction by VFE
06-20 15:47:40.942: ERROR/QualcommCameraHardware(70): frames in busy Q = 0
06-20 15:47:40.942: ERROR/QualcommCameraHardware(70): frames in busy Q = 0 after deq and add to freeQ
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): FATAL EXCEPTION: main
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): java.lang.NullPointerException
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at com.apapa.vrsixty.record$1.onClick(record.java:176)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at android.view.View.performClick(View.java:2532)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at android.view.View$PerformClick.run(View.java:9293)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at android.os.Handler.handleCallback(Handler.java:587)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at android.os.Handler.dispatchMessage(Handler.java:92)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at android.os.Looper.loop(Looper.java:143)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at android.app.ActivityThread.main(ActivityThread.java:4263)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at java.lang.reflect.Method.invokeNative(Native Method)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at java.lang.reflect.Method.invoke(Method.java:507)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
06-20 15:47:40.992: ERROR/AndroidRuntime(5745): at dalvik.system.NativeStart.main(Native Method)

It seems like cos of the STOP its changing my framerate or something.

Also I will try implementing your chronometer on this. I will let you know how it goes. No, seriously i love your blog.

Bob Nudd said...

I worked in 2.2 I updated to 2.3.3 the video preview screen is now blank

chilltime said...

Chilltime here...again. I forgot to ask how to get a preview before you start recording? I heard this process occurs in the surface changed area but mine always fails. This is what i have so far


public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {


Camera.Parameters parameters = camera.getParameters();
List previewSizes = parameters.getSupportedPreviewSizes();
Size bestSize = null;
int bestDiff = 0;
int diff = 0;
for (Size size : previewSizes) {
diff = Math.abs(height - size.height) + Math.abs(width - size.width);
if (bestSize == null || diff < bestDiff) {
bestSize = size;
bestDiff = diff;
}
parameters.setPreviewSize(bestSize.width, bestSize.height);
camera.setParameters(parameters);
}


camera.startPreview();

}

Android Er said...

hello chilltime,

pls check Camera Preview on SurfaceView

bhavna said...

Sir ,
this code is not working on real device.
plzz suggest me if u have my answer?
/******its gives force close on android 2.2 device

bhavna said...

hi,,
ts code is not working on android 2.2.
I donn't knw whr i had done a mistake plz suggest me :-(

Android Er said...

hello bhavna,

pls. try Chilltime suggestion.

bhavna said...

hello Mr.Android Er,
thanks for the reply, actually sir my application is not working on real device i.e samsung Galaxy.
I know that we have to check this application on real device it can't run on emulator.
well sir its my request to u if u have its original source code which is working truly than send to my mail id i.e bhavnavrma@gmail.com.
I have an Programming Android book of O'REILLY.
its code also not working,, feeling like looser now..

thanks ,
bhavna

bhavna said...

well at last,,, my target is completed.
it looks very easy now,,,,,,

chilltime said...

bhavana did you solve the problem of the black screen on preview?

bhavna said...

friends,,
I have a new topic to discuss hope u help me,,,
Well in my android application i opened a html page using WebView.
My html page containing Create video Button,,,
Now I want that when i click that button it takes the path of video file stored in sdk i.e in .mp4and uploads its,,,

Hope my problem is clear to u,,,,now suggest something,,,,

I think addJavaScriptInterface method is used here,,,,,

bhavna said...

hello Chilltime,

I didn't got blank screen in preview,,, my videoRecording application is working f9....

Android Er said...

hello bhavna,

do you want to start doing something using Android code, from webpage. Refer the article: Run Android Java code from Webpage.

chilltime said...

bhavna,

Mine was working fine until i tried it on 2.3, and on preview it shows a blank screen, its been pissing me off, I also try to implement a flash light while my video is recording but it crashes. when i start recording if the flash light is on, any help will suffice.

Here is my flash light code when I press the button.

Button flash = (Button) findViewById (R.id.flash);
flash.setOnClickListener(new Button.OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(camera == null){
camera = Camera.open();
parameters = camera.getParameters();
parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
camera.setParameters(parameters);

}else{
parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
camera.setParameters(parameters);
camera.release();
camera = null;
}

}});

I tried putting it in my on surface create method but that doesnt help.

Android Er said...

hello chilltime,

Thanks for your comment, I re-test it on Nexus One running 2.3.6, it cannot work as before!

Now the updated version is here: A simple exercise of Video Capture using MediaRecorder, for Android 2.3 or higher.

pratik said...

thanks for this example...!!
But can you help me in one problem..??
I want to store the captured video at different location rather at its default location..
But it is not working...

I have tried with..."setOutputFile()" method but not getting a result...
It stores the video at its default location only...
Pls Help me...??

pratik said...

hi i found a solution you have to use a surfaceview to capture the video and extends the surfaceholder.callback methos.....check it working....

ensi_nanou said...

Hello, Thank you for this code.
But i want to now if it's possible to use it for IP camera either then the intergreted camera?

FERNANDO Keep'Wisdom said...

hello sir,
i try to make this example, but ican run on my android phone(galaxy pocket)
it's said "the application cameraexam(proses com.camera.exam) has stopped unexpectedly.
please try again
FORCE CLOSED

n when i try in my eclipse it appear long cat many times

what should i do sir ?

Android Er said...

please note: This exercise cannot run on Android 2.3 and higher, refer A simple exercise of Video Capture using MediaRecorder, for Android 2.3 or higher for updated version.

Anonymous said...

Hello Android Er,

I am working on a project in which i am putting one android phone to my robot which will send all it have in its camera view to another mobile via bluetooth, so that it can control the robot, i m really confused from where to start with.. I have made an app to control robot via bluetooth, now i need help for live video streaming...could u help me pls...

Vinodkumar N.V said...

Hi..i used this code.....All videos is not storing properly...the new one is replacing the old video.....plz let me know..

Polo Zavala said...

@Vinodkumar N.V you need to give diferent names to your files, if you are only using setOutPutFile("/sdcard/myvideo.mp4")
all your videos will go to that direction, and will overwrite your already existing files, you need to give a diferent name every time, you can try with this:

private String file = Environment.getExternalStorageDirectory.getAbsolutePath()+ "/Video_" + System.currentTimeMillis() + ".3gp";

setOutputFile(file);

you give the current time in millis as name, and now you can storage many videos as you want, you can try to put custom names to your files too