Как объединить несколько (более двух) видео в Ubuntu?


39

Я хочу объединить видео в партии размером двадцать (20) каждый. Я работаю на машине с Linux. Видео в формате mp4 и среднего качества. У некоторых даже отсутствует аудиопоток. До сих пор я пытался ffmpeg, mencoder, cvlc/vlcи MP4Box. Я хочу написать сценарий командной строки для достижения этой цели, так как я делаю пакетную обработку.

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


2
Пожалуйста, не задавайте один и тот же вопрос на нескольких сайтах SE: superuser.com/questions/928548/…
Maythux

Не могли бы вы опубликовать конкретно, что вы пробовали до сих пор?
ohaal

1
@ohaal Я пытался использовать различные методы конкатенации, в ffmpegтом числе фильтры и файловые протоколы. Я также пытался использовать concatфункцию cvlc/vlc. Я также попробовал concatфункцию mencoder. Все это работало частично. Это наконец помогло мне решить проблему.
Дхрув Сингал

Да, вы уже упоминали инструменты, я имел в виду именно те команды, которые вы выполняли. Также было бы здорово, если бы вы включили команду, которая в конечном итоге решила ее для вас (в вашем ответе), для будущих посетителей.
ohaal

Ааа, я вижу твою точку зрения К сожалению, я не могу перечислить команды из-за большого числа. Команда, решить мою проблему было этоmelt {input-sequence} -consumer avformat:{output-name} acodec=libmp3lame vcodec=libx264
Dhruv Singal

Ответы:


41

Я использую, mkvmergeчтобы объединить несколько файлов MP4 в один:

mkvmerge -o outfile.mkv infile_01.mp4 \+ infile_02.mp4 \+ infile_03.mp4

3
Лучше использовать расширение .mkvдля выходного файла, так как это контейнер Matroska, независимо от того, какое расширение вы даете.
haridsv

Вот как установить mkvmerge: tipsonubuntu.com
Моргот

Только эта команда mkvmerge работает. Все ffmpeg терпят неудачу по крайней мере со сдвинутым звуком.
42n4

25

Вы можете сделать это используя ffmpeg:

ffmpeg -i concat:"input1.mp4|input2.mp4" output.mp4

справка и дополнительная информация


2
Я пытался это сделать. Проблема с этим состоит в том, что это не дает должного. 1. Аудиодорожки запутаны. 2. На видео-треке есть помехи.
Дхрув Сингал

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

Вы, вероятно, правы. Это решило проблему: askubuntu.com/a/637179/420614
Дхрув Сингал

2
Не используйте протокол concat для объединения MP4. Он работает только с определенными форматами, с которыми большинство обычных пользователей не сталкиваются. Вместо этого используйте concat demuxer или concat filter .
Llogan

Я попробовал ffmpeg с 2 mp4 файлами по 30 минут каждый. Я получил выходной файл длиной 7 часов.
Гус

7

Это решило вопрос: https://stackoverflow.com/a/22324018/5014767

meltэто отличная утилита командной строки для этого. Вот эта страница

Редактировать из комментариев: команда, которая решила мою проблему, была эта melt {input-sequence} -consumer avformat:{output-name} acodec=libmp3lame vcodec=libx264


4

Я написал небольшой сценарий оболочки для объединения MP4 без транскодирования с использованием ffmpeg.

for f in $(ls *.MP4); do
    ffmpeg -i $f -c copy -bsf:v h264_mp4toannexb -f mpegts $f.ts
done

CONCAT=$(echo $(ls *.ts) | sed -e "s/ /|/g")

ffmpeg -i "concat:$CONCAT" -c copy -bsf:a aac_adtstoasc output.mp4

rm *.ts

Это создает промежуточные файлы в контейнере MPEG и затем объединяет их в MP4.


Важно отметить, что этот скрипт не будет работать, если любое из имен файлов содержит пробелы или, в некоторых случаях, специальные символы. Для цикла значительно лучше использовать просто for f in *.MP4без использования ls. (Вы всегда должны избегать использования lsв сценариях по нескольким важным причинам; есть лучшие варианты.) Кроме того, используйте кавычки для переменных, если вы не уверены, что нет пробелов или других специальных символов, поэтому "${f}"(или просто "$f") вместо кавычек $f.
Пэдди Ландау

CONCAT=$(echo $(ls *.ts) | sed -e "s/ /|/g")не очень хорошо работает с именами файлов 1, 2, 3 ... 10 ... 20. В итоге они разбираются как 1, 10 ... 2, 20 ... и т. д. Я полагаю, CONCAT=$(echo $(ls -v *.ts) | sed -e "s/ /|/g")это обеспечит порядок ,
tisaconundrum

2

Создайте файл files.txt со всеми файлами, которые вы хотите объединить, в следующей форме (строки, начинающиеся с #, игнорируются):

# this is a comment
file 'file1.mp4'
file '/path/to/file2.mp4'
file 'file3.mp4'

Обратите внимание, что это могут быть относительные или абсолютные пути. Затем вы можете потоковое копирование или перекодировать ваши файлы:

ffmpeg -f concat -safe 0 -i files.txt -c copy output.mp4

0

Мой сценарий, чисто в bashиffmpeg . Перекодирует файлы, заданные в командной строке, в одну.

Требует, чтобы файлы имели одинаковое разрешение. Принимает разные метаданные ротации, что ffmpeg concat:не так.

rm ffmpeg-concat-output.mkv

FILE_COUNT=$#
INPUTS=""
FILTER=""
INDEX=0
for FNAME in $@; do
    echo "Processing ${FNAME}"
    INPUTS="${INPUTS} -i $FNAME"

    if [ -z "${FILTER}" ]; then
        FILTER="[$INDEX:v:0] [$INDEX:a:0]"
    else
        FILTER="${FILTER} [$INDEX:v:0] [$INDEX:a:0]"
    fi
    let INDEX+=1
done

COMMAND="ffmpeg ${INPUTS} \
    -filter_complex '${FILTER} \
        concat=n=${INDEX}:v=1:a=1 [v] [a]' \
    -map '[v]' -map '[a]' \
    ffmpeg-concat-output.mkv"

#   -af 'volume=15dB' # won't work with -filter_complex

bash -c "${COMMAND}"

0

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

Используйте это с:

vcat -i inputfile1,inputfile2[start-end],... -o <outputfile>

-1

В дополнение к ответу Maythux, из :

Несколько мультимедийных контейнеров (MPEG-1, MPEG-2 PS, DV) позволяют объединять видео, просто объединяя файлы, содержащие их.

Т.е. для объединения видео используйте один из вышеупомянутых контейнеров видео (к которому я добавлю MPEG-4 Part 14 для личного опыта), вы можете просто:

cat video1.ext video2.ext video3.ext > video4.ext

1
Я пробовал это, но он возвращает только первое видео в качестве вывода. Я где-то читал, что это не работает, хотя я не помню обоснования этого.
Дхрув Сингал

@DhruvSingal Да, я могу подтвердить это, я пробовал это на двух видео MP4 с точно такой же кодировкой видео / аудио и, как вы, я мог просматривать только первое видео. Это кажется разумным, однако я уверен, что уже делал это раньше с парой видео MP4. Возможно, память здесь не очень хорошо работает, или существуют другие требования, чтобы это работало. Я хочу исследовать это, так как мне также интересно, если я найду что-то, я обновлю ответ и оставлю вам комментарий
kos

Нам как-то нужно изменить метаданные в начале первого видео, чтобы охватить всю длину объединенного фильма, и, возможно, другие вещи. Только несколько файлов mpeg4 позволяют мне увидеть метаданные ..
Кен Моллеруп
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.