Подтвердить что ты не робот

Как извлечь временные видео сегменты с помощью ffmpeg?

Здесь нет особо нового вопроса, но я пробовал то, что было предложено там без большой удачи. Итак, моя история:

У меня есть кусок 15 секунд прямолинейного видео, из которого я хочу извлечь конкретный фрагмент, который я могу определить по времени начала и времени остановки в секундах. Я начал, пытаясь сделать то, что я назову "извлечение копии": чтобы получить секунды с 9 по 12,

ffmpeg -i test.mov -vcodec copy -acodec copy -ss 9 -to 12 test-copy.mov

Это было неплохое начало, но в начале и конце клипа есть черные кадры, которых я не могу - это должно быть чистое редактирование из оригинала. Итак, я попробовал перекодировать оригинал в новый обрезанный клип:

ffmpeg -i test.mov -ss 00:00:09 -t 00:00:03 test-out.mov

Это лучше, но не совсем: в начале клипа больше нет черных кадров, но они все еще там в конце.

После некоторого просмотра и чтения я тогда подозревал, что проблема в том, что ffmpeg не может найти правильные точки из-за отсутствия ключевых кадров в исходном видео. Поэтому я перекодировал исходное видео (предположительно), добавляя ключевые кадры несколькими способами. Поскольку я хочу, чтобы иметь возможность выбирать видео на границах секунды ( "от 9 секунд до 12 секунд" ), я пытался, копируя различные предложения по сети,

ffmpeg -i test.mov -force_key_frames "expr:gte(t, n_forced)" test-forced.mp4

и

ffmpeg -i test.mov -g 1 test-g-inserted.mp4

(Я построил их как mp4 на основе некоторых комментариев о контейнере mp4, который необходим для поддержки поиска ключевого кадра, но я, честно говоря, просто взламываю здесь.) Затем я попробовал извлечение, как и раньше, но на этих новых видео, которые предположительно теперь в них есть ключевые кадры. Не повезло - оба кажутся примерно одинаковыми; начало в порядке, но в конце все еще есть черные кадры. (FWIW, как test-forced.mp4, так и test-g-insert.mp4 также имеют завершающие черные кадры.)

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

4b9b3361

Ответ 1

Хорошо, прежде всего, предполагая, что вы знаете продолжительность начала и остановки; мы добавим ключевые кадры в эту продолжительность.

ffmpeg -i a.mp4 -force_key_frames 00:00:09,00:00:12 out.mp4

В большинстве случаев вы можете напрямую разрезать видео с совершенством, но в вашем случае это вам не поможет; поэтому мы позаботились об этом над командой. Здесь будьте осторожны, чтобы не добавлять слишком много ключевых кадров, поскольку это может быть проблемой при кодировании по Ffmpeg Docs.

Теперь вы можете снова попробовать отрезать видео с определенного времени.

ffmpeg -ss 00:00:09 -i out.mp4 -t 00:00:03 -vcodec copy -acodec copy -y final.mp4

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

Приветствия:.)

Ответ 2

Я думаю, что проблема, с которой возникает вопрос и другие ответы, заключается в том, что они используют -ss в качестве опции в выходном файле, а не во входном файле. Большинство параметров ffmpeg не являются глобальными, а применяются только к файлу, которому они предшествуют. Часто неясно, где должен идти вариант, поэтому иногда требуются проб и ошибок.

Используется правильно, перед входным файлом, к которому они предназначены, -ss и -t отлично работают для меня. При включении звука на выходе мне пришлось использовать -shortest в качестве опции для выходного файла, или я бы получил 2 минуты аудио с 2 секундами видео.

версия ffmpeg N-67413-g2a88c74 (в основном git источник с 14 декабря 2014 года)

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

ffmpeg -ss 120.2 -t 0.75 -i ../mcdeint.60p.lossless264.slow.mkv -c:a libopus -shortest -aspect 16:9 -preset veryslow -x264-params nr=250:ref=6 -crf 22 -movflags +faststart clip2.mkv

С -c:a copy (источник имеет аудио AC3), воспроизведение запускается с помощью mplayer. Вероятно, он захватывает звук с начала звукового фрейма, содержащего начало, а затем должен использовать смещение a/v в контейнере. При запуске требуется часть секунды для звука, чтобы опередить видео с помощью этого смещения, и до тех пор воспроизведение видео происходит с очень низким FPS. Поэтому я закодировал аудио. Ни opus, ни pcm_s16le не могут идти в mp4, поэтому я использовал контейнер mkv для этого примера.

Источник - это код без потерь x264 (-qp 0) из выхода очень медленного yadif = 3: 1, mcdeint = 3: 1:10 (на некотором чересстрочном видео BFF с NTSC DVD, возможно, с DV камера). Это НЕ все I фреймы, кадры P с нормальным интервалом ключевого кадра.

Настройка -ss на 0,2 секунды сделала именно то, что я надеялся, поэтому ffmpeg должен обрабатывать декодирование до требуемой точки. Это было не просто совпадение I-кадра, где я его хотел. Может быть, -accurate_seek по умолчанию? Я также получаю тот же результат (байт-байтовый идентичный выход gif), как при использовании источника без потерь ffvhuff в качестве входных данных. (но он работает быстрее, так как он не должен декодировать до требуемой точки.)

Другой возможный вариант - -seek2any, но он говорит: "Ищите не-ключевой кадр на уровне демультиплексирования", который звучит так, как будто это позволит вам искать способами, которые будут создавать искаженный вывод. (т.е. начать декодирование без фактического создания ссылок, которые требуется текущему кадру, просто используйте серо-серый?)

Я не пробовал использовать -c:v copy, так как я вырезаю очень короткий клип для цикла, поэтому я знаю, что не будут I фреймов, где они мне нужны.

Это командная строка, которую я фактически использовал, чтобы сделать короткий клип slo-mo без звука.

ffmpeg -ss 120.2 -t 0.75 -i ../vid.yadif3.1,mcdeint3.1.10.ffvhuff.mkv -an -shortest -aspect 16:9 -c:v libx264 -preset veryslow -x264-params nr=250:ref=6 -crf 22 -filter:v "setpts=3.0*PTS" -movflags +faststart -r 20 clip.mp4

Обратите внимание, что значение -r 20 было важно, потому что в отличие от mkv, выход ffmpeg MP4 является константой-частотой кадров (edit: потому что -vsync vfr не является значением по умолчанию с помощью mux4 mp4). Не говоря о другом, он установил бы выход FPS = ввод FPS и дублировал бы фреймы, когда это было необходимо, чтобы это произошло. x264 и анимированный gif (с прозрачностью) могут очень эффективно кодировать повторяющиеся кадры, но это все еще глупо.

Прежде чем приготовить это в качестве примера, я сделал это в 2 этапа, один из которых вывел на mkv, а затем ffmpeg -i clip.mkv -c:v copy -movflags +faststart -r 20 clip.mp4 в remux. BTW, возможно изменить fps видео при ремуксировании без xcoding, просто не с ffmpeg. https://superuser.com/questions/740196/reducing-video-size-with-avconv-why-does-the-size-increase. Но в любом случае ffmpeg отправил только 45 кадров в libx264 при создании mkv, хотя он думал, что делает 2,2-секундное видео со скоростью 60 кадров в секунду. Не используйте ffmpeg с mp4 для работы с переменными материалами FPS.

edit: получается ffmpeg по умолчанию -vsync vfr для вывода mkv, но не для mp4. С помощью -vsync vfr ffmpeg может записывать VFR в вывод mp4 просто отлично.

И снова для вывода gif, в случае, если я решу не размещать его с видео HTML5 (<video controls autoplay loop> <source src="clip.mp4" type="video/mp4"> </video>)

ffmpeg -ss 120.2 -t 0.75 -i ../vid.yadif3.1,mcdeint3.1.10.ffvhuff.mkv -an -shortest -aspect 16:9 -filter:v "setpts=3.0*PTS,scale=854x480" -r 20 clip.gif

Мне пришлось использовать scale=, потому что контейнер gif не сохраняет пропорции, поэтому он не может автоматически масштабироваться при воспроизведении. (мое видео с разрешением 720x480 пикселей 16: 9 становится масштабированным до 854x480 при воспроизведении. На самом деле должно быть 853,333, но это округляется, а затем ffmpeg хранит 853x480 в контейнере mkv, поэтому все время используется -спектр 16: 9, поэтому мой mp4 будет сохраните правильное соотношение сторон [SAR 32:27 DAR 16:9] вместо [SAR 186:157 DAR 279:157])

Ответ 3

Нет необходимости добавлять ключевые кадры; как говорит Питер, это просто вопрос получения вариантов в правильном порядке. Однако см. https://trac.ffmpeg.org/wiki/Seeking для окончательного официального руководства о том, как сделать это правильно.

Ответ 4

Я тоже хотел бы знать. До сих пор я без потерь конвертировал видео, извлекал сегмент и перекодировал их после редактирования:

ffmpeg -i input -ss 9.48 -t 3.52 -c:v libx264 -crf 0 -g 1 -c:a copy TempIframe.mp4

Но это трудоемкий процесс с потерями...

Я пробовал следующий без успеха:

ffmpeg -i source.mp4 -ss 1 -c:v copy -seek2any 1 -avoid_negative_ts 1 -safe 1 -c:a copy segment.mp4