TikTok 视频转码方案调研

0x00 简述

Tiktok的转码基于两个维度:质量 & 分辨率
质量包括 normallowerlowest 三个档次,主要使用crf值来控制;分辨率 包括 720p540p480p360p 四个档次,主要使用视频宽度来控制;具体的转码结果是质量 & 分辨率 两个维度结合产生的,如normal_720plower_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 视频转码方案调研_第1张图片

后来基于某一契机,我拿到了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转码可能还有我们未发现的问题,暂时搁置。

你可能感兴趣的:(linux,ffmpeg,cv,cv,ffmpeg)