zl程序教程

您现在的位置是:首页 >  Java

当前栏目

MediaMuxer录制视频踩坑记录

2023-02-18 16:27:07 时间

基本知识

MediaCodec的相关数据时间单位为(纳秒/1000),类似610,729,613,772, 倒数第7位代表秒级

MediaMuxer.writeSampleData Failed

描述:写入数据失败

常见原因

这类错误基本和时间戳有关

时间戳倒退问题

现象

解决

吐出时间戳倒退

丢弃异常帧(经测试无影响,且量级不大)

吐出时间戳相等

丢弃异常帧(有些机器能接受相等的数据,为了通用性还是丢弃)

此类问题出现一般在异常后的一帧写入报错

分析问题需要区分音频视频各自的时间戳查看

示例

第二行ts小于第一行的ts,第三行正常

writeSampleData size = 186,  ts = 621441165854
writeSampleData size = 186,  ts = 621441065854
writeSampleData size = 185,  ts = 621441131957

这是错误的音频写入日志,writeSampleData Failed会在第三行写入时候才会爆出来。所以分析此类问题可能需要往前多找几帧,出现问题的帧数据不一定是当前的帧

音视频录制合成后音频速率加快

MediaCodec的工作原理

两个队列管理入队出队,原始数据给到input,通过output吐出来

问题原因

如果input和output在不同线程,因为两边处理速率不一致,会导致input数据来不及消费,导致部分原始数据被覆盖(丢弃),最终形成的现象就是音频会加快,鬼畜。视频丢弃就会卡顿。

解决方案

  1. 使用队列保存原始数据,一般使用HandlerThread的Looper机制保存消息
  2. 在同一个线程做input,output,每一次input等到output完成再进行下一次input,保证每一帧数据消费完

音视频录制后卡顿

这类问题一般两种情况,时间戳不对,部分数据帧被都丢弃

MediaMuxer.Start时机不对

解决方案

建议时机:dequeueOutputBuffer返回MediaCodec.INFO_OUTPUT_FORMAT_CHANGED更新MediaMuxer.addTrack, 所有的track完成之后再触发start。

音频:dequeueOutputBuffer返回MediaCodec.INFO_OUTPUT_FORMAT_CHANGED触发新MediaMuxer.addTrack 视频:dequeueOutputBuffer返回MediaCodec.INFO_OUTPUT_FORMAT_CHANGED触发新MediaMuxer.addTrack MediaMuxer:所有track add完成之后触发start

问题示例

  1. 如果提前start,在触发addTrack会爆addTrack ERROR
  2. 如果提前addTrack && start,录制视频会卡顿

兼容性问题导致数据被丢弃

问题现象

有些机型,音频 or 视频初始化很慢,时间错开,导致另一个通道数据到达之后,因为MediaMuxer没有start,所以这部分数据默认被丢弃了。

解决方案

  1. 添加队列保存提前到来的数据,当MediaMuxer.Start之后统一写进去
  2. 写入缓存时候需要加锁,防止新的数据进来导致时序不对,就会出现上面MediaMuxer.writeSampleData Failed

MediaMuxer.stop: Failed to stop the muxer

一般出现这类问题的场景如下,需要做逻辑保护

  1. 多track场景需要等多个MediaCodec都释放之后触发
  2. 多track场景某一个track一直不写数据
  3. 录制快速停止场景,某些track对应的MediaCodec还没初始化完成