Інтерактивне об'єднання відеофайлів


9

Як інтерактивно об'єднати (об'єднати) декілька відеофайлів MP4 в один файл?

Існує маса програм, які роблять це для двох файлів з командного рядка. Наприклад:

  • ffmpeg
  • avconv
  • MP4Box

Але нам часто потрібно рішення, щоб це зробити інтерактивно.


1
Чи можете ви описати, що ви розумієте під інтерактивом?
slm

@slm Я маю на увазі програму, яка просить користувача ввести вхідні файли по черзі, а потім вихідний файл для створення. а потім зробіть конкатенацію.
Slyx

Я ніколи не бачив програми, яка це робить безпосередньо, це сценарій оболонки, який збирає інформацію, а потім збирає командний рядок. Шукаєте покращення щодо того, що у вас є?
slm

@slm я розмістив це, тому що це часто потребує таких користувачів, як я. Тож сподіваюся, що це допоможе комусь іншому. Звичайно, будь-які поліпшення більш ніж вітаються!
Slyx

1
@gold Я поклав правки в чергу. 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 варіанти описані тут .


Цікаво! Я не знав, що catцього достатньо для файлів MP4! рішення не є інтерактивним!
Slyx

@Slyx - так, тому я запитав, що ти маєш на увазі під інтерактивом. Дозвольте мені побачити, що ви сказали про це, і побачити, що я можу додати до цього. Перевірте, чи catпрацює це. Востаннє я це використовував з .mpgфайлами, і це def. працював з тими.
slm

2
Я це перевірив. Використання catне є дійсним рішенням. Згенерований файл за допомогою catдвох файлів показує лише вміст першого вхідного файлу!
Slyx

@Slyx - кішка працює, але мітки часу невірні, тому при спробі відтворення відеоплеєр заплутається у стрибці часової мітки від 00 до кінця, а потім назад до 00. Якщо ви перекодували це відео, буде закріплено як частина цього процесу. Є також способи відновити часові позначки.
slm

Це я теж маю на увазі. Два вмісту є, але медіаплеєр просто виявляє перший.
Slyx

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 !"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.