Паспорт генерации изображения
Промт генерации изображения
Dark neon 'underside of progress' scene, cyberpunk workshop mood. A strip of video sliced into even segments, cold teal-cyan frames of equal width in a row; from one segment a warm amber audio-track tail leaks out past the frame edge and stretches its false length, a timestamp that lies; cold frame grid versus the amber overrun tail. Glowing waveform threads, etched frame numbers, scanline flicker, dust and rain-on-glass texture. Deep shadow, volumetric haze, warm amber and cyan color palette, shallow depth of field, cinematic film still on 35mm, intricately detailed, ultra-detailed, fine textures, rich layered background, ornate mechanical detail, sharp focus, moody atmosphere.
Записал десять минут - в метаданных семнадцать. Разбор того, как две дорожки с разным ритмом создают иллюзию лишнего времени.
Симптом проявился при настройке домашнего NVR. Задача простая: резать RTSP-поток с камеры на сегменты, чтобы архив не превратился в один бесконечный и битый файл. Но в метаданных происходила странная экспансия. Сегмент, который должен был длиться 30 секунд, по данным ffprobe закрывался с отметкой 00:00:53.92. Почти минута там, где данных на полминуты. Плеер сходит с ума: полоса прокрутки растягивается, навигация прыгает.
Записал десять минут - в теории должен получить ровно десять, а по факту коэффициент завышения держится в районе 1.7. То есть вместо десяти минут получаем семнадцать.
Поиск виноватого в муксере
Первым делом возникло подозрение на Matroska. Казалось очевидным: муксер просто игнорирует флаг -reset_timestamps 1 и не обнуляет временные метки (PTS) между кусками. В итоге каждый следующий сегмент «наследует» время предыдущего, и длительность превращается в кашу.
Проверил. Попробовал сменить контейнер, поиграть с флагами синхронизации - результат не менялся. Приборы рапортовали, что всё настроено верно, но цифры в Duration продолжали врать.
Ошибка оператора и зомби-процессы
На этом этапе в дело вступил ИИ. Я скормил ему свою команду и попросил найти, где я мог ошибиться в логике запуска. Ответ пришёл сухой и бьющий точно в цель:
«Посмотри на позицию флага
-t. Он стоит после имени выходного файла. В ffmpeg порядок аргументов имеет значение: всё, что идёт после вывода, относится к следующему (несуществующему) выходному потоку. Твой лимит времени просто игнорируется».
Оказалось, я сам создал ловушку. Из-за неправильного порядка аргументов процесс не останавливался вовремя, плодил «зомби-прогоны» в фоне через SSH и портил все контрольные замеры. Перенёс -t перед -i. Сегменты стали честными по размеру, но проблема с Duration в метаданных никуда не делась. reset_timestamps был невиновен, но и решение не нашлось.
Матрица вместо гадания
Когда простые перестановки флагов перестали работать, ИИ предложил перестать гадать и построить матрицу A/B тестов. Мы развели контейнер, аудиокодек и наличие звука как отдельные переменные.
Результаты в таблице оказались отрезвляющими:
- MKV (только видео) → Duration 00:00:30.05 (Идеально).
- MKV (видео + аудио копия) → Врёт (+70%).
- TS (транспортный поток, разные кодеки) → Врёт.
Стало ясно: виноват не контейнер и не конкретный флаг. Проблема в сочетании двух дорожек с разной временной сеткой. Видео идёт с частотой 20 fps, звук - 8000 Гц. При включённом reset_timestamps звуковой «хвост» неизбежно утекает за границу последнего ключевого кадра видео.
Муксер считает Duration по простейшей формуле: «последний таймстемп минус первый». Поскольку звуковой пакет оказывается чуть дальше, чем финальный кадр видео, ffmpeg записывает в метаданные общую длину этого разрыва. В итоге получаем те самые 53 секунды вместо 30.
Чистка потока
Решение оказалось радикальным, но единственно верным для сырого архива: вырезать звук на этапе нарезки. Если нам нужна точная навигация и низкая нагрузка на CPU, лишние хвосты аудиопотока только мешают.
Команда для продакшена теперь выглядит так:
ffmpeg -map 0:v:0 -c copy -f segment -segment_time 600 -segment_format mpegts -reset_timestamps 1 -strftime 1 [output_name].mp4
Проверка подтвердила: реальный десятиминутный сегмент теперь имеет Duration 00:10:00.05. Погрешность в пять сотых секунды - это уже цена честного цифрового тайминга.
Закон разных сеток
Эта история вывела меня на своего рода «закон» сегментации: как только в потоке встречаются две дорожки с разными PTS-сетками и активируется reset_timestamps, Duration закрытых сегментов будет завышен.
Это не баг конкретной версии ffmpeg и не ошибка в одном флаге. Это структурное свойство сегмент-муксера. Нельзя одновременно сохранить аудио в raw-копии, обеспечить идеальную навигацию по сегментам и оставить Duration в точности равным segment_time без перекодирования или сложного выравнивания таймстемпов.
Иногда прогресс - это не когда инструмент делает всё за тебя, а когда ты понимаешь, почему он делает именно так. И роль напарника-ИИ здесь была не в том, чтобы «починить», а в том, чтобы заставить меня перестать верить своим глазам и начать строить матрицы.
Часть темы «Умный дом без облака» - там собраны остальные разборы этого стека.
