Concatenar vídeos con ffmpeg no da siempre los resultados esperados, depende de la versión, de los codecs instalados y varios factores que pueden hacer que el script que en un equipo funciona perfectamente, en otro ordenador no funcione tan bien.
Lo que nunca falla es ImageMagick -sic-. Así pues, voy a comentar un script que funcionaría, o debería funcionar, en todos los sistemas:
El objetivo es el mismo que el del artículo sobre cómo componer vídeos con fotografías y sonido:
Un script que reciba un fichero de audio como parámetro, por ejemplo un podcast, aunque podría ser cualqueir otro fichero de audio, con una duración variable y que se genere un vídeo con unos elementos básicos para un vídeo de YouTube:
- Entradilla
- Una imagen principal que se intercale con una cartela con las redes sociales o cualquier otra imagen, por ejemplo, una llamada a la acción de suscribirse al canal o cualquier otra imagen.
- Pantalla final
La imagen de la llamada a la acción o las redes sociales podría ser también una animación o una secuencia de vídeo. Su adaptación simplemente sería cambiar la imagen fija por un vídeo y copiar la parte de la entradilla. De hecho, si he combinado vídeo con imagen fija ha sido precisamente para que este script pueda ser germen para otras adaptaciones.
Y, de paso, ver en acción el contenido explicado en otros artículos:
- Recorrer un directorio con head y tail
- Saber la duración de un vídeo o audio y usarlo en un shell script
- Componer un vídeo con ffmpeg a partir de fotogramas generados con ImageMagick
- Trabajar con funciones y parámetros en shell script
- Que ImageMagick sirve para multitud de propósitos, no únicamente escalar imágenes o ponerles una marca de agua
La explicación del código está en estos artículos. El resto, en los comentarios del script:
#!/bin/bashfunction numerodesegundos(){ let horasdeaudio=${1:0:2} let minutosdeaudio=${1:3:2} let segundosdeaudio=${1:6:2} echo $[ ($horasdeaudio*60*60) + ($minutosdeaudio*60) + $segundosdeaudio ]}function compruebaentradilla(){# Comprueba si la entradilla tiene su directorio# y están los fotogramas desmontados ahí.## Si no lo está, crea el directorio y# desmonta los fotogramas de la entradillaif [ ! -d $directorioentradilla ]then mkdir $directorioentradilla ffmpeg -i $entradilla $directorioentradilla/fotograma%04d.pngelse let contenido=$(ls $directorioentradilla | wc -l) if [ $contenido -eq 0 ] then ffmpeg -i $entradilla $directorioentradilla/fotograma%04d.png fififotogramasentradilla=$(ls $directorioentradilla | wc -l)echo $fotogramasentradilla}# Extrae el nombre del fichero de audio pasado como parámetro quitando la extensiónsinextension=${1%.*}# Calcula la duración del audio del fichero pasado como argumentoduracion=$(./vinfo.sh duration $1)# Ficheros auxiliaresentradilla="entradilla.mp4"directorioentradilla="entradilla"imagenprincipal="fondopodcast.png"redessociales="redessociales.png"pantallafinal="pantallafinal.png"# Calcula la duración en segundos del audio y el número de fotogramas necesarios para el vídeosegundosdeaudio=$(numerodesegundos $duracion)let totalfotogramas=$segundosdeaudio*24fotogramasentradilla=$(compruebaentradilla)# Calcula la duración de la entradilladuracionentradilla=$(./vinfo.sh duration $entradilla)segundosentradilla=${duracionentradilla:6:2}# Calcula cuánto duran los contenidos extras con dos cortes para la cartela de redes socialeslet duracionextras=$segundosentradilla+5+5+20# Calcula la diferencia entre los segundos de audio del fichero parámetro y los extraslet tiempototalarellenar=$segundosdeaudio-$duracionextras# Como vamos a hacer dos cortes para la cartela de redes sociales, divide el tiempo entre 3let tercio=$tiempototalarellenar/3let fotogramastercio=$tercio*24################################################################################ Los bloques de imágenes quedarán así:# Entradilla -> del fotograma 1 hasta que se acaben los fotogramas de la entradilla# Imagen Principal -> desde último fotograma entradilla + 1 hasta un tercio de los fotogramas restantes más# Cartela Redes Sociales: 5 segundos x 24 fotogramas = 120 fotogramas## Nuevo bloque de: Imagen principal + cartela redes sociales + imagen principal# Este bloque hay que repetirlo a mano, con un while que compruebe los bloques # no funciona el convert imagen.png png:- para pasárselo a ffmpeg# # Pantalla final: 20 segundos x 24 fotogramas = 480 fotogramas###############################################################################contador=1let fotogramasredessociales=120let fotogramaspantallafinal=480# Calcula los finales de los bloques:let finprimerbloque=$fotogramasentradilla+1+$fotogramasterciolet finsegundobloque=$finprimerbloque+1+$fotogramasterciolet fintercerbloque=$finsegundobloque+1+$fotogramasredessocialeslet fincuartobloque=$fintercerbloque+1+$fotogramasterciolet finquintobloque=$fincuartobloque+1+$fotogramasredessocialeslet finsextobloque=$finquintobloque+1+$fotogramasterciolet finseptimobloque=$finsextobloque+1+$fotogramaspantallafinalfor i in $(seq 1 $totalfotogramas)do if [ $contador -le $fotogramasentradilla ] then imagen=$(ls $directorioentradilla | head -n $contador | tail -n 1) let contador++ elif [ $contador -gt $fotogramasentradilla ] && [ $contador -le $finprimerbloque ] then imagen=$imagenprincipal let contador++ elif [ $contador -gt $finprimerbloque ] && [ $contador -le $finsegundobloque ] then imagen=$redessociales let contador++ elif [ $contador -gt $finsegundobloque ] && [ $contador -le $fintercerbloque ] then imagen=$imagenprincipal let contador++ elif [ $contador -gt $fintercerbloque ] && [ $contador -le $fincuartobloque ] then imagen=$redessociales let contador++ elif [ $contador -gt $fincuartobloque ] && [ $contador -le $finquintobloque ] then imagen=$imagenprincipal let contador++ elif [ $contador -gt $finquintobloque ] && [ $contador -le $finsextobloque ] then imagen=$imagenprincipal let contador++ elif [ $contador -gt $finsextobloque ] && [ $contador -le $finseptimobloque ] then imagen=$pantallafinal let contador++ fi convert $imagen png:-done | ffmpeg -f image2pipe -i - pistadevideo.mp4ffmpeg -i pistadevideo.mp4 -i $1 -c:v copy -c:a copy $sinextension.mp4rm pistadevideo.mp4







