Implementation steps of Android video recording function
- 2021-12-12 09:34:36
- OfStack
Please see the Google Audio and Video Guide for the official user guide
Basic steps of video recording
1. Declare authority
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<-- If the recorded video is saved externally SD Card, you also need to add the following permissions ->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Note: RECORD_AUDIO is a dangerous permission, starting with Android 6.0 (API level 23), which needs to be obtained dynamically.
2. Configuration of video recording parameters
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.text.TextUtils;
/**
* @author Created by LRH
* @description Video recording parameters (parameters can be expanded by themselves)
* @date 2021/1/19 13:54
*/
public class VideoRecorderConfig {
//Camera
private Camera camera;
// Camera preview width
private int videoWidth;
// Camera preview height
private int videoHeight;
// Camera preview deflection angle
private int cameraRotation;
// Saved file path
private String path;
// Due to Camera Using the SurfaceTexture , so the SurfaceTexture
// You can also use the SurfaceHolder
private SurfaceTexture mSurfaceTexture;
private int cameraId = 0;
public SurfaceTexture getSurfaceTexture() {
return mSurfaceTexture;
}
public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
mSurfaceTexture = surfaceTexture;
}
public Camera getCamera() {
return camera;
}
public void setCamera(Camera camera) {
this.camera = camera;
}
public int getVideoWidth() {
return videoWidth;
}
public void setVideoWidth(int videoWidth) {
this.videoWidth = videoWidth;
}
public int getVideoHeight() {
return videoHeight;
}
public void setVideoHeight(int videoHeight) {
this.videoHeight = videoHeight;
}
public int getCameraRotation() {
return cameraRotation;
}
public void setCameraRotation(int cameraRotation) {
this.cameraRotation = cameraRotation;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getCameraId() {
return cameraId;
}
public void setCameraId(int cameraId) {
this.cameraId = cameraId;
}
public boolean checkParam() {
return mSurfaceTexture != null && camera != null && videoWidth > 0 && videoHeight > 0 && !TextUtils.isEmpty(path);
}
}
3. Video recording interface encapsulation (using MediaRecorder)
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.view.Surface;
import com.emp.yjy.baselib.utils.LogUtils;
import java.io.IOException;
/**
* @author Created by LRH
* @description
* @date 2021/1/19 13:53
*/
public class VideoRecorder {
private static final String TAG = "VideoRecord";
private MediaRecorder mRecorder;
public VideoRecorder() {
}
/**
* Start recording
*
* @param config
* @return
*/
public boolean startRecord(VideoRecorderConfig config, MediaRecorder.OnErrorListener listener) {
if (config == null || !config.checkParam()) {
LogUtils.e(TAG, " Parameter error ");
return false;
}
if (mRecorder == null) {
mRecorder = new MediaRecorder();
}
mRecorder.reset();
if (listener != null) {
mRecorder.setOnErrorListener(listener);
}
config.getCamera().unlock();
mRecorder.setCamera(config.getCamera());
// Set up the audio channel
// mRecorder.setAudioChannels(1);
// Sound source
// AudioSource.DEFAULT: Default audio source
// AudioSource.MIC: Microphone (commonly used)
// AudioSource.VOICE_UPLINK: Telephone uplink
// AudioSource.VOICE_DOWNLINK: Downlink telephone
// AudioSource.VOICE_CALL: Telephone, including uplink and downlink
// AudioSource.CAMCORDER: Microphone next to the camera
// AudioSource.VOICE_RECOGNITION: Speech recognition
// AudioSource.VOICE_COMMUNICATION: Voice communication
mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
// Video source
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
try {
// The following code is recommended for parameter configuration
CamcorderProfile bestCamcorderProfile = getBestCamcorderProfile(config.getCameraId());
mRecorder.setProfile(bestCamcorderProfile);
} catch (Exception e) {
// Format Output
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
// Voice coding format
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
// Video coding format
mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
}
// Set the length and width of the video
mRecorder.setVideoSize(config.getVideoWidth(), config.getVideoHeight());
// Set the sampling frame rate
mRecorder.setVideoFrameRate(30);
// mRecorder.setAudioEncodingBitRate(44100);
// Set the bit rate (the higher the bit rate, the higher the quality)
mRecorder.setVideoEncodingBitRate(800 * 1024);
// Here is to adjust the rotation angle (the front and rear angles are not 1 Sample)
mRecorder.setOrientationHint(config.getCameraRotation());
// Set the maximum duration of a recording session (in milliseconds)
mRecorder.setMaxDuration(15 * 1000);
// Set the output file path
mRecorder.setOutputFile(config.getPath());
// Set the preview object (you can use the SurfaceHoler Instead)
mRecorder.setPreviewDisplay(new Surface(config.getSurfaceTexture()));
// Pretreatment
try {
mRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
return false;
}
// Start recording
mRecorder.start();
return true;
}
/**
* Stop recording
*/
public void stopRecord() {
if (mRecorder != null) {
try {
mRecorder.stop();
mRecorder.reset();
mRecorder.release();
mRecorder = null;
} catch (Exception e) {
e.printStackTrace();
LogUtils.e(TAG, e.getMessage());
}
}
}
/**
* Pause recording
*
* @return
*/
public boolean pause() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && mRecorder != null) {
mRecorder.pause();
return true;
}
return false;
}
/**
* Continue recording
*
* @return
*/
public boolean resume() {
if (mRecorder != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mRecorder.resume();
return true;
}
return false;
}
}
public CamcorderProfile getBestCamcorderProfile(int cameraID){
CamcorderProfile profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_LOW);
if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_480P)){
// Compare the following 720 This choice Each frame is not very clear
profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_480P);
profile.videoBitRate = profile.videoBitRate/5;
return profile;
}
if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_720P)){
// Compare the above 480 This choice Mosaic when moving big !!
profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_720P);
profile.videoBitRate = profile.videoBitRate/35;
return profile;
}
if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_CIF)){
profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_CIF);
return profile;
}
if(CamcorderProfile.hasProfile(cameraID, CamcorderProfile.QUALITY_QVGA)){
profile = CamcorderProfile.get(cameraID, CamcorderProfile.QUALITY_QVGA);
return profile;
}
return profile;
}
3. Use examples
public void recordVideo(CustomCameraView CameraView) {
VideoRecorderConfig config = new VideoRecorderConfig();
String path = App.sGlobalContext.getExternalFilesDir("video").getAbsolutePath() + File.separator + "test1.mp4";
config.setCamera(CameraView.getCamera());
config.setCameraRotation(CameraView.getCameraRotation());
config.setVideoHeight(CameraView.getCameraSize().height);
config.setVideoWidth(CameraView.getCameraSize().width);
config.setPath(path);
config.setSurfaceTexture(CameraView.getSurfaceTexture());
config.setCameraId(0);
VideoRecorder record = new VideoRecorder();
boolean start = record.startRecord(config, null);
int duration = 15_000;
while (duration > 0) {
if (duration == 10_000) {
boolean pause = record.pause();
LogUtils.e(TAG, " Pause recording " + pause);
}
if (duration == 5_000) {
boolean resume = record.resume();
LogUtils.e(TAG, " Restart recording " + resume);
}
SystemClock.sleep(1_000);
duration -= 1_000;
}
record.stopRecord();
LogUtils.d(TAG, " Stop recording ");
}
Among them
CustomCameraView
Camera library packaged for yourself