Androidで動画録画時に異常停電やAPKクラッシュにより動画が再生できない問題を解決

問題の説明

Android は mp4 (h264+acc) ビデオを録画します。デバイスの電源が異常にオフになると、APK は録画を正常に閉じることができません。

問題分析

Longitude Niang は、録画されたビデオ ファイルを正常に閉じることができず、いくつかの moov ボックスが欠けていたため、ビデオが適切に再生されなかったと分析しました。

解決

ここに画像の説明を挿入しますDu Niang 氏が提示した計画を検証したところ、どれもニーズを満たしていないか、運用が容易ではないことが判明しました。最終的に、同僚と話し合って、録画したビデオの形式を直接 TS ファイルに変更することにしました。再度ロジックを確認して問題がなければコードをアップロードします。

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

注 1: カメラ、オーディオ、ファイルの読み取りおよび書き込み権限が必要です (ファイルの読み取りはオプションです)。

    <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" />

注 2: ここでは setMaxDuration を直接使用してビデオ セグメントを記録することはできません。特定の理由については、公式の紹介を参照してください。上で投稿したコードに従って実装できます。ただし、この解決策は完璧ではなく、フレーム損失が発生する可能性があります。この問題については以下のDu Niangさんに質問したところ解決策がありましたので詳しくはBig Brotherのブログを参照してください

おすすめ

転載: blog.csdn.net/qq_35350654/article/details/130382227