ENDERU
GitHub22 RepositoriesDaily Tech3 Abonnentenaudion.devdas ProduktregalRSSVeröffentlichungen
← Alle NotizenProjects

Нарезка: матрица форматов, методы проверки и грабли FFmpeg

English

Про интерфейс в этом документе. Точки реза находят в плеере mpv, который
открывается кнопкой из раздела, и переносят в поля кнопками — либо вводят
таймкодом с клавиатуры.

Справочник по разделу НАРЕЗКА. Всё, что здесь написано, измерено, а не взято из документации: каждая ячейка таблиц — реальная попытка записи с -c copy и чтением результата обратно, каждое число синхрона — замер по кадрам и сэмплам. Числа сняты на FFmpeg 9.0.1 и переснятые на 8.0.1 совпали до ячейки. Какая сборка попадёт в поставку — решает установщик по версии драйвера NVIDIA (на большинстве машин это ветка 8.x), поэтому обе проверены.

Раздел подробно — в TRIM_RU.md, решения — в DECISIONS_RU.md. Здесь — фактура по обрезке; полный свод измерений, включая пересчёт частоты и пределы самого FFmpeg, — в MEASUREMENTS_RU.md.


1. Что раздел делает

Нарезка копирует потоки (-c:v copy) и не перекодирует картинку. Отсюда четыре свойства, которые определяют всё остальное:

  • частота берётся у файла как есть: ffprobe отдаёт точную дробь

(24000/1001 для 23,976 и 24/1 для честных 24,000), и ничего не домысливается — камера снимает и то, и другое;

  • начало куска ложится на ключевой кадр (иначе поток нечем начать);
  • конец режется числом кадров по точной дроби частоты;
  • звук копируется как есть, кроме двух случаев (выбор канала и PCM в MXF), где

он переписывается сэмпл-в-сэмпл без потери поколения.

РежимЧто остаётсяТочек
Убрать началовсё после INодна (IN)
Убрать конецвсё до OUTодна (OUT)
Оставить серединукусок между IN и OUTдве
Разделитьвсе части, ничего не выбрасывается; стыки на ключевых кадрахN точек — N + 1 частей, до 30 точек

Строки + в Оставить и Вырезать — не новые режимы, а отдельные прогоны того же режима по тому же дублю, каждый в своём файле (_keep01, _cut01): всё измеренное здесь относится к каждому из них как к одиночному резу.


2. Контейнер × видеокодек

Пары «видео + звук, который контейнер точно принимает», запись -c copy, затем чтение обратно и сверка кодека.

ВидеоMP4MOVMKVMXFTSM2TS
H.264дададададада
HEVCдададанетдада
ProResнетдададанетнет
DNxHD/DNxHRнетдададанетнет
MPEG-2дададададада
AV1данетданетнетнет
VP9данетданетнетнет

Что из этого следует для практики:

  • ProRes и DNxHR живут в MOV, MKV и MXF. MP4 их не примет — попытка даёт

«Could not find tag for codec» и файл нулевой длины, поэтому такая пара отклоняется до запуска.

  • HEVC не идёт в MXF. Камерный HEVC (Canon, Sony) в MXF не переложить без

перекодирования — это отдельная операция, не обрезка.

  • AV1 и VP9 не идут в MOV.

3. Контейнер × аудиокодек

ЗвукMP4MOVMKVMXFTSM2TS
PCM 16 LEдадададанетнет
PCM 16 BE (twos, Canon)дададанетнетнет
PCM 24 LEдадададанетнет
PCM 32 floatдададанетнетнет
AACдададанетдада
AC-3дададанетдада
E-AC-3дададанетдада
MP3дададанетдада
FLACданетданетнетнет
ALACдададанетнетнет
Opusданетданетдада

Главное:

  • MXF принимает только PCM, и только little-endian. Это важно для Canon:

камера пишет pcm_s16be, и при выводе в MXF звук переписывается в pcm_s16le — те же сэмплы, порядок байт, который требует контейнер.

  • MPEG-TS не принимает PCM. Материал с AVCHD-карты со звуком PCM в TS не

переложить; MOV возьмёт как есть.

  • MOV не принимает FLAC и Opus, хотя MP4 принимает оба.

3.1. Звуковой файл

Звуковой файл не копирует поток, а декодирует его и режет по сэмплу, поэтому матрица контейнеров выше к нему не относится. Что куда пишется:

КнопкаКодекКонтейнерБез потерь
Как есть: PCMтот же PCMwav, w64, aif, aiff, caf, au, snd, mkaда
Как есть: FLAC, ALAC, WavPack, TTAтот жесвой или mkaда
Как есть: MP3, AAC, Opus, Vorbis, AC-3, E-AC-3тот же, битрейт исходникасвой или mkaодно поколение
WAVPCM разрядности исходника; float для сжатогоwav, RF64 после 4 ГБда
FLAC, ALACFLAC, ALACflac, m4aдо 24 бит
M4AAACm4aнет
MP3LAMEmp3нет
Opuslibopus, не больше 256 kbpsopusнет

Обложку держат MP3, M4A, FLAC, ALAC и MKA; WAV и Opus — нет.

Копирование пакетов (точная резка выключена) предлагается для MP3 в mp3, AAC в m4a и m4b, Vorbis в ogg и oga, Opus в opus, ogg и oga; для остального — нет. Во что обходится стык у каждого кодека — в TRIM_RU.md, замеры — в MEASUREMENTS_RU.md, раздел 12.3.


4. Точность реза

4.1 Кадры

Проверено на восьми синтетических источниках и одном камерном. Во всех случаях число кадров совпало с планом до единицы.

ИсточникЗапросКадровРасхождение
ProRes 25p3 → 91500
HEVC long-GOP 29.9712 → 306000 (после добора по декодируемым)
H.264 all-intra 23.9763 → 91440
29.97 drop-frame5 → 153300
59.94 drop-frame3 → 93600
MPEG-TS (старт 1.44 с)2 → 83000
4 канала PCM2 → 81500
Canon HEVC 4:2:2 10 бит3 → 101660
ARRI ProRes 4444 XQ 24,0002 → 81440
VFR (30 → 17.6)4 → 16по времени+1.07 с, объявлено

4.2 Синхрон звука

Метка есть в обеих дорожках одновременно: белый кадр в начале каждой секунды и щелчок в тот же момент. Отклонение считается от исходника, а не абсолютное.

КонтейнерИзменение против исходника
MP40…2 мс
MOV0…5 мс
MKV1…3 мс
MXF0…5 мс (после перезаписи PCM; до неё было 9…18)

На камерном файле звук найден в исходнике дословно: кусок начинается на 48 сэмплов (1 мс, сороковая доля кадра) после точки реза.

4.3 Метаданные

Проверено на файле с поворотом, двумя дорожками и тегами проекта:

ЧтоMP4MOVMKV
Поворот (rotation=90)дадада
Язык дорожек (rus, eng)дадада
Теги проекта (title, artist)дадада
Камерные теги (make, model, brands)дадачастично
Таймкод как дорожка tmcdдаданет (текстовый тег)

Камерные теги переносит -movflags use_metadata_tags; без него MP4-мультиплексор пишет свои isomiso2mp41 и теряет make, model и бренд вроде mp42hvc1CAEP.


5. Грабли FFmpeg, найденные измерением

Каждая стоила отдельного разбора; ни одна не очевидна из документации.

№ГрабляПроявлениеКак обойдено
1-ss до -i сбрасывает время-to после него считает от нового нуляхвост уезжает как длительность/кадры, не как абсолютная точка
2round(fps) на дробных частотах4 минуты на 29.97 превращаются в 240.27 счастота живёт как Fraction от ffprobe до ffmpeg
3Округление конца «к ближайшему»теряется кадр, стоящий на 29.9966 при запросе 30.0конец округляется вверх
4-t при копированииперебор на 1–3 кадра на потоке с B-кадрамихвост задаётся -frames:v
5-frames:v точен только с точным -ssпри -ss мимо ключевого кадра кусок короче на зазорseek всегда на вычисленный ключевой кадр
6HEVC с B-пирамидоймуксер пишет на 2–4 кадра меньше, чем просилинедобор измеряется и рез повторяется один раз с поправкой
7-avoid_negative_ts make_zeroвидео уезжает на 0.1 с от звукане используется
8start_time ≠ 0 (MPEG-TS 1.44 с)все точки смещаются на эту величинусмещение снимается с ключевых кадров и возвращается при seek
9avg_frame_rate на VFRсчёт кадров покрывает не тот отрезок (12 с → 16 с)VFR определяется и режется по времени, с предупреждением
10-n на существующий файл«already exists», код возврата 0цель проверяется до запуска
11PCM в MXF при -c copy384 лишних сэмпла в начале (8 мс)PCM переписывается сэмпл-в-сэмпл (LE)
12-map_metadata 0 в MP4камерные теги и бренды теряются-movflags use_metadata_tags
13`pan=monoc0=c1` на монопишет тишину, код возврата 0число каналов проверяется до запуска
14MXF + сжатый звук«Could not write header», код 4294967274отклоняется до запуска с объяснением
15Пакет ≠ кадрмуксер пишет 600 пакетов, декодер отдаёт 597: хвостовые B-кадры ссылаются за границу резанедобор ловится по длительности потока и добирается по декодируемым кадрам
16Камерный RAW в MXFcodec_name пуст, размеры нулевые, «dimensions not set», файл нулевой длиныотклоняется до запуска: у FFmpeg нет декодера X-OCN и ARRIRAW
17Предупреждение ломает разбор JSONstderr подмешивается в stdout, и json.loads падает на строке «could not resolve file descriptor strong ref»пробы читаются с разделёнными потоками

6. Как всё это меряется

Команды, которыми получены числа выше. Их же стоит использовать при следующей проверке — иначе результаты не сравнить.

Кадры. Считать пакеты, а не декодировать: результат тот же, время — в сорок раз меньше (0.14 с против 5.7 с на четырёх минутах 59.94).

ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 FILE

Ключевые кадры вокруг точки, без сканирования всего файла:

ffprobe -v error -select_streams v:0 -skip_frame nokey -read_intervals "START%+WINDOW" -show_entries frame=pts_time -of csv=p=0 FILE

Синхрон. Нужен источник с меткой в обеих дорожках: белый кадр и щелчок в один момент. Видео читать через signalstats с -fps_mode passthrough — иначе фильтр продублирует кадры под свои часы и сдвинет времена:

ffmpeg -v info -i FILE -map 0:v:0 -vf "signalstats,metadata=print:key=lavfi.signalstats.YAVG" -fps_mode passthrough -f null -

Звук — по сэмплам, а не через silencedetect: детектор работает окнами по 20 мс, а мерить приходится единицы миллисекунд.

ffmpeg -v error -i FILE -map 0:a:0 -ac 1 -ar 48000 -f s16le -

Побитовая проверка копирования. Найти звук куска внутри звука исходника: если он там есть дословно, звук скопирован, а позиция даёт точное смещение реза.

Совместимость. Записать одну секунду -c copy в контейнер и прочитать обратно. Партнёрский поток подбирать под контейнер: MXF не примет AAC, TS не примет PCM, и без этого ячейка покажет отказ партнёра, а не проверяемого кодека.

Ловушки самих измерений

Три ошибки, на которых я уже спотыкался — стоят того, чтобы их не повторять:

  1. Сравнивать «первую найденную вспышку» с «первым найденным щелчком». Если

один поток открывается меткой, а другой нет, детекторы описывают разные события — получается «рассинхрон 107 мс», которого нет.

  1. Мерить синхрон детекторами FFmpeg. blackdetect работает целыми кадрами,

silencedetect — окнами; вместе они дают 40 мс погрешности, то есть больше, чем измеряемая величина.

  1. Проверять совместимость по коду возврата. Файл может записаться и не

читаться обратно; TS «принимает» ProRes ровно так.


6.1. Камерный RAW: чего инструмент не может

Два формата, которые FFmpeg не открывает ни в какой версии — проверено и на 8.0.1, и на 9.0.1:

ФайлЧто внутриЧто видит ffprobe
Sony BURANO X-OCN LTX-OCN в MXF OP1aпоток без имени кодека, width=0, звук pcm_s24le читается
ARRI Alexa Mini .mxfARRIRAW в MXFто же самое

Попытка простого копирования даёт «dimensions not set» и файл нулевой длины, поэтому такие исходники отклоняются до запуска с прямым объяснением. Резать их можно в родном ПО производителя (Sony Catalyst, ARRI Reference Tool) или после транскода.

Тот же материал в MOV режется полноценно: ARRI ProRes 4444 XQ (2944×2160, 12 бит, 5 дорожек PCM) прошёл кадр в кадр, вместе с таймкодом 02:00:11:11 → 02:00:13:11.


7. Чего мы не проверяли

Список открытый — чтобы никто (включая автора) не решил, что матрица закрыта:

  • камеры, кроме Canon HEVC и ARRI ProRes: Sony XAVC, Panasonic, BMPCC, GoPro с

телеметрией, AVCHD прямо с карты;

  • файлы длиннее часа (час проверен: 50,7 ГБ, рез кадр в кадр на 58-й минуте

и на последних секундах — см. MEASUREMENTS_RU.md);

  • нехватка места на диске в середине записи;
  • источник на сетевом пути или занятый другой программой;
  • две операции одновременно;
  • звук 96 кГц и 32 бита float в реальном материале;
  • звук, идущий за последним кадром на границу пакета: после добора хвоста он

уходит вперёд на 0,1 с и об этом сообщается, но на слух это не проверялось;

  • звуковые файлы с настоящего рекордера (poly-WAV, iXML), копирование пакетов

AC-3, E-AC-3, DTS и AAC вне M4A.

Bearbeitet 16.10.2026