
Я читал о резке и сращивании с использованиемконкатно мне этого мало.
Я хотел бы вырезать отмеченные части видео и объединить в один видеофайл без перекодирования. Возможно ли вырезать и объединить (в памяти) за один раз?
Не должно быть теоретических ограничений на количество видеочастей для вырезания или соединения. Звук должен быть синхронизирован.
Видео: H.264+AAC
Редактировать:
Из ответов я узнал, что перекодирование видео все равно необходимо.
Я хотел бы уточнить, что вырезание видеоклипов из середины видеофайла может выполняться в несколько этапов. Я думал, что обработка видео за один раз будет иметь производительность, так как сэкономит некоторую активность ввода-вывода. Однако это не является целью само по себе.
решение1
Ваш вопрос, если я правильно понял, состоит из четырех основных частей:
- Как вырезать временной сегмент из фильма
- Как объединить несколько сегментов вместе
- Как сделать вышеперечисленное без перекодирования фильма, не теряя при этом качества
- Как сделать вышеперечисленное эффективно с точки зрения скорости
Вырезание временного отрезка
Вы можете вырезать сегмент, перейдя к его начальной точке с помощью параметра -ss
, а затем либо задав длительность сегмента с помощью -t
, либо задав конечную точку с помощью -to
:
# skip 30 seconds, then copy the next 60 seconds
ffmpeg -ss 30 -t 60 full-movie.mp4 segment.mp4
В документации ffmpeg, пожалуйста, ознакомьтесь с разделом5.4 Основные параметрыотносительно разницы между размещением опций -ss
и -t
перед входным файлом или перед выходным файлом. Поэкспериментировав с этим, вы можете обнаружить, что эта разница актуальна в вашем случае.
Важное примечание: Приведенный выше пример приводит к транскодированию видео. Ниже мы обсудим возможность сделать это без транскодирования.
Объединение нескольких сегментов
Существует три основных метода объединения фильмов, два из которых лучше всего описаны в этомстатья вики ffmpeg, а третье - этодемультиплексор concat. Если все ваши сегменты идентичны с точки зрения спецификации кодирования аудио/видео и формата контейнера, вы, вероятно, обнаружите, что самым простым методом будет протокол concat:
:
# merge the segments
ffmpeg -i "concat:seg1.mp4|seg2.mp4|seg3.mp4" final.mp4
Важно отметить, что это слияние, как и нарезка, снова перекодирует фильм, поэтому здесь мы имеем перекодирование перекода, что потенциально ухудшает качество видео, поэтому мыДействительнохотим избежать этого перекодирования насколько это возможно!
Резка и слияние без перекодирования
Причина, по которой примеры в предыдущих разделах требуют транскодирования, заключается в том, что каждый файл и каждый полученный сегмент — это отдельный фильм, который был упакован так, чтобы предоставить все, что вы ожидаете при открытии полного фильма, например, продолжительность фильма и другие метаданные. Но эй, вы не собираетесь воспроизводить их как отдельные фильмы, вы хотите, чтобы эти сегменты стали частью более крупного видеопотока. Поэтому вместо того, чтобы обслуживать ffmpeg с упакованными фильмами, вам лучше переупаковать — повторно мультиплексировать — входные файлы в потоковый контейнер реального времени, забыв о заголовках, которые вам на самом деле не нужны на этом этапе. В случае H.264 формат потокового мультиплексирования называется MPEG-TS, и вот как вы повторно мультиплексируете свой поток без его транскодирования:
# re-muxing the whole movie (see a better option in next example)
ffmpeg -i full-movie.mp4 -c:v copy -c:a copy -bsf:v h264_mp4toannexb full-movies-as-ts.ts
Ну, раз уж вы этим уже занялись, то можете воспользоваться этой возможностью и вырезать именно тот сегмент, который вам нужен:
# skip 30 seconds and re-mux a 60 seconds segment
ffmpeg -ss 30 -t 60 -i full-movie.mp4 -c:v copy -c:a copy -bsf:v h264_mp4toannexb segment.ts
При слиянии сегментов TS вы также можете выполнить обратное мультиплексирование в контейнер mp4:
# merge the segments and re-mux them as mp4
ffmpeg -i "concat:seg1.ts|seg2.ts|seg3.ts" -c:v copy -c:a copy -movflags empty_moov -flags global_header -bsf:v dump_extra edited-final.mp4
Итак, теперь мы сделали все это без перекодирования фильма, сохранив оригинальное качество. Но, как всегда, есть оговорка...
ПРЕДОСТЕРЕЖЕНИЕ: Резка может быть выполнена только на границе ключевого кадра. Объяснение: H.264 организует сжатые кадры в пакеты, каждый из которых начинается с полного, но сжатого изображения первого кадра, за которым следуют дельты следующих кадров, тем самым уменьшая объем памяти, необходимый для каждого пакета. Для наших целей каждый пакет подобен запечатанному zip-архиву всех кадров на эту длительность — либо все, либо ни одного. Если вам нужна только часть пакета, то вам придется распаковать его и заархивировать обратно, другими словами — перекодировать его. Таким образом, описанный выше метод актуален только в том случае, если у вас есть ключевой кадр в каждой позиции, где вы хотите вырезать фильм. Например, если у вас есть ключевой кадр каждые 5 секунд, вы можете вырезать его только каждые 5 секунд.
Итак, теперь вопрос в том, можете ли вы принять ограничения на точки резки, особенно потому, что вы, вероятно, понятия не имеете, где в вашем фильме у вас есть ключевые кадры. И вот почему я предложил выше прочитать в5.4 Основные параметрыоб указании -s
and -t
перед входом или перед выходом. Если вы укажете перед входом, то ffmpeg найдет ближайший ключевой кадр для выполнения вашего запроса, который будет "более или менее" там, где вы хотели выполнить разрез. Если вас не волнует точность разреза, то хорошо, дерзайте.
Но если вам нужно, чтобы разрез был именно в этом месте, то у вас нет выбора, вы должны декодировать фильм, чтобы точно определить кадр, который вы ищете. Ну, по крайней мере, у нас естьнекоторыйХорошие новости: вместо перекодирования и повторного перекодирования можно обойтись одним перекодированием, что несколько улучшает ситуацию:
# skip PRECISELY 30 seconds and transcode a 60 seconds TS segment
ffmpeg -i full-movie.mp4 -ss 30 -t 60 -bsf:v h264_mp4toannexb segment.ts
Поскольку полученные сегменты будут находиться в TS, нет необходимости в повторном перекодировании при объединении сегментов.
Скорость
встатья в вики ffmpeg о слиянииесть объяснение того, как запустить весь процесс через каналы, тем самым устраняя необходимость в промежуточных файлах и ускоряя весь процесс.НЕ.Это займет у васдольше. Причина, по которой выполнение всего этого в памяти займет больше времени, заключается не в том, что это будет работать дольше, а в том, что у вас не будет промежуточных результатов, пока вы будете выяснять, как все это сделать, и вы обнаружите, что запускаете весь процесс снова и снова. Так что теория каналов хороша, но в вашем случае вам следует начать с разработки и совершенствования каждого шага. Вы обнаружите, что для того, чтобы все работало и давало достойный результат, потребуется еще немного доработки и настройки. Как только вы освоите весь процесс и захотите написать скрипты для автоматизированного массового редактирования, вы можете вернуться к концепции конвейера.
Надеюсь, вышеизложенное поможет.