Точная нарезка видео (+ аудио) с помощью ffmpeg

10

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

У меня есть исходный видеофайл, который я сначала хочу преобразовать во что-то подходящее для веб-сайта:

Input #0, matroska,webm, from 'source.mkv': 
Duration: 00:28:18.57, start: 0.000000, bitrate: 10183 kb/s 
Stream #0:0: Video: h264 (Constrained Baseline), yuv420p, 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 48 tbc (default)
Stream #0:1: Audio: mp3, 44100 Hz, stereo, s16, 128 kb/s (default)

Я использую ffmpeg, чтобы преобразовать его так:

ffmpeg -i source.mkv -c:v libx264 -c:a aac -strict experimental -vf scale="960:-1" source.mp4

Смотря это видео обратно, оно достаточно хорошего качества и достаточно маленького размера для моих нужд, и загружается / воспроизводится на моем веб-сайте.

У меня есть веб-страница, которая позволяет пользователям выбирать начальную и конечную точку в этом видео - и создавать клип. Вот пример команды ffmpeg, которую я использую для этого:

-ss 577.920 -i source.mp4 -t 011.980 -codec:v copy -codec:a copy -vf scale="960:-1" clip1.mp4

Проблема в том, что клип не всегда точен во времени. Обычно звук достаточно точный, но видео останавливается на полсекунды раньше или что-то в этом роде.

Есть ли способ сделать это точно и синхронно, скажем, 0,2 секунды?

РЕДАКТИРОВАТЬ: Добавление -force_key_frames 00:00:00.2не помогло.

РЕДАКТИРОВАТЬ: я изменил обрезку, чтобы использовать -c:v libx264 -c:a aac -strict experimentalвместо -codec:v copy -codec:a copyс хорошими (ish) результатами.

Файл может воспроизводиться внешне без проблем - но когда я загружаю его в свой элемент видео html5 и воспроизводю его - последняя часть видео (аудио в порядке) зависает. Последняя часть, которая замирает, длится менее секунды.

Должен ли я попробовать это с другим видео кодером? Какова лучшая альтернатива для libx264? Имея в виду, я, вероятно, хочу, чтобы это было на общедоступном веб-сайте.

Но подождите, разве тот факт, что он воспроизводится точно без проблем с таким проигрывателем, как MPC или Windows Media Player, не говорит о том, что это проблема либо с Google Chrome, либо с элементом HTML-видео? Или я использую неподдерживаемую кодировку или что-то?

Пит Оки
источник
Это может быть связано с синхронизацией ключевых кадров. В любом случае, это должно быть перенесено на SuperUser.com.
Брэд
Привет, ffmpeg не может обрезать видео в любой момент, он может обрезать только ключевые кадры; по этой причине звук почти точен, а видео нет.
Могу ли я переместить это сам? Я попытаюсь добавить ключевые кадры в исходный файл с помощью -force_key_frames 00: 00: 00.2
Пит Оки

Ответы:

9

Поведение -ssменяется в зависимости от того, используется ли оно в качестве параметра ввода или вывода, и часто оно медленнее, но может быть более точным при использовании в качестве параметра вывода. См. Ответ на ffmpeg, преобразующий видео из указанного периода времени для более подробной информации и примеров.

Для изменения качества продукции source.mp4используйте -crfпараметр со значением 18-28 (по умолчанию 23). См. Раздел CRF в Руководстве по кодированию FFmpeg и x264 для примеров.

Ваша команда обрезки может быть упрощена:

ffmpeg -ss 577.92 -i source.mp4 -ss 0 -t 11.98 -c copy -map 0 clip1.mp4

Я заменил -codec:v copy -codec:a copyна -c copy -map 0. Это скопирует все потоки, а не только первые видео- и аудиопотоки - хотя на входе есть только два потока из-за вашей предыдущей команды. Так как вы не можете масштабировать без перекодирования, поэтому, будучи взаимоисключающими -codec:v copy, и поскольку ваш вход уже масштабирован до заданного размера, я удалил опции фильтра.

Если это все еще не достаточно точно, то попробуйте:

ffmpeg -i source.mp4 -ss 577.92 -t 11.98 -c copy -map 0 clip1.mp4

Это будет медленнее, но, вероятно, более точным. См. Ссылки в ответе в первой предоставленной мной ссылке для описания различий этих двух примеров.

И, наконец, вы должны запустить source.mp4через qt-faststart(находится в каталоге инструментов в источнике FFmpeg), или используйте -movflags faststartопцию. Это позволит переместить некоторые данные в начало файла, чтобы можно было начать воспроизведение до его полной загрузки.

llogan
источник
+1 за советы, но я попытался ffmpeg -i source.mp4 -ss 577,92 -t 011,980 -c copy -map 0 clip1.mp4, но первая часть (почти вторая) и последняя часть (возможно, четверть секунды) видео пропущено, звук в порядке, хотя.
Пит Оки
@PeteOakey Вы пробовали вырезать без битового потока, но с рекодированием?
Slhck
Пробовал без битрейта - результаты приложены к моему вопросу.
Пит Оки
3
Использование в -ssкачестве выходного параметра вместо входного параметра решило мою проблему: первый видеокадр составлял около 1 с в выходном видео, а перед ним был только звук (также подтверждено ffprobe -show_frames). Перемещение -ssпосле -iзаставило это вывести аудио и видеокадры, начинающиеся с кадра 0.
CodeManX