Ролик после сжатия стал больше исходника
Когда появился раздел с тиктоками, первые же ролики из TikTok после «сжатия» стали весить больше, чем были. Обычное видео с телефона ffmpeg ужимает в 3–6 раз, а тут наоборот. Пришлось разбираться.
Как сжимается обычный ролик
Сервер приводит всё к одному виду: H.264, потому что его играет любой браузер, включая старые айфоны. Короткая сторона не больше 720 пикселей, не больше 30 кадров в секунду.
filters = ["scale='if(gt(iw,ih),-2,min(720,iw))':'if(gt(iw,ih),min(720,ih),-2)':flags=lanczos"]
if fps_of(video) > 31:
filters.append('fps=30')Формула в scale выглядит страшно, но смысл простой: у горизонтального ролика ограничивается высота, у вертикального — ширина, а вторая сторона считается сама. Качество задаёт -crf 28 с пресетом slow. Он медленнее, зато при той же картинке файл меньше.
Почему TikTok сжимать бесполезно
TikTok отдаёт видео, которое уже пережато сильнее, чем дал бы CRF 28. Кодек честно пытается сохранить качество и добавляет биты, отсюда и рост. Поэтому битрейт теперь ограничен долей от исходного, на первом проходе это 85%:
cap = max(48000, int(vbr * share))
args += ['-maxrate', str(cap), '-bufsize', str(cap * 2)]Если и так не вышло меньше оригинала, второй проход идёт построже: CRF 32 и 60% битрейта. Из двух вариантов остаётся меньший. А если исходник уже в H.264, рядом готовится копия вообще без пересжатия, просто перепакованная через -c copy. Часто выигрывает именно она, и качество при этом не теряется совсем.
Одно исключение осталось. Иногда TikTok отдаёт ролик в H.265, который играют не все браузеры. Перепаковать его нельзя, только пересжать в H.264, и тогда файл может выйти чуть больше. У одного ролика было 302 КБ, стало 322. Лишние 20 КБ лучше, чем чёрный прямоугольник вместо видео у кого-то на телефоне.
Чтобы видео начинало играть сразу
В mp4 есть служебный блок moov, что-то вроде оглавления файла. ffmpeg по умолчанию пишет его в самый конец, и браузеру приходится тянуть весь ролик, прежде чем показать первый кадр. Флаг -movflags +faststart переносит оглавление в начало, и видео стартует с первых килобайт.
И чтобы сайт при этом не тормозил
Сжатие идёт в фоне с самым низким приоритетом: Nice=19, не больше 60% процессора, а на диск пишет только тогда, когда он никому не нужен. Сеть у обработчика вообще отключена: ему незачем куда-то ходить, пока он жмёт видео.