7. Use MediaRecorder to record video files

Use MediaRecorder to record video files

Android emulator cannot record audio.

Life cycle

First, you need to grant two permissions through ActivityCompat.requestPermissions():

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

The steps to record audio using MediaRecorder are usually as follows:

 MediaRecorder recorder = new MediaRecorder();
 recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
 recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
 recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
 recorder.setOutputFile(PATH_NAME);
 recorder.prepare();
 recorder.start(); // Recording is now started
 ...
 recorder.stop();
 recorder.reset(); // You can reuse the object by going back to setAudioSource() step
 recorder.release(); // Now the object cannot be reused
// Remember to release camera resources

Code

Detailed steps for recording videos with Android MediaRecorder_APDL_10’s Blog-CSDN Blog

GitHub – android/media-samples at master

There are many demo examples in this

The way these codes are written is really interesting, gives people a good feeling, and is worth learning.

After clicking the record button, determine whether to enter the recording state or end the recording based on the current status.

Because recording needs to be prepared first and then started, go to the prepare sub-method first to enter the relevant initialization configuration, and then decide whether to start based on the return value of prepare (these two steps are executed through async)

If the end is entered, the resources are released.

When setting a series of parameters such as audio and video encoder, output format, bit rate, etc., you can actually use the setProfile method to set them, instead of setting them one by one.

public class MediaRecorderActivity extends AppCompatActivity {
    private static final String TAG = "MediaRecorderActivity";

    private Camera mCamera;
    private SurfaceView mPreview;
    private MediaRecorder mMediaRecorder;
    private File mOutputFile;

    private boolean isRecording = false;
    private Button captureButton;

    public static Intent newIntent(Context packageContext) {
        Intent intent = new Intent(packageContext, MediaRecorderActivity.class);
        return intent;
}

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_media_recorder);

        mPreview = findViewById(R.id.afv_media_recorder);
        captureButton = findViewById(R.id.btn_media_recorder_capture);
    }

    /**
     * The capture button controls all user interaction. When recording, the button click
     * stops recording, releases {@link android.media.MediaRecorder} and
     * {@link android.hardware.Camera}. When not recording, it prepares the
     * {@link android.media.MediaRecorder} and starts recording.
     *
     * @param view the view generating the event.
     */
    public void onCaptureClick(View view) {
        if (isRecording) {
            // BEGIN_INCLUDE(stop_release_media_recorder)

            // stop recording and release camera
            try {
                mMediaRecorder.stop(); // stop the recording
            } catch (RuntimeException e) {
                // RuntimeException is thrown when stop() is called immediately after start().
                // In this case the output file is not properly constructed ans should be deleted.
            Log.d(TAG, "RuntimeException: stop() is called immediately after start()");
            //noinspection ResultOfMethodCallIgnored
            mOutputFile.delete();
            }
            releaseMediaRecorder(); // release the MediaRecorder object
            mCamera.lock(); // take camera access back from MediaRecorder

            // inform the user that recording has stopped
            setCaptureButtonText("Capture");
            isRecording = false;
            releaseCamera();
            // END_INCLUDE(stop_release_media_recorder)

        } else {

            // BEGIN_INCLUDE(prepare_start_media_recorder)

            new MediaPrepareTask().execute(null, null, null);

            // END_INCLUDE(prepare_start_media_recorder)

        }
    }

    private void setCaptureButtonText(String title) {
        captureButton.setText(title);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // if we are using MediaRecorder, release it first
        releaseMediaRecorder();
        // release the camera immediately on pause event
        releaseCamera();
    }

    private void releaseMediaRecorder() {
        if (mMediaRecorder != null) {
            // clear recorder configuration
            mMediaRecorder.reset();
            // release the recorder object
            mMediaRecorder.release();
            mMediaRecorder = null;
            // Lock camera for later use i.e taking it back from MediaRecorder.
            // MediaRecorder doesn't need it anymore and we will release it if the activity pauses.
            mCamera.lock();
        }
    }

    private void releaseCamera() {
        if (mCamera != null) {
            // release the camera for other applications
            mCamera.release();
            mCamera = null;
        }
    }

    private boolean prepareVideoRecorder() {

        //1.Create recorder object
        mMediaRecorder = new MediaRecorder();
        //2.Set the direction of recording video
        mCamera = Camera.open();//Camera object
        mCamera.setDisplayOrientation(90);//Adjust the angle of the camera preview
        mCamera.unlock();
        mMediaRecorder.setCamera(mCamera);
        //3.Set the audio source (MIC: microphone collects audio)
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        //4. Set the video source (CAMERA: camera captures video)
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        //5.Set video output format (MP4)
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        //6.Set audio encoding format
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        //7.Set video encoding format
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        //8.Set the direction of video playback
        mMediaRecorder.setOrientationHint(90);
        //9.Set the location of the output file

        // Step 4: Set output file
        mOutputFile = CameraHelper.getOutputMediaFile(CameraHelper.MEDIA_TYPE_VIDEO);
        if (mOutputFile == null) {
            return false;
        }
        mMediaRecorder.setOutputFile(mOutputFile.getPath());
        // END_INCLUDE (configure_media_recorder)

        //10.Set the size of the output video
        mMediaRecorder.setVideoSize(640,480);
        //11.Set the frame rate of the video
        mMediaRecorder.setVideoFrameRate(30);
        //12. Set the preview interface (set a Surface, which is the preview page, and then hand it over)
        mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

        // Step 5: Prepare configured MediaRecorder
        try {
            mMediaRecorder.prepare();
        } catch (IllegalStateException e) {
            Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
            return false;
        } catch (IOException e) {
            Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
            return false;
        }
        return true;
    }

    /**
     * Asynchronous task for preparing the {@link android.media.MediaRecorder} since it's a long blocking
     * operation.
     */
    class MediaPrepareTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... voids) {
            // initialize video camera
            if (prepareVideoRecorder()) {
                // Camera is available and unlocked, MediaRecorder is prepared,
                // now you can start recording
                mMediaRecorder.start();

                isRecording = true;
            } else {
                // prepare didn't work, release the camera
                releaseMediaRecorder();
                return false;
            }
            return true;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            if (!result) {
                MediaRecorderActivity.this.finish();
            }
            // inform the user that recording has started
            setCaptureButtonText("Stop");
        }
    }
}