0x00 简述
Tiktok的转码基于两个维度:质量
& 分辨率
。
质量
包括 normal
、lower
、lowest
三个档次,主要使用crf值来控制;分辨率
包括 720p
、540p
、480p
、360p
四个档次,主要使用视频宽度来控制;具体的转码结果是质量
& 分辨率
两个维度结合产生的,如normal_720p
、lower_480p
等
详细的质量
& 分辨率
定义 如下:
质量定义
质量标识 | crf | 音频比特率 |
---|---|---|
normal | 24 | 64k |
lower | 29 | 64k |
lowest | 32 | 48k |
分辨率定义
分辨率标识 | 宽 | 高(约) |
---|---|---|
720p | 576 | 1024 |
540p | 540 | 952 |
480p | 480 | 854 |
360p | 240 | 426 |
0x01 各清晰度参数对比
视频总时长为 00:00:11.65,在mbp2015上使用ffmpeg 4.1 版本进行转码的效果如下
标识 | 文件大小 | 比特率 | 宽高 | crf | 音频比特率 | 转码耗时 |
---|---|---|---|---|---|---|
原始视频 | 9.8M | 6998kb/s | 1920x1088 | - | 128kb/s | - |
normal_720p | 5.3M | 3766kb/s | 576x1024 | 24 | 64kb/s | 7.993s |
lower_720p | 3.3M | 2348kb/s | 576x1024 | 29 | 64kb/s | 7.198s |
lowest_720p | 1.9M | 1356kb/s | 576x1024 | 32 | 48kb/s | 5.872s |
normal_540p | 5.0M | 3573kb/s | 540x952 | 24 | 64kb/s | 7.842s |
lower_540p | 3.0M | 2091kb/s | 540x952 | 29 | 64kb/s | 6.432s |
lowest_540p | 1.7M | 1195kb/s | 540x952 | 32 | 48kb/s | 5.330s |
normal_480p | 4.7M | 3327kb/s | 480x854 | 24 | 64kb/s | 6.961s |
lower_480p | 2.4M | 1652kb/s | 480x854 | 29 | 64kb/s | 5.496s |
lowest_480p | 1.3M | 908kb/s | 480x854 | 32 | 48kb/s | 4.715s |
normal_360p | 1.3M | 898kb/s | 240x426 | 24 | 64kb/s | 2.697s |
lower_360p | 540k | 308kb/s | 240x426 | 29 | 64kb/s | 2.293s |
lowest_360p | 302k | 155kb/s | 240x426 | 32 | 48kb/s | 2.207s |
Tiktok清晰度共有上述12种组合,但API并不会一次返回上述所有组合,目前发现API返回的组合方式有「normal_720p/lower_720p/lowest_720p」
、 「normal_540p/lower_540p/lowest_540p」
、「normal_720p/lower_720p/lowest_720p/lowest_480p/normal_360p」
、
「normal_540p/lower_540p/lowest_540p/lowest_480p/normal_360p」
等多种,此外,Tiktok中Save locally
功能默认保存的是normal_720
或者 normal_540p
视频。
0x02 详细转码指令
# normal_720p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 576x1024 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 24 normal_720p.mp4
# lower_720p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 576x1024 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 29 lower_720p.mp4
# lowest_720p
ffmpeg -y -i ori.mp4 -b:a 48k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 576x1024 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 32 lowest_720p.mp4
# ----------------
# normal_540p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 540x952 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 24 normal_540p.mp4
# normal_540p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 540x952 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 29 lower_540p.mp4
# lower_540p
ffmpeg -y -i ori.mp4 -b:a 48k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 540x952 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 32 lowest_540p.mp4
# ----------------
# normal_480p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 480x854 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 24 normal_480p.mp4
# lower_480p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 480x854 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 29 lower_480p.mp4
# lowest_480p
ffmpeg -y -i ori.mp4 -b:a 48k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 480x854 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 32 lowest_480p.mp4
# ----------------
# normal_360p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 240x426 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 24 normal_360p.mp4
# lower_360p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 240x426 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 29 lower_360p.mp4
# lowest_360p
ffmpeg -y -i ori.mp4 -b:a 48k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 240x426 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 32 lowest_360p.mp4
0x03 转码方案演进
之前由于Tiktok将其Encoding Setting抹掉了,无法完全还原其转码方式,为保证视频质量,选择在速度上做了妥协,随着任务量的增加,速度上的压力越来越难以忍受。
原转码方式示例
ffmpeg -y -i 1.mp4 -acodec copy -movflags faststart -c:v libx264 -strict -2 -preset veryslow -tune psnr -tune ssim -crf 28 o1_lower_720.mp4
ffmpeg -y -i 1.mp4 -acodec copy -movflags faststart -c:v libx264 -strict -2 -preset veryslow -tune psnr -tune ssim -crf 32 o1_lowest_720.mp4
ffmpeg -y -i 1.mp4 -acodec copy -movflags faststart -c:v libx264 -strict -2 -preset veryslow -s 480x854 -tune psnr -tune ssim -crf 32 o1_lowest_480.mp4
ffmpeg -y -i 1.mp4 -acodec copy -movflags faststart -c:v libx264 -strict -2 -preset veryslow -s 240x426 -tune psnr -tune ssim -crf 24 o1_normal_360.mp4
因此尝试了调整preset参数来加快转码速度,最终得出加快preset参数,降低crf参数,来达到增加转码速度的目的,具体调研结果如图
后来基于某一契机,我拿到了Tiktok的Encoding Setting,我也因此可以复现了Tiktok的转码方式(也就是上文给出的转码方式)。
新转码方式示例
# normal_540p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 540x952 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 24 normal_540p.mp4
# normal_540p
ffmpeg -y -i ori.mp4 -b:a 64k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 540x952 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 29 lower_540p.mp4
# lower_540p
ffmpeg -y -i ori.mp4 -b:a 48k -ar 44.1k -movflags faststart -c:v libx264 -strict -2 -s 540x952 -psy 1 -psy-rd 1.00:0.00 -chromaoffset -2 -threads 30 -maxrate 4000k -bufsize 8000k -preset slow -crf 32 lowest_540p.mp4
新的转码方式在质量上与原转码方式保持一致,文件体积和比特率也保持一致,但速度提升了4倍左右!
展望
我还调研了使用GPU对转码进行加速,速度上效果非常好,能提升数十倍(GPU: Tesla M40 ,CPU:Intel® Xeon® CPU E5-26xx v4 ),但由于调研中发现GPU转码的视频质量较CPU有差别,且考虑到行业巨头抖音也没有选择使用GPU,故GPU转码可能还有我们未发现的问题,暂时搁置。