适合我的安卓电视的 ffmpeg 配置

ffmpeg / tv / mp4

找到了一个适合家里电视的 ffmpeg 编码配置,记录一下

问题

家里有一台安卓 4.4 的电视,比较老了,有些视频格式播放有问题,有的是黑屏, 有的是声音有异响或无声,所以一般我都把一些视频重新用 ffmpeg 以 h264 的格式再重新编码一下,再进行播放,不过处理后的视频还是会有语音和图像 不同步的问题。

尴尬的是,其他设备播放时并没有不同步的情况,所以我推测是这台电视性能 不太好,查了一下 cpu 是 ARM Cortex A53,至少标配播放 1080p 应该是没问题的 我也尝试降低压缩比或码率,试了不少组合,也没有太大的效果。

解决

最近偶然发现一个视频在我的电视上播放并不卡,而且清晰度也还可以,顿时来了 兴趣,它是怎么做到的?

我们可以用 ffmpeg -i 来查看文件的编码格式

  Metadata:
    major_brand     : isom
    minor_version   : 1
    compatible_brands: isomavc1
    creation_time   : 2021-09-17T14:38:28.000000Z
  Duration: 00:59:42.20, start: 0.000000, bitrate: 3076 kb/s
  Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 2947 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Metadata:
      creation_time   : 2021-09-17T14:38:28.000000Z
      vendor_id       : [0][0][0][0]
  Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 125 kb/s (default)
    Metadata:
      vendor_id       : [0][0][0][0]

看到了 yuv420p, tbr, tbn, tbc 几个我还没有试过的参数,搜索了一番,yuv 似乎是色彩 相关的编码,tbr, tbn, tbc 几个是跟时间相关的参数,看上去感觉只有这几个参数还没有 试过,接下来我们就试着在 ffmpeg 中设置这几个参数:

  • yuv420p: 这个比较简单 -pix_fmt yuv420p
  • tbr: 似乎没有这个参数,但是因为它和帧数相同,所以我们暂时用帧数的设定 -r 23.98
  • tbn: ffmpeg 的设定格式是倒数 -time_base 1/24000
  • tbc: 同样是倒数 -enc_time_base 1/47.95 尝试重新压缩了下视频发现,帧数居然较设定翻了一倍,所以又添加了一个参数 -vsync 2

这下转换后的视频的帧数正常了,在电视上试了下,也没有感觉到明显的不同步问题。

总结

我把 ffmpeg 的参数整理成一个了脚本文件 cmp4.sh

#!/bin/bash
AUDIO="-c:a aac -profile:a aac_low -b:a 125k"
VIDEO="-vf scale=1920:-1 -c:v libx264 -pix_fmt yuv420p -b:v 2M -maxrate 3M -bufsize 2M -time_base 1/24000 -enc_time_base 1/47.95 -f mp4 -r 23.98 -vsync 2"
ffmpeg -hwaccel cuda -i "${1}" $AUDIO $VIDEO "c-${1##*/}"

除了上面提到的参数,还有一些编码格式,码率以及符合我电视的参数,可以适当修改, 这样我们可以直接执行 cmp4.sh filename.mp4 来转换文件,新生成的文件会被命名为 c-filename.mp4

我没有深入去研究和介绍为什么我的电视会卡、这些参数具体是做什么的, 因为我只要它能用就好,不过如果你也遇到类似我的问题,试一下上面的办法, 如果解决了并且你想深入研究的话,可能 这里 是一个起点。