Concatenar interactivamente archivos de video

9

¿Cómo concatenar (unir) múltiples archivos de video MP4 en un solo archivo de manera interactiva?

Hay muchos programas que hacen esto para dos archivos desde la línea de comandos. Por ejemplo:

  • ffmpeg
  • avconv
  • MP4Box

Pero con frecuencia necesitamos una solución para hacer esto de forma interactiva.

Slyx
fuente
1
¿Puedes describir lo que quieres decir con interactivo?
slm
@slm Me refiero a un programa que le pide al usuario que ingrese los archivos de entrada uno por uno, luego el archivo de salida para crear. y luego hacer la concatenación.
Slyx
Nunca he visto un programa que haga esto directamente, es como lo has creado, un script de shell que recopila la información y luego ensambla la línea de comandos. ¿Estás buscando mejoras sobre lo que tienes?
slm
@slm publiqué esto porque es una necesidad frecuente de usuarios multimedia como yo. Así que espero que ayude a alguien más. Por supuesto, cualquier mejora es más que bienvenida.
Slyx
1
@ Oro Puse una edición en la cola. ffmpegde hecho, de ninguna manera está muerto u obsoleto: el último gitcompromiso masterfue hace 15 minutos y lo uso a diario.
Anko

Respuestas:

8

No he probado este método recientemente, pero no veo por qué todavía no funcionaría. Creo que puedes simplemente cat .mp4juntar archivos si no quieres hacer otra cosa que concatenarlos.

1. Usando gato

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

Todavía uso ffmpegtodo el tiempo, también puede concatenar archivos.

2. Usando ffmpeg

  1. Haga una lista de archivos 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
    

    Otros métodos están cubiertos en el wiki de FFmpeg: Cómo concatenar (unir, fusionar) archivos multimedia .

    NOTA: Ubuntu no parece admitir el concatformato. Tienes que usar el protocolo concat. Además, tiene opciones de códec por flujo. Por lo tanto, el uso del protocolo concat resulta de la siguiente manera:

    $ 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
    

    Las opciones de Ubuntu ffmpeg se documentan aquí .

slm
fuente
Interesante! ¡No sabía que eso cates suficiente para archivos MP4! ¡la solución no es interactiva!
Slyx
@Slyx: sí, por eso te pregunté qué querías decir interactivo. Déjame ver lo que dijiste al respecto y ver qué puedo agregar a esto. Comprueba que eso catfunciona. La última vez que lo usé fue con .mpgarchivos y definitivamente. Trabajó con ellos.
slm
2
Lo verifiqué. Usar catno es una solución válida. ¡El archivo generado por catdos archivos solo muestra el contenido del primer archivo de entrada!
Slyx
@Slyx - cat funciona pero las marcas de tiempo no son correctas, por lo que cuando intentas reproducirlo, el reproductor de video se confunde con el salto en la marca de tiempo desde 00 hasta el final, luego de nuevo a 00. Si fueras a transcodificar el video se arreglaría como parte de ese proceso. Hay formas de regenerar las marcas de tiempo también.
slm
A eso me refiero también. Los dos contenidos están ahí, pero el reproductor multimedia solo detecta el primero.
Slyx
4

Yo uso MP4Box como base de trabajo.
El script que sugiero lee todos los archivos uno por uno, verificando cada uno (si es un archivo ordinario), le pide al usuario el nombre de archivo de entrada para crear.

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