Concatenar interativamente arquivos de vídeo

9

Como concatenar (unir) vários arquivos de vídeo MP4 em um arquivo de maneira interativa?

Existem muitos programas que fazem isso para dois arquivos na linha de comando. Por exemplo:

  • ffmpeg
  • avconv
  • MP4Box

Mas frequentemente precisamos de uma solução para fazer isso de maneira interativa.

Slyx
fonte
1
Você pode descrever o que você quer dizer com interativo?
slm
@slm Refiro-me a um programa que solicita ao usuário que insira os arquivos de entrada um por um, depois o arquivo de saída a ser criado. e faça a concatenação.
Slyx
Eu nunca vi um programa que faça isso diretamente, é como você criou, um shell script que coleta as informações e monta a linha de comando. Você está procurando melhorias sobre o que tem?
slm
@ slm eu postei isso porque é uma necessidade frequente de usuários de multimídia como eu. Então, espero que ajude outra pessoa. É claro que qualquer melhoria é mais que bem-vinda!
Slyx
1
@ gold Coloquei uma edição na fila. ffmpegde fato não está morto ou obsoleto: o último gitcommit masterfoi há 15 minutos e eu o uso diariamente.
Anko

Respostas:

8

Não tentei esse método recentemente, mas não vejo por que ele ainda não funcionaria. Eu acredito que você pode apenas cat .mp4arquivar os arquivos se não quiser fazer outra coisa senão concatená-los.

1. Usando gato

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

Eu ainda uso ffmpego tempo todo, ele também pode concatenar arquivos.

2. Usando ffmpeg

  1. Faça uma lista de arquivos para concatenar

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

    $ 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
    

    Outros métodos são abordados no wiki do FFmpeg: Como concatenar (ingressar, mesclar) arquivos de mídia .

    NOTA: O Ubuntu não parece suportar o concatformato. Você precisa usar o protocolo concat. Além disso, possui opções de codec por stream. Portanto, o uso do protocolo concat resulta da seguinte maneira:

    $ 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
    

    As opções do Ubuntu ffmpeg estão documentadas aqui .

slm
fonte
Interessante! Eu não sabia o catsuficiente para arquivos MP4! a solução não é interativa!
Slyx
@Slyx - sim, é por isso que perguntei o que você quis dizer com interativo. Deixe-me ver o que você disse sobre isso e ver o que posso acrescentar a isso. Verifique se catfunciona embora. A última vez que o usei foi com .mpgarquivos e def. trabalhou com aqueles.
slm
2
Eu verifiquei isso. Usar catnão é uma solução válida. O arquivo gerado por catdois arquivos mostra apenas o conteúdo do primeiro arquivo de entrada!
Slyx
@Slyx - cat funciona, mas os carimbos de data e hora não estão corretos; portanto, quando você tenta reproduzi-lo, o reprodutor de vídeo fica confuso com o salto no carimbo de data e hora de 00 até o final e depois para 00. Se você fosse transcodificar o vídeo, seria corrigido como parte desse processo. Existem maneiras de regenerar os carimbos de hora também.
slm
É isso que eu quero dizer também. Os dois conteúdos estão lá, mas o media player apenas detecta o primeiro.
Slyx
4

Eu uso o MP4Box como base de trabalho.
O script que eu sugiro lê todos os arquivos, um por um, verificando cada um (apesar de ser um arquivo comum), pede ao usuário o nome do arquivo de entrada a ser criado.

#!/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
fonte