Solve the problem that the video cannot be played due to abnormal power outage or apk crash when recording video on Android

Problem description

Android records mp4 (h264+acc) video. When the device is powered off abnormally, the apk cannot close the recording normally;

Problem analysis

Longitude Niang analyzed that the recorded video file could not be closed normally and lacked a few moov boxes, resulting in the video not playing properly;

solution

Insert image description hereAfter verifying the plans given by Du Niang, it was found that none of them met the needs or were not easy to operate. Finally, I discussed with my colleagues and decided to change the recorded video format directly to TS files. After checking the logic again, there is no problem, and then upload the code.

package com.example.demo;

import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Surface;

import androidx.appcompat.app.AppCompatActivity;

import com.zlmediakit.jni.ZLMediaKit;

import java.io.File;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();
    private  MediaRecorder mediaRecorder;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initMediaRecorder();
    }
    
    private void initMediaRecorder() {
        //new SurfaceTexture
        Camera mCamera = Camera.open(0);
        Camera.Parameters params = mCamera.getParameters();
        params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        mCamera.setParameters(params);
        SurfaceTexture surfaceTexture = new SurfaceTexture(0);
        try {
            mCamera.setPreviewTexture(surfaceTexture);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        mCamera.startPreview();
        mCamera.unlock();


        mediaRecorder = new MediaRecorder();
        mediaRecorder.setCamera(mCamera);
        mediaRecorder.reset();
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);           // 设置麦克风获取声音
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);        // 设置摄像头获取图像
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);   // 设置 ts 格式
        mediaRecorder.setVideoSize(1920, 1080);
        mediaRecorder.setVideoEncodingBitRate(2*1024*1024);// 2M 码率
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);  

        File f = new File(MainActivity.this.getExternalFilesDir(null).getAbsolutePath() + "/video");
        if (!f.exists()) f.mkdirs();
        String p = f.getAbsolutePath() + "/" + System.currentTimeMillis() + ".ts";
        Log.e(TAG, "initMediaRecorder   录制路径: " + p);

        mediaRecorder.setOutputFile(p);                   // 设置视频输出路径
        mediaRecorder.setPreviewDisplay(new Surface(surfaceTexture)); // 设置使用SurfaceView预览视频
        mediaRecorder.setOrientationHint(90);                                  // 调整播放视频角度
        try {
            mediaRecorder.prepare();                                           // 准备录像
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("WillWolf", "mediaRecorder-->录制异常:" + e.toString());
        }
        mediaRecorder.start();
        handler.sendEmptyMessageDelayed(1, 10 * 1000);
    }

    private Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == 1) {
                mediaRecorder.stop();
                mediaRecorder.reset();
                mediaRecorder.release();
                mediaRecorder = null;
                initMediaRecorder();
            }
            return false;
        }
    });
}

Note 1: You must have camera, audio, and read and write file permissions (reading files is optional)

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

Note 2: You cannot directly use setMaxDuration to record video segments here. For specific reasons, see the official introduction. You can implement it according to the code I posted above. However, this solution is not perfect and may cause frame loss. Regarding this problem, I asked the following Du Niang. There is a solution. For details, please refer to: Big Brother’s Blog

Guess you like

Origin blog.csdn.net/qq_35350654/article/details/130382227