Concatenare in modo interattivo i file video


9

Come concatenare (unire) più file video MP4 in un file in modo interattivo?

Esistono molti programmi che lo fanno per due file dalla riga di comando. Per esempio:

  • ffmpeg
  • avconv
  • MP4Box

Ma spesso abbiamo bisogno di una soluzione per farlo interattivamente.


1
Puoi descrivere cosa intendi per interattivo?
slm

@slm Intendo un programma che chiede all'utente di inserire i file di input uno per uno, quindi il file di output da creare. e quindi concatenare.
Slyx,

Non ho mai visto un programma che lo fa direttamente, è come hai creato, uno script di shell che raccoglie le informazioni e quindi assembla la riga di comando. Stai cercando miglioramenti rispetto a quello che hai?
slm

@slm l'ho pubblicato perché è un bisogno frequente di utenti multimediali come me. Quindi spero che aiuti qualcun altro. Ovviamente qualsiasi miglioramento è più che benvenuto!
Slyx,

1
@gold Ho messo una modifica in coda. ffmpegè infatti da affatto morti o obsoleti: L'ultima gitimpegnano a masterera 15 minuti fa e lo uso tutti i giorni.
Anko,

Risposte:


8

Non ho provato questo metodo di recente, ma non vedo perché non funzionerebbe ancora. Credo che puoi semplicemente cat .mp4archiviare i file se non vuoi fare altro che concatenarli.

1. Usando il gatto

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

Uso ancora ffmpegtutto il tempo, anche io posso concatenare i file.

2. Utilizzo di ffmpeg

  1. Crea un elenco di file da concatenare

    $ cat inputs.txt 
    file sample_mpeg4.mp4
    file sample_mpeg4.mp4
    
  2. concatenare

    $ 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
    

    Altri metodi sono trattati nel wiki di FFmpeg: Come concatenare (unire, unire) i file multimediali .

    NOTA: Ubuntu non sembra supportare il concatformato. Devi usare il protocollo concat. Inoltre, ha opzioni di codec per flusso. Pertanto, utilizzando il protocollo concat si ottiene come segue:

    $ 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
    

    Le opzioni di Ubuntu ffmpeg sono documentate qui .


Interessante ! Non sapevo che catfosse abbastanza per i file MP4! la soluzione non è interattiva però!
Slyx,

@Slyx - sì, è per questo che ho chiesto cosa intendevi per interattivo. Fammi vedere cosa hai detto a riguardo e vedere cosa posso aggiungere a questo. Controlla che catfunzioni comunque. L'ultima volta che l'ho usato è stato con i .mpgfile ed è def. lavorato con quelli.
slm

2
L'ho verificato. L'uso catnon è una soluzione valida. Il file generato da catdue file mostra solo il contenuto del primo file di input!
Slyx,

@Slyx - cat funziona ma i timestamp non sono corretti, quindi quando tenti di riprodurlo il lettore video viene confuso dal salto nel timestamp da 00 alla fine, quindi torna a 00. Se dovessi transcodificare il video questo verrebbe riparato come parte di quel processo. Ci sono modi per rigenerare anche i timestamp.
slm

Questo è anche quello che intendo. I due contenuti sono presenti ma il lettore multimediale rileva solo il primo.
Slyx,

4

Uso MP4Box come base di lavoro.
Lo script che suggerisco legge tutti i file uno per uno, verificandoli ciascuno (weather è un file normale), chiede all'utente il nome del file di input da creare.

#!/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 !"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.