En Kdenlive 17 han cambiado la ubicación de algunas funciones en los menús. Y algunas han desaparecido, como la de invertir los clips. Por extrapolación de cómo se hace en otros programas he deducido la solución que os comparto:
Sobre el clip que se desea invertir, botón derecho / Agregar efecto / Moviemiento / Velocidad. Y le damos una velocidad negativa al clip.
Si queremos un vídeo que siga el orden normal y otro que vaya hacia atrás, lo que podemos hacer es sobre el fichero en la carpeta del proyecto: botón derecho / Trabajos del clip / Duplicar el clip con cambio de velocidad. Y le damos una velocidad negativa al clip.
Para girar o rotar una imagen con ImageMagick tenemos el parámetro -rotate que debe ir seguido por los grados de rotación a girar la imagen.
Veamos un ejemplo. Primero, creamos una imagen:
convert -size 250x250 xc:Blue cuadroazul.png
Y una vez que tenemos la imagen, lo podemos rotar:
convert cuadroazul.png -rotate 45 cuadroazul-rotado.png
Al rotar una imagen nos podemos encontrar con dos problemas, pero para ambos problemas hay solución:
que nos podemos encontrar que el color de fondo no nos guste, que se soluciona con -background
que el resultado sea una imagen con un tamaño que nos descuadre el resto de la composición, que se soluciona con -extent
Veamos los dos con ejemplos. Primero, el color de fondo:
convert cuadroazul.png -background Red -rotate 45 cuadroazul-rotado-confondorojo.png
convert cuadroazul.png -background Red -rotate 45 -extent 250x250 cuadroazul-rotado-confondorojo-ajustado.png
convert cuadroazul.png -background Red -rotate 45 -gravity Center -extent 250x250 cuadroazul-rotado-confondorojo-ajustado-centrado.png
convert -size 500x500 xc:GhostWhite -background NavajoWhite -rotate 45 -gravity NorthEast -extent 1000x1000 cuadroblancosobrefondoblanco-imagemagick.png
Uno de los primeros artículos que escribí en Linux Center sobre ImageMagick versaba sobre cómo generar lienzos simples en ImageMagick.
Ahora, después de haber publicado unos cuantos artículos más sobre ImageMagick me parece un buen momento para hacer una recopilación de las distintas formas de hacer un lienzo y cómo aplicarle efectos para poder generar multitud de imágenes distintas como fondo de escritorio, fondos para escribir textos en redes sociales y llamar así más la atención de los destinatarios, imágenes para WhatsAPP / Telegram... y de paso, ver también cómo construir instrucciones complejas en ImageMagick.
Para generar imágenes con ImageMagick el comando a usar es convert, al cual le tenemos que indicar el tamaño de la imagen con -size, el color a usar con xc: y el nombre de la imagen a generar.
La estructura más sencilla para generar una imagen con ImageMagick sería algo así:
convert -size 500x100 xc:Black franjanegra.png
Podríamos combinar en la misma instrucción varias veces el parámetro xc: con atención a que si no añadimos más parámetros, convert generará tantos ficheros como imágenes generadas con xc:
convert -size 500x100 xc:Black xc:Red xc:Blue franjanegra.png
Generará tres ficheros:
franjanegra-0.png
franjanegra-1.png
franjanegra-2.png
Si queremos que esos lienzos formen parte de un único fichero unido verticalmente necesitamos usar el parámetro append. Con -append la unión será vertical y con +append la unión será horzontal.
convert -size 500x100 xc:Black xc:Red xc:Blue -append tresfranjas.png
Como hemos visto hasta aquí, si únicamente utilizamos un -size, todas las piezas medirán lo mismo. Veamos cómo hacer una imagen con piezas de distintos tamaños. Y de paso, veamos cómo concatenar imágenes en formato horizontal (con +append):
convert -size 100x500 xc:Black -size 200x500 xc:Red -size 300x500 xc:Blue +append tresfranjasverticales.png
A los lienzos generados se les puede añadir nuevos parámetros. Por ejemplo -border que añade un borde al lienzo del color indicado con -bordercolor:
convert -size 300x300 xc:Red -bordercolor Black -border 100x100 negroborderojo.png
Los gradientes de color o degradados básicos que se pueden hacer en ImageMagick son lineales o radiales, con los parámetros gradient: y radial-gradient: en lugar de xc:
convert -size 500x500 gradient:Red-Blue degradadorojoazul.png
convert -size 500x500 radial-gradient:Red-Blue degradadoradialrojoazul.png
Una vez visto este recordatorio, aquí empezamos con la elaboración de instrucciones complejas en ImageMagick.
Los degradados lineales realizados con gradient no permiten grandes posibildades de adaptación, pero podemos unir parámetros, como xc: y gradient: para poder hacer imágenes en el que haya partes sin degradados:
convert -size 500x100 xc:Red -size 500x300 gradient:Red-Blue -size 500x100 xc:Blue -append unionxcgradient.png
Vamos a rizar un poco más el rizo y vamos a unir un parámetro más, el parámetro rotate para girar la imagen y que el degradado tenga formato horizontal:
convert -size 500x100 xc:Red -size 500x300 gradient:Red-Blue -size 500x100 xc:Blue -append -rotate 90 unionxcgradientgirado.png
Podemos encadenar distintos gradientes y lienzos lisos, tantos como queramos, aquí uniremos dos degradados con un lienzo liso a modo de ejemplo:
convert -size 500x200 gradient:Red-Blue -size 500x100 xc:Blue -size 500x200 gradient:Blue-Red -append doblegradiente.png
A los lienzos creados, podemos aplicarles un difuminado posterior para que haga el efecto de degradado
convert -size 500x250 xc:Blue xc:Red -append -blur 0x250 difuminadoblur.png
Y aquí viene un punto muy importante que quiero remarcar:
ImageMagick procesa los parámetros de izquierda a derecha, así que para que pueda generarse el difuminado en la unión de los dos lienzos es necesario que el parámetro -append esté antes del parámetro -blur.
A convert se le puede indicar que haga degradados en direcciones concretas. Tanto lineales como radiales. Veamos esta última opción con distintos grados aplicados como valor al parámetro -radial-blur ya que es más sencillo ver el resultado en una imagen que leer su descripción:
convert -size 500x250 xc:Blue xc:Red -append -radial-blur 45 difuminadoradialblur-45.png
convert -size 500x250 xc:Blue xc:Red -append -radial-blur 90 difuminadoradialblur-90.png
convert -size 500x250 xc:Blue xc:Red -append -radial-blur 135 difuminadoradialblur-135.png
convert -size 500x250 xc:Blue xc:Red -append -radial-blur 180 difuminadoradialblur-180.png
convert -size 500x250 xc:Blue xc:Red -append -radial-blur 225 difuminadoradialblur-225.png
convert -size 500x250 xc:Blue xc:Red -append -radial-blur 270 difuminadoradialblur-270.png
convert -size 500x250 xc:Blue xc:Red -append -radial-blur 315 difuminadoradialblur-315.png
convert -size 500x250 xc:Blue xc:Red -append -radial-blur 360 difuminadoradialblur-360.png
Vista la evolución de -radial-blur, veamos lo mismo con -motion-blur, que cuenta con tres parámetros: $radioX$sigma+$ángulo
convert -size 500x250 xc:Blue xc:Red -append -motion-blur 0x100+45 difuminadomotionblur-45.png
convert -size 500x250 xc:Blue xc:Red -append -motion-blur 0x100+90 difuminadomotionblur-90.png
convert -size 500x250 xc:Blue xc:Red -append -motion-blur 0x100+135 difuminadomotionblur-135.png
convert -size 500x250 xc:Blue xc:Red -append -motion-blur 0x100+180 difuminadomotionblur-180.png
convert -size 500x250 xc:Blue xc:Red -append -motion-blur 0x100+225 difuminadomotionblur-225.png
convert -size 500x250 xc:Blue xc:Red -append -motion-blur 0x100+270 difuminadomotionblur-270.png
convert -size 500x250 xc:Blue xc:Red -append -motion-blur 0x100+315 difuminadomotionblur-315.png
convert -size 500x250 xc:Blue xc:Red -append -motion-blur 0x100+360 difuminadomotionblur-360.png
Sobre todo quiero que se note cómo afecta a la imagen un -motion-blur con un ángulo de 180 ó 360 grados en una imagen con dos franjas horizontales. Y ahora veamos cómo afecta el valor del ángulo tanto en -radial-blur como -motion-blur en una imagen con predominancia de un color y una forma que la cruce. Por ejemplo, una cruz de San Jorge:
convert -size 400x400 xc:White -background Red -splice 100x100+200+200 sanjorge.png
Y ahora vamos a hacer una evolución de un -motion-blur y un -radial-blur para ver cómo afecta cuando la imagen muestra una forma de cruz:
Veamos la diferencia entre -motion-blur 90 y -motion-blur 180
Y entre -motion-blur 45 y -motion-blur 135
Y en cuanto a -radial-blur, veamos como afecta con 90 y múltiplos de 90: 180, 270 y 360:
Y sin embargo, cómo afecta cuando no son mútliplos de 90:
-radial-blur 45
-radial-blur 135
-radial-blur 225
-radial-blur 315
Otra forma de modificar las imágenes y hacer menos nítidos los bordes es mediantes las dispersiones con el parámetro -spread:
convert -size 500x250 xc:Red xc:Blue -append -spread 5 rojoazul-spread5.png
[code]convert -size 500x250 xc:Red xc:Blue -append -spread 50 rojoazul-spread50.png[/code]
Incluso se puede aplicar un valor mayor al tamaño en píxeles de la altura de la imagen dando un efecto de caos total:
convet -size 500x250 xc:Red xc:Blue -append -spread 1000 rojoazul-spread1000.png
En una imagen en el que no están definidas las líneas, sí que afecta el -motion-blur con 180 y 360:
[code]convert -size 500x250 xc:Red xc:Blue -append -spread 1000 -motion-blur 0x100+180 rojoazul-spread1000-motion-blur180.png[/code]
convert -size 500x250 xc:Red xc:Blue -append -spread 1000 -motion-blur 0x100+360 rojoazul-spread1000-motion-blur360.png
convert -size 500x250 xc:Red xc:Blue -append -spread 1000 -radial-blur 90 rojoazul-spread1000-radial-blur90.png
convert -size 500x250 xc:Red xc:Blue -append -spread 1000 -radial-blur 360 rojoazul-spread1000-radial-blur360.png
convert -size 500x250 xc:Red xc:Blue -append -radial-blur 360 -spread 1000 rojoazul-radial-blur360-spread1000.png
[code]convert -size 500x250 xc:Red xc:Blue -append -radial-blur 360 rojoazul-radial-blur360-sin-spread.png[/code]
En ImageMagick podemos seleccionar colores de varias maneras, principalmente mediante el nombre predefinido del color o mediante un código hexadecimal.
Ya hemos visto en otros artículos que para trabajar con los colores predefinidos por ImageMagick podemos listarlos con:
convert -list color
Y usar esos colores. Es una forma muy útil y práctica de trabajar, pero esto nos limita a unos cuantos colores, unos setecientos según la versión, podemos saber la cantidad con:
convert -list color | wc -l
Y además no nos permite trabajar con transparencias.
Por lo tanto, el trabajo con código hexadecimal, aunque nos obligue a un pequeño mayor esfuerzo a la hora de programar, nos ofrece una mayor cantidad de colores. Con los nombres de los colores predefinidos tenemos algo menos de 700 colores frente a los 255 * 255 * 255 colores con los que podemos trabajar si usamos códigos hexadecimales. Y si usamos el canal alpha para las transparencias, el número pasa a ser de 255 * 255 * 255 * 255 = 4.228,250.625 colores posibles.
Podemos escribir a mano el código:
convert -size 500x200 xc:#11223344 imagen.png
O podemos generar ese código aleatoriamente.
Para ello nos ayudaremos de shuf para generar un número aleatorio y bc para convertir de decimal a hexadecimal.
Y veamos una función que nos genere aleatoriamente un código hexadecimal de color en nuestros scripts. Pero que, además de dar la posibilidad de generar aleatoriamente un color aleatorio que le podamos indicar que tenga una tonalidad rojiza, verdosa o azulada, o bien que tenga menos coloración de uno de esos canales, que el color sea claro u oscuro y que tenga o no transparencia. Para ello uso una serie de parámetros en la función:
t T -t -T -> Se añade un canal Alfa de transparencia
d D -d -D o O -o -O -> oscuro o dark, el color generado será oscuro, entre 0 y 85 (255 / 3)
l L -l -L c C -c -C -> claro o light, el color será claro, entre 170 ( 255 / 3 * 2 ) y 255
gb GB -gb -GB bg BG -bg -BG -> Mayor cantidad de verde y azul que de rojo
rb RB -rb -RB br BR -br -BR -> Mayor cantidad de rojo y azul que de verde
rg RG -rg -RG gr GR -gr -GR -> Mayor cantidad de rojo y verde que de azul
b B -b -B -> Color azulado
g G -g -G -> Color verdoso
r R -r -R -> Color rojizo
Con esas premisas, aquí dejo la función en un script de ejemplo:
#!/bin/bash
function devuelvecolor()
{
if [ $1 = "r" ] || [ $1 = "R" ] || [ $1 = "-r" ] || [ $1 = "-R" ]
then
let decimalrojo=$(shuf -i 128-255 -n 1)
let decimalverde=$(shuf -i 0-127 -n 1)
let decimalazul=$(shuf -i 0-127 -n 1)
elif [ $1 = "g" ] || [ $1 = "G" ] || [ $1 = "-g" ] || [ $1 = "-G" ]
then
let decimalrojo=$(shuf -i 0-127 -n 1)
let decimalverde=$(shuf -i 128-255 -n 1)
let decimalazul=$(shuf -i 0-127 -n 1)
elif [ $1 = "b" ] || [ $1 = "B" ] || [ $1 = "-b" ] || [ $1 = "-B" ]
then
let decimalrojo=$(shuf -i 0-127 -n 1)
let decimalverde=$(shuf -i 0-127 -n 1)
let decimalazul=$(shuf -i 128-255 -n 1)
elif [ $1 = "rg" ] || [ $1 = "RG" ] || [ $1 = "-rg" ] || [ $1 = "-RG" ] || [ $1 = "gr" ] || [ $1 = "GR" ] || [ $1 = "-gr" ] || [ $1 = "-GR" ]
then
let decimalrojo=$(shuf -i 128-255 -n 1)
let decimalverde=$(shuf -i 128-255 -n 1)
let decimalazul=$(shuf -i 0-127 -n 1)
elif [ $1 = "rb" ] || [ $1 = "RB" ] || [ $1 = "-rb" ] || [ $1 = "-RB" ] || [ $1 = "br" ] || [ $1 = "BR" ] || [ $1 = "-br" ] || [ $1 = "-BR" ]
then
let decimalrojo=$(shuf -i 128-255 -n 1)
let decimalverde=$(shuf -i 0-127 -n 1)
let decimalazul=$(shuf -i 128-255 -n 1)
elif [ $1 = "gb" ] || [ $1 = "GB" ] || [ $1 = "-gb" ] || [ $1 = "-GB" ] || [ $1 = "bg" ] || [ $1 = "BG" ] || [ $1 = "-bg" ] || [ $1 = "-BG" ]
then
let decimalrojo=$(shuf -i 0-127 -n 1)
let decimalverde=$(shuf -i 128-255 -n 1)
let decimalazul=$(shuf -i 128-255 -n 1)
elif [ $1 = "l" ] || [ $1 = "L" ] || [ $1 = "-l" ] || [ $1 = "-L" ] || [ $1 = "c" ] || [ $1 = "C" ] || [ $1 = "-c" ] || [ $1 = "-C" ]
then
let decimalrojo=$(shuf -i 170-255 -n 1)
let decimalverde=$(shuf -i 170-255 -n 1)
let decimalazul=$(shuf -i 170-255 -n 1)
elif [ $1 = "d" ] || [ $1 = "D" ] || [ $1 = "-d" ] || [ $1 = "-D" ] || [ $1 = "o" ] || [ $1 = "O" ] || [ $1 = "-o" ] || [ $1 = "-O" ]
then
let decimalrojo=$(shuf -i 0-85 -n 1)
let decimalverde=$(shuf -i 0-85 -n 1)
let decimalazul=$(shuf -i 0-85 -n 1)
else
let decimalrojo=$(shuf -i 0-255 -n 1)
let decimalverde=$(shuf -i 0-100 -n 1)
let decimalazul=$(shuf -i 0-255 -n 1)
fi
if [ "$2" ]
then
if [ $1 = "t" ] || [ $1 = "T" ] || [ $2 = "t" ] || [ $2 = "T" ] || [ $1 = "-t" ] || [ $1 = "-T" ] || [ $2 = "-t" ] || [ $2 = "-T" ]
then
let decimaltransparencia=$(shuf -i 30-125 -n 1)
hexadecimaltransparencia=$(echo "ibase=10;obase=16;$decimaltransparencia" | bc)
if [ `expr length $hexadecimaltransparencia` -lt 2 ]
then
hexadecimaltransparencia="0"$hexadecimaltransparencia
fi
fi
fi
hexadecimalrojo=$(echo "ibase=10;obase=16;$decimalrojo" | bc)
if [ `expr length $hexadecimalrojo` -lt 2 ]
then
hexadecimalrojo="0"$hexadecimalrojo
fi
hexadecimalverde=$(echo "ibase=10;obase=16;$decimalverde" | bc)
if [ `expr length $hexadecimalverde` -lt 2 ]
then
hexadecimalverde="0"$hexadecimalverde
fi
hexadecimalazul=$(echo "ibase=10;obase=16;$decimalazul" | bc)
if [ `expr length $hexadecimalazul` -lt 2 ]
then
hexadecimalazul="0"$hexadecimalazul
fi
echo "#"$hexadecimalrojo$hexadecimalverde$hexadecimalazul$hexadecimaltransparencia
}
devuelvecolor R t
Hemos hecho un vídeo que no tiene sonido a partir de imágenes generadas con ImageMagick, o a partir de una única imagen, o hemos concatenado vídeos con ffmpeg o... sea como sea, resulta que tenemos un vídeo sin audio.
Y queremos que tenga audio para que sea más agradable su visionado.
Pero hay veces que nos ha salido un vídeo más largo, otras veces más pequeño... generalmente, al montar un vídeo no sabemos antes de empezar la duración exacta de dicho vídeo. Y si lo hemos hecho automáticamente con scripts, menos. Así que queremos vacilar de ser hackers de ImageMagick, deberemos de buscar, de forma automática, una canción que dure exactamente lo mismo que el vídeo.
Y aquí viene de nuevo vinfo.sh a ayudarnos. Y youtube-dl también puede ayudarnos mucho, ya que podemos buscar canciones con licencia creative commons en YouTube y descargarlas en un directorio. Y usarlas justo en el momento que coincida su duración con la duración del vídeo que acabamos de hacer.
¿Vemos cómo?
Aquí está el código, bastante autodescriptivo si has leído los anteriores artículos. Pero con una salvedad: si los nombres de las canciones, o de cualquier otro fichero puede que contenga espacios vacíos, deberemos cambiar el separador de campo.
#!/bin/bash # Script que recibe un vídeo como parámetro # calcula su duración y busca en un directorio # una canción que coincida en duración # y lo anexa. # Para mantener el nombre original el script # creará una copia temporal que luego borrará. # Para poder enlazar la canción y referenciar # al autor, acabará el script escribiendo # el nombre del fichero de la canción. directoriocanciones="instrumentales" # Cambia el separador de campo IFS=' ' # Extrae el nombre del fichero # y la extensión del fichero pasado como parámetro sinextension=${1%.*} extension=${1##*.} # Calcula la duración del audio del fichero pasado como argumento duracion=$(./vinfo.sh duration $1) duracionneta=${duracion:0:8} echo "La duracion del video es "$duracion # Crea el fichero temporal y borra el antiguo nuevofichero=$sinextension"-temp."$extension echo "El nuevo fichero será: "$nuevofichero # Busca una canción en el directorio de canciones # que tenga la misma duración que el vídeo for i in $(ls $directoriocanciones) do duracioncancion=$(./vinfo.sh duration "$directoriocanciones/$i") duracionnetacancion=${duracioncancion:0:8} echo "duracion video: "$duracionneta echo "duracion cancion: "$duracionnetacancion echo "cancion: "$i if [ "$duracionneta" = "$duracionnetacancion" ] then ffmpeg -i $1 -i "$directoriocanciones/$i" -c:v copy -c:a copy $nuevofichero rm $1 mv $nuevofichero $1 rm $nuevofichero echo $i break fi done
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:
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:
La explicación del código está en estos artículos. El resto, en los comentarios del script:
#!/bin/bash
function 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 entradilla
if [ ! -d $directorioentradilla ]
then
mkdir $directorioentradilla
ffmpeg -i $entradilla $directorioentradilla/fotograma%04d.png
else
let contenido=$(ls $directorioentradilla | wc -l)
if [ $contenido -eq 0 ]
then
ffmpeg -i $entradilla $directorioentradilla/fotograma%04d.png
fi
fi
fotogramasentradilla=$(ls $directorioentradilla | wc -l)
echo $fotogramasentradilla
}
# Extrae el nombre del fichero de audio pasado como parámetro quitando la extensión
sinextension=${1%.*}
# Calcula la duración del audio del fichero pasado como argumento
duracion=$(./vinfo.sh duration $1)
# Ficheros auxiliares
entradilla="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ídeo
segundosdeaudio=$(numerodesegundos $duracion)
let totalfotogramas=$segundosdeaudio*24
fotogramasentradilla=$(compruebaentradilla)
# Calcula la duración de la entradilla
duracionentradilla=$(./vinfo.sh duration $entradilla)
segundosentradilla=${duracionentradilla:6:2}
# Calcula cuánto duran los contenidos extras con dos cortes para la cartela de redes sociales
let duracionextras=$segundosentradilla+5+5+20
# Calcula la diferencia entre los segundos de audio del fichero parámetro y los extras
let tiempototalarellenar=$segundosdeaudio-$duracionextras
# Como vamos a hacer dos cortes para la cartela de redes sociales, divide el tiempo entre 3
let tercio=$tiempototalarellenar/3
let 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=1
let fotogramasredessociales=120
let fotogramaspantallafinal=480
# Calcula los finales de los bloques:
let finprimerbloque=$fotogramasentradilla+1+$fotogramastercio
let finsegundobloque=$finprimerbloque+1+$fotogramastercio
let fintercerbloque=$finsegundobloque+1+$fotogramasredessociales
let fincuartobloque=$fintercerbloque+1+$fotogramastercio
let finquintobloque=$fincuartobloque+1+$fotogramasredessociales
let finsextobloque=$finquintobloque+1+$fotogramastercio
let finseptimobloque=$finsextobloque+1+$fotogramaspantallafinal
for 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.mp4
ffmpeg -i pistadevideo.mp4 -i $1 -c:v copy -c:a copy $sinextension.mp4
rm pistadevideo.mp4
Si queremos hacer un vídeo con una imagen fija y un audio, por ejemplo, para subir un podcast a YouTube, una opción sencilla es que lo haga ffmpeg directamente:ffmpeg -loop 1 -y -i imagen.png -i podcast.mp3 -shortest video.mp4
Quizá nos de pereza escribirlo siempre, máxime si para hacer el mp3 del podcast hemos utilizado una cadena larga para el nombre con palabras clave para ser encontrados en el buscador de YouTube y no somos excesivamente aficionados al tabulador o a usar history, podemos hacer un script:
#!/bin/bash
sinextension=${1%.*}
ffmpeg -loop 1 -y -i fondopodcast.png -i $1 -shortest $sinextension.mp4
De esta manera, le pasamos como parámetro el fichero donde tengamos el podcast y crea con el mismo nombre y extensión .mp4 una pista de vídeo y la imagen que usemos habitualmente como fondo para los podcasts.
Pero esto nos permite únicamente trabajar con una imagen. Podríamos intentar con:
ffmpeg -loop 1 -y -i imagen.png -i imagen2.png -i podcast.mp3 -shortest video.mp4
Pero no incluye la segunda imagen. Otra opción es:
ffmpeg -i *.png -i podcast.mp3 video.mp4
Pero tampoco nos hace un vídeo interesante si queremos meter una imagen de 20 segundos como pantalla final para YouTube, alguna entradilla y alguna imagen de fondo variada, por lo que tenemos que elaborar un poco más el script.
Volvemos a usar el vinfo.sh de de Gaspar Fernández que podemos descargar desde su web: https://poesiabinaria.net/2016/02/como-extraer-duracion-fotogramas-bitrate-y-fps-de-un-video-para-nuestros-scripts/
Y con ese script y ffmpeg, hacemos un shell script que automatice la generación de una pista de vídeo con imágenes para poder subir un podcast a YouTube:#!/bin/bash
function numerodesegundos()
{
let horasdeaudio=${1:0:2}
let minutosdeaudio=${1:3:2}
let segundosdeaudio=${1:6:2}
echo $[ ($horasdeaudio*60*60) + ($minutosdeaudio*60) + $segundosdeaudio]
}
sinextension=${1%.*}
duracion=$(./vinfo.sh duration $1)
entradilla="entradilla.mp4"
imagenprincipal="fondopodcast.png"
redessociales="redessociales.png"
pantallafinal="pantallafinal.png"
# Clip con las redes sociales
ffmpeg -loop 1 -f image2 -i $redessociales -vcodec libx264 -t 5 redessociales.ts
# Salida con la pantalla final
ffmpeg -loop 1 -f image2 -i $pantallafinal -vcodec libx264 -t 20 salida.ts
# Calcula la duración de la entradilla
duracionentradilla=$(./vinfo.sh duration $entradilla)
segundosentradilla=${duracionentradilla:6:2}
# Convierte la entradilla en .ts
ffmpeg -i $entradilla entradilla.ts
# Calcula cuánto duran los contenidos extras con dos cortes para la cartela de redes sociales
let duracionextras=$segundosentradilla+5+5+20
# Calcula cuántos segundos dura el audio pasado como parámetro
segundosdeaudio=$(numerodesegundos $duracion)
# Calcula la diferencia entre los segundos de audio del fichero parámetro y los extras
let tiempototalarellenar=$segundosdeaudio-$duracionextras
# Como vamos a hacer dos cortes para la cartela de redes sociales, divide el tiempo entre 3
let tercio=$tiempototalarellenar/3
# Y crea la pieza de vídeo con la imagen principal del podcast con esa duración:
ffmpeg -loop 1 -f image2 -i $imagenprincipal -vcodec libx264 -t 5 imagenprincipal.ts
# Monta una pista de vídeo con las piezas generadas hasta ahora:
ffmpeg -i "concat:entradilla.ts|imagenprincipal.ts|redessociales.ts|imagenprincipal.ts|redessociales.ts|imagenprincipal.ts|salida.ts" -c copy pistadevideo.ts
# Conviértelo en mp4
ffmpeg -i pistadevideo.ts -acodec copy -vcodec copy pistadevideo.mp4
# Monta el vídeo final con la pista de video generada con las imágenes y el podcast
ffmpeg -i pistadevideo.mp4 -i $1 -c:v copy -c:a copy $sinextension.mp4
# Borra todos los ficheros auxiliares generados
rm redessociales.ts
rm entradilla.ts
rm salida.ts
rm imagenprincipal.ts
rm pistadevideo.ts
Pueden comprobar cómo quedan los podcast con estas cartelas en mi canal. Y si les ha servido este tutorial, les gusta el mundo audiovisual y el software libre, o simplemente, si les apete, pueden suscribirse:
Para saber la duración de un vídeo en un script y usar esa información para tabajar con ella, podemos usar ffmpeg, avconf o un script de Gaspar Fernández disponible desde su web: https://poesiabinaria.net/2016/02/como-extraer-duracion-fotogramas-bitrate-y-fps-de-un-video-para-nuestros-scripts/
Y como en el script el autor indica claramente:
# Do whatever you want with this code.
Vamos a darle uso a esa libertad y usarlo para evolucionar su uso:
Almacenar la duración de un vídeo en una variable
Antes de nada, deberemos copiar al directorio de trabajo ese script y darle permisos de ejecución:
chmod + vinfo.sh
Con esto ya podremos invocarlo desde nuestros scripts y recoger la duración de los vídeos en variables:
duracion=$(./vinfo.sh duration $video)
Extraer algunos fotogramas por minuto de una serie de vídeos
Queremos hacer uno o más vídeos a partir de los brutos tomados en un evento, los típicos recursos que se utilizan mucho en las noticias, en los resúmenes de los eventos o para promocionar un evento a partir de los eventos anteriores. Y además, como nos encanta trabajar con ImageMagick queremos extraer fotogramas para luego meterle efectos y hacer más espectaculares esos clips.
Pues aquí tenemos una posible solución:
#!/bin/bash
# Script que recorre un directorio con brutos de vídeo
# Por cada minuto de duración del vídeo extrae de un punto aleatorio
# tres bloques de 200 fotogramas cada uno
# Guardará esos bloques en un nuevo directorio empaquetados en subdirectorios
# cuyo nombre será igual al nombre del bruto donde se ha extraído sin extensión
directoriooriginales="halloween"
directoriodestino="fotogramas-"$directoriooriginales
for i in $(ls $directoriooriginales)
do
# Quita la extensión del nombre del fichero original
# para que el directorio se llame igual
# y tener así una referencia en caso de tener que volver a usar el original
sinextension=${i%.*}
# Calcula la duración del vídeo
duracion=$(./vinfo.sh duration $directoriooriginales/$i)
horas=${duracion:0:2}
minutos=${duracion:3:2}
# Extrae los fotogramas y almacénalos en directorios numerados
# consecutivamente con el mismo nombre que el vídeo origina + numeral
let numeral=1
for min in $(seq 0 $minutos)
do
for tercios in $(seq 1 3)
do
let seg=$(shuf -i 0-59 -n 1)
mkdir $directoriodestino/$sinextension$numeral
ffmpeg -i $directoriooriginales"/"$i -ss 00:$min:$seg -vframes 200 $directoriodestino/$sinextension$numeral/captura%03d.png
let numeral++
done
done
done
Buscar una canción que se ajuste al tamaño de un vídeo para usarla como banda sonora
Recortar una canción para que se ajuste a la duración de un vídeo
Crear una pista de vídeo a partir de una cartela que se ajuste a la duración de un podcast
Ya sabemos cómo seleccionar aleatoriamente una tipografía para incluir texto en ImageMagick, pero nos puede ocurrir que, al ser aleatoria esa selección, nos elija una tipografía que sean dibujos, signos matemáticos o cualquier otra tipografía que no sea de letras, también nos puede mostrar una tipografía con un alfabeto distinto al nuestro o que no muestre bien algunos caracteres.
Yo siempre me fijo en cuatro caracteres clave: apertura de interrogación y exclamación, vocales con tilde y eñes.
Así pues, voy a usar una cadena de caracteres que tenga interrogaciones, una vocal con tilde y una eñe:
¿Leña? ¡Porrón!
Y como quiero ver qué tipografías que tengo instaladas en cada máquina muestran correctamente estos caracteres, hago los siguientes pasos:
#!/bin/bash
directoriotemporaltipografias="tipografias"
if [ ! -d directoriotemporaltipografias ]
then
mkdir $directoriotemporaltipografias
fi
for tipografia in $(convert -list font | grep "Font" | cut -d " " -f 4)
do
convert -pointsize 100 -font $tipografia label:"¿Leña? ¡Porrón!" $directoriotemporaltipografias/$tipografia.jpg
done
Veamos qué es lo que hace:
Indico que es un script en bash:
#!/bin/bash
Que el directorio con el que voy a trabajar se llama "tipografias", pero lo meto en una variable por si por cualquier motivo quiero cambiar de directorio:
directoriotemporaltipografias="tipografias"
Compruebo si existe o no ese directorio y si no existe, lo creo:if [ ! -d directoriotemporaltipografias ]
then
mkdir $directoriotemporaltipografias
fi
Hago un bucle en el que recorre todas las tipografías tal como vimos en el artículo anterior sobre tipografías en ImageMagick: y le digo que me genere una imagen por cada tipografía con la cadena antes indicada de "¿Leña? ¡Porrón!" guardando esas imágenes con el nombre de la tipografía utilizada en el directorio creado para tal efecto:for tipografia in $(convert -list font | grep "Font" | cut -d " " -f 4)
do
convert -pointsize 100 -font $tipografia label:"¿Leña? ¡Porrón!" $directoriotemporaltipografias/$tipografia.jpg
done
Con esto, tengo un directorio lleno de imágenes con cadenas de texto. Abro el directorio con un navegador de ficheros que muestre una previsualización de cada imagen y selecciono todas las imágenes que no me interesan por el motivo que sea, que generalmente es porque no escribe bien todos los caracteres indicados:
Otras veces es porque, aunque muestre correctamente los caracteres, no me parecen lo suficientemente legibles o son muy específicos de una determinada fecha: navideños, de Hallowen, con nieve...
Una vez borrados los que en una primera ronda en bruto me han parecido que no cubren mis necesidades (ojo, que cuando seleccionamos aleatoriamente una tipografía es bastante arriesgado poner a trabajar ese script y desentendernos, por lo que es mejor que, en caso de duda, borrar el fichero), paso a una segunda fase en la que miro una por una las tipografías.
A veces nos encontramos que una tipografía escribe correctamente los caracteres pero no nos queremos arriesgar a que un script la seleccione sin nuestra aprobación:
Estas tipografías muestran todos los caracteres, pero quizá no encajen en todos los contextos, por lo que las borro también.
Y una vez que he borrado todo lo que sobra, ejecuto un segundo script:
#!/bin/bash
directoriotemporaltipografias="tipografias"
for fichero in $(ls $directoriotemporaltipografias)
do
echo ${fichero%.*} >> tipografiasausar.txt
done
rm -r $directoriotemporaltipografias
rmdir $directoriotemporaltipografias
En el que le indico:
Que es un script bash:
#!/bin/bash
Que recoja los ficheros de un determinado directorio:directoriotemporaltipografias="tipografias"
Que recorra ese directorio fichero a fichero y quite la extensión de esos ficheros ${fichero%.*} e incluya el nombre sin extensión en un fichero de texto llamado tipografiasausar.txt añadiendo en cada pasada de for cada tipografía al texto ya existente en ese fichero (>>) for fichero in $(ls $directoriotemporaltipografias)
do
echo ${fichero%.*} >> tipografiasausar.txt
done
Que borre el contenido de ese directorio y el propio directorio para que no ocupe espacio en disco ni moleste una vez hecha la selección. rm -r $directoriotemporaltipografias
rmdir $directoriotemporaltipografias
Una vez creado el fichero tipografiasausar.txt para seleccionar aleatoriamente una línea de ese fichero lo podemos hacer con shuf. Así:
tipografia=$(shuf -n 1 tipografiasausar.txt)
Y así quedaría un script de ejemplo:
#!/bin/bash
tipografia=$(shuf -n 1 tipografiasausar.txt)
convert -pointsize 100 -fill Blue -font $tipografia label:"Automaticen\ny sean felices" automaticen.png
En ImageMagick tenemos el parámetro -list que lista los valores que pueden recibir algunos parámetros.
Uno de los parámetros del que se puede listar los valores que puede recibir es font, que es el parámetro que permite seleccionar la tipografía con la que escribir un texto con annotate o label, así pues, si escribimos:
convert -list font
convert nos mostará las tipografías de nuestro sistema con una serie de datos más, como la familia, la dirección...
Font: Zoidal-BRK
family: Zoidal BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/zoidal.ttf
Font: Zrnic
family: Zrnic
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/larabie/zrnic___.ttf
Font: Zurklez-Outline-BRK
family: Zurklez Outline BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/zurklezo.ttf
Font: Zurklez-Solid-BRK
family: Zurklez Solid BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/zurklezs.ttf
Font: Æ-Systematic-TT-BRK
family: Æ Systematic TT BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/aesymatt.ttf
Font: Ænigma-Scrawl-4-BRK
family: Ænigma Scrawl 4 BRK
style: Normal
stretch: Normal
weight: 400
glyphs: /usr/share/fonts/truetype/aenigma/aescrawl.ttf
Sin embargo, pese a que convert muestra toda esa información el nombre de la tipografía que vamos a usar a la hora de generar un texto con ImageMagick es el que sucede a "Font:". Así pues, si lo que queremos es saber el nombre con el que podremos invocar a las tipografías desde convert para añadir textos en nuestras imágenes o generar imágenes con texto, podremos listar únicamente esas líneas. Y aquí es donde llamamos a nuestro amigo grep:
convert -list font | grep Font
Font: Zakenstein-Rotalic
Font: Zekton
Font: Zekton-Bold
Font: Zekton-Bold-Italic
Font: Zekton-Dots
Font: Zekton-Italic
Font: Zelda-DX-TT-BRK
Font: Zenith-BRK
Font: Zephyrean-BRK
Font: Zephyrean-Gust-BRK
Font: Zero-Threes
Font: Zero-Twos
Font: Zero-Velocity-BRK
Font: ZeroHour
Font: Zirconia-BRK
Font: Zirconia-Cubic-BRK
Font: Zodillinstrisstirust
Font: Zoetrope-BRK
Font: Zoidal-BRK
Font: Zrnic
Font: Zurklez-Outline-BRK
Font: Zurklez-Solid-BRK
Font: Æ-Systematic-TT-BRK
Font: Ænigma-Scrawl-4-BRK
Otra fórmula sería extraer la columna donde están las cadenas de texto que contienen los nombres de las tipografías, el comando cut ayuda mucho en esta tarea:
convert -list font | grep Font | cut -d " " -f 4
Con estos parámetros le decimos a cut, que es un comando que "corta" cadenas, que el separador es un espacio en blanco con -d " ".
Del mismo modo, le podríamos indicar que el separador de columnas es cualqueir otro caracter o cadena de caracteres. El parámetro -f lo que indica es el número de la columna que ha de mostar, en este caso, la cuarta. Veamos:
Zekton
Zekton-Bold
Zekton-Bold-Italic
Zekton-Dots
Zekton-Italic
Zelda-DX-TT-BRK
Zenith-BRK Zephyrean-BRK
Zephyrean-Gust-BRK
Zero-Threes Zero-Twos
Zero-Velocity-BRK
ZeroHour Zirconia-BRK
Zirconia-Cubic-BRK
Zodillinstrisstirust
Zoetrope-BRK
Zoidal-BRK
Zrnic
Zurklez-Outline-BRK
Zurklez-Solid-BRK
Æ-Systematic-TT-BRK
Ænigma-Scrawl-4-BRK
Y ahora que ya tenemos el listado limpio, únicamente tenemos que elegir una cadena al azar. Lo podemos hacer con shuf: convert -list font | grep Font | cut -d " " -f 4 | shuf -n 1
Intersect-O-BRK
Y si lo probamos muchas veces, veremos que el resultado es aleatorio, por lo que cada vez que ejecutemos esa instrucción será distinta:
Y dentro de un script, el uso sería igual:
#!/bin/bash
tipografia=$(convert -list font | grep Font | cut -d " " -f 4 | shuf -n 1)
echo "La tipografía seleccionada de forma aleatoria ha salido: "$tipografia
Veamos si así funciona:
Como vemos, cada vez que ejecutamos el script nos muestra una tipografía distinta.
Y ahora, vamos a usarlo con ImageMagick para generar una imagen con una tipografía aleatoria:
#!/bin/bash
tipografia=$(convert -list font | grep Font | cut -d " " -f 4 | shuf -n 1)
convert -pointsize 100 -font $tipografia label:"Disfruten del\nSoftware Libre" disfruten.png
Y vamos a hacer un for para comprobar que realmente genera imágenes con distintas tipografías:
#!/bin/bash
for i in $(seq 1 3)
do
tipografia=$(convert -list font | grep Font | cut -d " " -f 4 | shuf -n 1)
convert -pointsize 100 -font $tipografia label:"Disfruten del\nSoftware Libre" disfruten$i.png
done
Vista la forma básica de generar textos con tipografías aleatorias, veremos también cómo hacer una selección previa de las tipografías para usar aquellas tipografías que se ajusten a nuestras necesidades.