Интерактивно объединять видеофайлы

9

Как объединить (объединить) несколько видеофайлов MP4 в один файл в интерактивном режиме?

Есть много программ, которые делают это для двух файлов из командной строки. Например:

  • FFmpeg
  • avconv
  • MP4Box

Но нам часто нужно решение, чтобы сделать это в интерактивном режиме.

Slyx
источник
1
Можете ли вы описать, что вы подразумеваете под интерактивом?
SLM
@slm Я имею в виду программу, которая просит пользователя ввести входные файлы один за другим, а затем создать выходной файл. а затем сделать объединение.
Сликс
Я никогда не видел программы, которая делает это напрямую, это как вы создали, сценарий оболочки, который собирает информацию и затем собирает командную строку. Вы ищете улучшения по сравнению с тем, что у вас есть?
SLM
@slm я опубликовал это, потому что это частая необходимость для таких пользователей мультимедиа, как я. Поэтому я надеюсь, что это поможет кому-то еще. Конечно, любые улучшения приветствуются!
Сликс
1
@ золото я положил правку в очередь. ffmpegдействительно ни в коем случае не мертвый и не устаревший: последний gitкоммит masterбыл 15 минут назад, и я использую его ежедневно.
Анко

Ответы:

8

Я недавно не пробовал этот метод, но не понимаю, почему он все еще не работает. Я полагаю, что вы можете просто cat .mp4объединять файлы, если не хотите ничего делать, кроме как объединять их.

1. Использование кошки

$ cat file1.mp4 file2.mp4 > file3.mp4
$ ffmpeg -i file3.mp4 -qscale:v 2 output.avi

Я все еще использую ffmpegвсе время, он тоже может объединять файлы.

2. Использование ffmpeg

  1. Составьте список файлов для объединения

    $ cat inputs.txt 
    file sample_mpeg4.mp4
    file sample_mpeg4.mp4
    
  2. конкатенация

    $ ffmpeg -f concat -i inputs.txt -c copy out.mp4
    
    $ ll |grep -E "sample|out"
    -rw-rw-r--. 1 saml saml 491860 Feb 19 23:36 out.mp4
    -rw-r--r--. 1 saml saml 245779 Feb 19 23:32 sample_mpeg4.mp4

    Другие методы описаны в вики FFmpeg: Как объединить (объединить, объединить) медиа-файлы .

    ПРИМЕЧАНИЕ. Ubuntu не поддерживает этот concatформат. Вы должны использовать протокол concat. Кроме того, он имеет опции кодека для каждого потока. Таким образом, использование протокола concat приводит к следующему:

    $ ffmpeg -i input1.mp4 -vcodec copy -acodec copy \
         -vbsf h264_mp4toannexb -f mpegts intermediate1.ts
    
    $ ffmpeg -i input2.mp4 -vcodec copy -acodec copy \
         -vbsf h264_mp4toannexb -f mpegts intermediate2.ts
    
    $ ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" \
         -vcodec copy -acodec copy -absf aac_adtstoasc output.mp4

    Опции Ubuntu ffmpeg описаны здесь .

SLM
источник
Интересно ! Я не знал, что этого catдостаточно для файлов MP4! решение не является интерактивным, хотя!
Сликс
@Slyx - да, именно поэтому я спросил, что ты имел в виду под интерактивом. Позвольте мне увидеть, что вы сказали об этом, и посмотреть, что я могу добавить к этому. Проверьте, что catработает, хотя. В прошлый раз, когда я использовал это, это было с .mpgфайлами, и это определило. работал с теми.
SLM
2
Я это подтвердил. Использование catне является допустимым решением. Сгенерированный файл с помощью catдвух файлов показывает только содержимое первого входного файла!
Сликс
@Slyx - cat работает, но временные метки неверны, поэтому, когда вы пытаетесь воспроизвести его, видеопроигрыватель смущается скачком временной метки с 00 до конца, а затем обратно на 00. Если вам нужно было перекодировать видео, это будет исправлено как часть этого процесса. Также есть способы восстановить временные метки.
SLM
Это то, что я тоже имею в виду. Два содержимого есть, но медиаплеер просто обнаруживает первый.
Сликс
4

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

#!/bin/bash
printf "###  Concatenate Media files ###\n"
fInputCount=0
# Reading input files
IFS=''
while (true)
do
    let currentNumber=$fInputCount+1 
    printf "File n°%s (\"ok\" to finish): " $currentNumber
    read inputFile
    [ "$inputFile" == "ok" ] && break
    [ ! -e "$inputFile" ] || [ ! -f "$inputFile" ] && printf "\"%s\" : Invalid filename. Skipped !\n" "$inputFile" && continue
    ((fInputCount++))
    inputFileList[$fInputCount]=$inputFile
    printf "\"%s\" : Added to queue !\n" "$inputFile"
done
[ "$fInputCount" == "0" ] || [ "$fInputCount" == "1" ] && echo "No enough input data. BYE ! " && exit
# Listing the input file list 
for ((i=1;i<=$fInputCount;i++))
do
    printf "%2d : %s\n" $i ${inputFileList[$i]}
done
# Reading the output filename
while (true)
do
    printf "Output file without extention (\"none\" to dismiss) : "
    read outputRead
    [ "$outputRead" == "none" ] && echo "Dismissed. BYE ! " && exit
    [ "$outputRead" == "" ] && echo "Try again ! " && continue
    [ -e "$outputRead" ] && echo "\"$outputRead\" exists. Try again !" && continue
    outputFile=$outputRead.mp4
    echo "Output to \"$outputFile\". Go !" && break
done
# Creating a random temporary filename
tmpOutFile="/tmp/concatMedia"`date +"%s%N"| sha1sum | awk '{print $1}'`".mp4"
# Joining the two first input files
MP4Box -cat "${inputFileList[1]}" -cat "${inputFileList[2]}" $tmpOutFile
# Adding all other files
for ((i=3;i<=$fInputCount;i++))
do
    tmpIntermediateFile=$tmpOutFile
    tmpOutFile="/tmp/concatMedia"`date +"%s%N"| sha1sum | awk '{print $1}'`".mp4"
    MP4Box -cat $tmpIntermediateFile -cat "${inputFileList[$i]}" $tmpOutFile
    rm $tmpIntermediateFile
done
mv $tmpOutFile "$outputFile"
# Finished
echo "\"$outputFile\" Saved !"
Slyx
источник