Как объединить несколько (более двух) видео в 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

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

Maythux
источник
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.

RawwrBag
источник
Важно отметить, что этот скрипт не будет работать, если любое из имен файлов содержит пробелы или, в некоторых случаях, специальные символы. Для цикла значительно лучше использовать просто 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
ShaDeRzz
источник
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 позволяют мне увидеть метаданные ..
Кен Моллеруп