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();
 }
}
}


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

38 comments:

  1. Nice example.

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

    ReplyDelete
  2. hello Blastdemo,

    I THINK it can run on 2.3.3. with preview.

    But need to run on true device, not emulator.

    ReplyDelete
  3. 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

    ReplyDelete
  4. 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

    ReplyDelete
  5. 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.

    ReplyDelete
  6. @Raj, sometimes you need to add

    mediarecorder.reset();

    at the beginning in your initRecorder();

    For some reason that worked, lemme know

    ReplyDelete
  7. 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.

    ReplyDelete
  8. 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.

    ReplyDelete
  9. Thanks Chilltime, it worked fine

    ReplyDelete
  10. 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.

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

    ReplyDelete
  12. 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();

    }

    ReplyDelete
  13. 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

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

    ReplyDelete
  15. hello bhavna,

    pls. try Chilltime suggestion.

    ReplyDelete
  16. 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

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

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

    ReplyDelete
  19. 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,,,,,

    ReplyDelete
  20. hello Chilltime,

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

    ReplyDelete
  21. hello bhavna,

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

    ReplyDelete
  22. 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.

    ReplyDelete
  23. 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.

    ReplyDelete
  24. 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...??

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

    ReplyDelete
  26. 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?

    ReplyDelete
  27. 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 ?

    ReplyDelete
  28. 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...

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

    ReplyDelete
  30. @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

    ReplyDelete
  31. The "download file" link doesn't work.

    Please upload the source again.

    Thanks

    ReplyDelete
  32. hello sir i am trying to built an app to streaming live video from my laptop camera and send the video to mobile or desktop ...... can you help me plz :)

    ReplyDelete
  33. hello mostafa Hussien,

    sorry, I also lost the files.

    ReplyDelete
  34. How to compress video size without ffmpeg.

    ReplyDelete
  35. Hello I doing my apps which is CCTV application.
    i need to insert live streaming cctv (nvr, ahd)
    then it can be record the video, capture, playback. I hope you can help me.
    Thank you

    ReplyDelete
  36. Hello,
    I want to use video recorder without clicking on Button means I want start video recording when we call activity. Please tell me how can we do that?

    ReplyDelete