You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Android中MP4视频编码及SQLite视频存储与检索播放问题

Hey there! Let's break down your two Android questions clearly, step by step.

1. 如何在Android平台中对MP4格式视频进行编码?

在Android上编码MP4视频,常用的方案有三种,各有适用场景:

  • 原生MediaCodec API(高性能、系统级支持)
    这是Android官方推荐的底层编码方案,直接调用系统硬件编码器,性能最优。核心步骤如下:

    1. 配置MediaFormat,指定MP4常用的H.264编码(MIME类型为video/avc),并设置分辨率、比特率、帧率等参数:
      MediaFormat videoFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080);
      videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
      videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, 6000000); // 6Mbps比特率
      videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
      videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5); // 每5帧生成一个关键帧
      
    2. 创建MediaCodec实例并启动,循环处理输入的原始视频帧(比如从Camera预览的Surface获取数据),输出编码后的H.264流。
    3. 使用MediaMuxer将编码后的视频流(若需要音频则同步处理音频编码)封装为MP4文件。
      提示:需要注意缓冲区的操作逻辑,以及不同Android版本的兼容性差异,处理过程中要做好异常捕获。
  • FFmpeg库(高灵活性、跨平台)
    如果需要自定义编码逻辑或支持更多格式,可集成FFmpeg。步骤如下:

    1. 编译FFmpeg的Android适配版本,或者使用现成的预编译库(如mobile-ffmpeg)。
    2. 通过JNI调用FFmpeg API,配置编码参数(指定输出格式为MP4,编码器为libx264等)。
    3. 输入原始视频数据,编码后写入MP4文件。
      优点是功能强大,缺点是会增大APK包体积。
  • MediaRecorder(快速实现、低自定义)
    如果你只是需要录制Camera或屏幕内容生成MP4,MediaRecorder是最简便的选择——它封装了MediaCodec和MediaMuxer,无需处理底层细节:

    MediaRecorder recorder = new MediaRecorder();
    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    recorder.setOutputFile(getExternalFilesDir(null) + "/recorded_video.mp4");
    recorder.setPreviewDisplay(surfaceHolder.getSurface());
    recorder.prepare();
    recorder.start();
    
    // 录制结束后释放资源
    // recorder.stop();
    // recorder.release();
    
2. 从SQLite数据库中检索视频并播放

首先要说明:SQLite并不适合存储大体积视频(会导致数据库臃肿、读写性能下降),更推荐存储视频的文件路径到数据库而非直接存字节数组。不过针对你已实现的存储逻辑,以下是检索和播放的方案:

步骤1:从数据库读取视频字节数组

// 假设db是你的SQLiteDatabase实例
Cursor cursor = db.query("tb", new String[]{"a"}, null, null, null, null, null);
byte[] videoBytes = null;
if (cursor.moveToFirst()) {
    // 读取blob类型的字段
    videoBytes = cursor.getBlob(cursor.getColumnIndexOrThrow("a"));
}
cursor.close(); // 记得关闭Cursor释放资源

步骤2:将字节数组写入临时文件

MediaPlayer无法直接播放字节数组,所以需要先把字节数组写入一个临时文件:

File tempVideoFile = null;
if (videoBytes != null) {
    try {
        // 在应用缓存目录创建临时MP4文件
        tempVideoFile = File.createTempFile("temp_video", ".mp4", getCacheDir());
        FileOutputStream fos = new FileOutputStream(tempVideoFile);
        fos.write(videoBytes);
        fos.flush();
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

步骤3:使用MediaPlayer播放临时文件

MediaPlayer mediaPlayer = new MediaPlayer();
if (tempVideoFile != null && tempVideoFile.exists()) {
    try {
        mediaPlayer.setDataSource(tempVideoFile.getAbsolutePath());
        mediaPlayer.prepare();
        mediaPlayer.start();

        // 播放完成后释放资源并删除临时文件
        mediaPlayer.setOnCompletionListener(mp -> {
            mp.release();
            if (tempVideoFile.exists()) {
                tempVideoFile.delete();
            }
        });
    } catch (IOException e) {
        e.printStackTrace();
        mediaPlayer.release();
        // 异常时也要清理临时文件
        if (tempVideoFile.exists()) {
            tempVideoFile.delete();
        }
    }
}

额外提示:如果视频体积较大,一次性读取字节数组可能引发OOM(内存溢出),这种情况下更不建议用SQLite存储视频,转而存储文件路径会更稳妥。

内容的提问来源于stack exchange,提问作者Amir

火山引擎 最新活动