解决Android录制视频时异常断电或apk闪退导致视频播放不了问题

问题点描述

Android录制mp4(h264+acc)视频,当设备异常断电时,导致apk没法正常关闭录制;

问题点分析

经度娘分析,没能正常关闭录制的视频文件缺少少moov box,导致视频没法正常播放;

解决方案

在这里插入图片描述经验证度娘给出的方案,发现都不满足需求或者不太好操作。最后跟同事讨论了一下决定更换录制的视频格式,直接换成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;
        }
    });
}

注意一:要有摄像头、音频、读写文件权限(读文件可以不要)

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

注意二:这里不能直接使用setMaxDuration进行视频分段录制,具体原因看官方介绍,可以按我上面贴的代码来实现,不过这个方案不太完美,有丢帧。针对这个问题问了以下度娘,有解决方案,具体可以参见:大佬的博客

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
摄像头重启,javacv 录制视频分段失效的问题可能是由于摄像头重启导致的连接中断或状态丢失引起的。 在录制视频过程中,如果摄像头突然断电或者重启,就会导致正在进行的录制操作被中断。这候,javacv 可能无法正确处理这种中断,导致无法实现视频分段的功能。 另外,摄像头重启,会导致摄像头的状态发生变化,可能会丢失某些参数设置或连接信息。如果 javacv 没有正确处理状态变化,就会导致无法继续录制视频或者无法保存录制视频。这也会影响视频分段的功能。 要解决这个问题,可以尝试以下方法: 1. 检测摄像头的连接状态,如果连接断开,可以尝试重新建立连接。可以在摄像头重启后自动重连,避免录制中断。 2. 在摄像头重启后,重新配置摄像头的参数和状态,确保与 javacv 的录制参数一致。确保配置的参数正确,包括帧率、分辨率等设置。 3. 在进行视频分段,需要检测录制视频文件是否已经达到预设的大小或间长度,如果达到了,则进行分段并创建新的视频文件。 4. 如果出现错误或者中断,需要做好异常处理,确保错误能够及捕获并处理,避免影响录制过程。 总之,要解决摄像头重启 javacv 录制视频分段失效的问题,需要注意处理连接中断、状态丢失以及合理的异常处理,以确保录制过程能够稳定进行并实现视频分段的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玉念聿辉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值