视频源文件音频轨异常分析记录

背景

某回放视频在客户端播放或拖动进度后提示"加载失败"。客户端日志显示播放器进入错误状态,表现为 ExoPlayer 音频解码失败。

本文记录该类问题的分析过程、关键证据和可复用排查指令。

现象

客户端播放回放视频时,起播可以成功,拖动到后半段或某个固定时间点之后会快速失败。

典型日志特征如下:

text 复制代码
MediaCodecAudioRenderer error
format=audio/mp4a-latm, mp4a.40.2, 64000, [1, 44100]
format_supported=YES
Decoder failed: c2.android.aac.decoder
ERROR_CODE_DECODING_FAILED
MediaCodec$CodecException: Error 0xe

这类日志说明:

  • 音频格式为 AAC-LC,播放器和系统认为格式受支持。
  • 失败发生在解码阶段,不是普通网络加载失败。
  • 报错模块是音频渲染器 MediaCodecAudioRenderer,不是视频渲染器。

分析结论

源文件本身存在音轨/封装异常。

实际有效视频轨只有约 3377s,即约 56分17秒。但音频轨末尾存在异常 AAC packet,其 duration 被写成约 5011s,导致音频轨和容器总时长被错误拉长到约 8651s,即约 2小时24分

因此,当客户端播放或 seek 到 3377s 之后时:

  • 视频轨已经没有正常画面数据。
  • 音频轨进入异常拖尾区间。
  • 系统 AAC decoder 解码异常音频数据失败。
  • 播放器收到 ERROR_CODE_DECODING_FAILED,进入 error 状态。

准确描述是:3377 秒之后没有视频轨数据;音频轨还有异常拖尾,但不是正常可播放音频。

排查过程

1. 查看源文件基础信息

bash 复制代码
ffprobe -hide_banner -v error \
  -show_format \
  -show_streams \
  /path/to/input.mp4

重点关注:

  • format.duration
  • 视频流 duration
  • 音频流 duration
  • 音频编码、采样率、声道数

异常文件的典型表现:

text 复制代码
video duration ~= 3377s
audio duration ~= 8651s
format duration ~= 8651s
audio codec = aac
sample_rate = 44100
channels = 1

视频轨和音频轨时长严重不一致,是本问题的重要线索。

2. 检查异常时间点附近的音频 packet

bash 复制代码
ffprobe -hide_banner -v error \
  -select_streams a:0 \
  -show_packets \
  -read_intervals 3376%+5 \
  -show_entries packet=pts_time,dts_time,duration_time,size,flags,pos \
  /path/to/input.mp4

正常 AAC packet 的时长通常约为 0.023s。异常文件在末尾会出现类似:

text 复制代码
pts_time=3377.050000
duration_time=5011.263991
size=188

这说明音频轨最后出现了一个异常长 duration 的 packet,直接把音频轨和容器总时长拖长。

3. 单独验证音频解码

bash 复制代码
ffmpeg -hide_banner -v error \
  -ss 3376 \
  -t 10 \
  -i /path/to/input.mp4 \
  -map 0:a:0 \
  -f null -

异常文件会报类似错误:

text 复制代码
[aac] channel element 2.8 is not allocated
Error submitting packet to decoder: Invalid data found when processing input

这说明问题可以在本地通过 FFmpeg 解码复现,不依赖客户端环境。

4. 单独验证视频轨

bash 复制代码
ffmpeg -hide_banner -v error \
  -ss 3376 \
  -t 10 \
  -i /path/to/input.mp4 \
  -map 0:v:0 \
  -f null -

若视频轨无报错,同时音频轨报错,则可以进一步确认主问题在音频轨/封装。

5. 客户端现场日志验证

通过 ADB 抓取播放现场日志:

bash 复制代码
adb devices -l
adb -s <device_serial> logcat -c
adb -s <device_serial> logcat -v threadtime > full.log

同时过滤播放器关键日志:

bash 复制代码
adb -s <device_serial> logcat -v threadtime \
  | rg --line-buffered 'JZMediaExo|JzvdPro|ExoPlayer|MediaCodecAudioRenderer|MediaCodec|CodecException|Decoder failed|ERROR_CODE_DECODING_FAILED|onPlayerError|Audio Codec Error|seekTo|onError'

现场日志中如果出现以下组合,基本可以和源文件异常对齐:

text 复制代码
seekTo <大于视频轨实际时长的时间点>
Audio Codec Error
MediaCodecAudioRenderer error
Decoder failed: c2.android.aac.decoder
ERROR_CODE_DECODING_FAILED
onError 1000 - 1000

修复验证

如果只需要保留有效视频内容,可裁掉异常音频拖尾:

bash 复制代码
ffmpeg -hide_banner -y -v error \
  -i /path/to/input.mp4 \
  -to 3377.027 \
  -map 0:v:0 -map 0:a:0 \
  -c copy -movflags +faststart \
  /path/to/output_trimmed.mp4

验证裁剪后的文件:

bash 复制代码
ffprobe -hide_banner -v error \
  -show_format \
  -show_streams \
  /path/to/output_trimmed.mp4

ffmpeg -hide_banner -v error \
  -i /path/to/output_trimmed.mp4 \
  -f null -

预期结果:

  • 输出文件总时长约 3377s,即 56分17秒
  • 视频轨和音频轨时长基本一致。
  • 全量解码不再报 AAC 解码错误。

注意:-shortest 对这类问题不一定有效,因为异常音频 packet 可能仍会保留在输出文件中。更可靠的方式是裁剪到坏 packet 之前。

相关推荐
程序员-Benothing1 小时前
MySQL 索引下推是什么?——深入理解 ICP 原理与实践
android·数据库·mysql
怀化纱厂球迷2 小时前
百度地图--android接入百度地图导航
android
AFinalStone2 小时前
Android 7系统无障碍服务(四)AccessibilityEvent 的产生与投递
android·无障碍服务
智购科技无人售货机工厂3 小时前
2026自动售货机热敏打印模块集成:从串口驱动到小票自动裁切的工程实践~YH
android·stm32·单片机·嵌入式硬件·系统架构
A13345553 小时前
苹果安卓手机播放器推荐:2026无广告4K怎么选
android·智能手机
hunterandroid5 小时前
ContentProvider 跨进程数据共享实战
android·前端
天空之城--5 小时前
Android输入法子系统深度解析
android
天空之城--7 小时前
Android全链路性能优化:从原理到实践的终极指南
android·性能优化
Meteors.7 小时前
Android 性能优化:05.CPU优化
android·性能优化
石头猫灯8 小时前
一次 CMS 被黑实录:完整事件思路梳理
android·学习