Cómo eliminar las franjas negras de un vídeo para crear thumbnails consistentes

  • #general

Si necesitas eliminar las franjas negras de un vídeo, te enseñamos cómo eliminarlas automáticamente mediante FFmpeg.

En el mundo del desarrollo web, a veces tenemos que tocar otros temas que no están directamente relacionados con la programación o el diseño web en sí. En este caso vamos a hablar del cropping en FFmpeg y de cómo utilizarlo para eliminar esas molestas franjas negras y poder generar thumbnails (vistas previas) de nuestros vídeos para utilizarlos en nuestros proyectos web, como por ejemplo, un clon de Youtube.

Para empezar, una vista previa de una captura realizada a un vídeo:

Captura de vídeo con franjas negras

Esta captura se habrá realizado automáticamente con una aplicación del lado del servidor tipo FFmpeg. Quizás no deberíamos utilizarla para nuestro proyecto, ya que esas horribles franjas negras no serán consistentes en todos los vídeos y sería caótico. Así pues vamos a utilizar FFmpeg para auto-detectarlas y eliminarlas.

Obteniendo los valores de corte automáticamente

El primer paso es utilizar el filtro de vídeo cropdetect para obtener los valores automáticamente. El parámetro a pasar a FFmpeg es: -vf "cropdetect=24:16:0".

Los parámetros de cropdetect siguen el formato cropdetect=limit:round:reset.

Este parámetro puede contener hasta tres opciones extra. Para nuestro ejemplo no vamos a utilizar ninguno, pero aún asi, una breve explicación:

  • limit: Establece el umbral de intensidad del color negro, que puede ser especificado desde nada (0) hasta todo (255). Por defecto es 24. Esto ayudará cuando nos elimine partes oscuras que no son franjas negras, o viceversa, cuando no esté detectando las franjas porque no son tan negras.

  • round: Asegura que la resolución de salida es divisible por el valor especificado. Por defecto es 16, el mejor valor para la mayoría de los códecs de vídeo.

  • reset: Determina después de cuántos fotogramas cropdetect restablecerá el área de vídeo más grande detectada anteriormente y empezará a contar de nuevo para detectar el área de recorte óptima. Esto es útil cuando hay logotipos de televisión. Por defecto es 0, no hay reset.

Así pues, ejecutamos el siguiente comando y dado que estamos utilizando 2>&1, el resultado se imprimirá en pantalla.

ffmpeg -i fichero.mp4 -vf cropdetect -f null - 2>&1
[Parsed_cropdetect_0 @ 000000000268d400] x1:0 x2:719 y1:74 y2:501 w:720 h:416 x:0 y:80 pts:1814400 t:20.160000 crop=720:416:0:80

[Parsed_cropdetect_0 @ 000000000268d400] x1:0 x2:719 y1:74 y2:501 w:720 h:416 x:0 y:80 pts:1814400 t:20.160000 crop=720:416:0:80

Como podemos ver en el resultado, ya tenemos nuestros valores de corte.

Utilizando los valores de corte

El siguiente paso es utilizar esos valores de la siguiente manera:

ffmpeg -i fichero.mp4 -vf "crop=720:416:0:80"

Los parámetros de crop siguen el formato crop=w:h:x:y. Donde W y H se refieren al tamaño del vídeo resultante (width y height), y X e Y se refieren a las coordenadas donde empezará. Un X e Y de 20 quieren decir que se ignorarán los 20px de la izquierda y los 20px de arriba.

En nuestro caso, horizontalmente no se quita nada puesto que no hay franjas negras horizontales. Verticalmente, nuestro vídeo resultante eliminará 80px en la parte superior mediante el parámetro Y. La parte inferior se calcula de una manera distinta. Nuestro vídeo tiene 576px de altura por lo que después de saltar 80px en la parte superior mediante Y, FFmpeg nos dará un H de 416 (576 - 80 - 80).

Así pues, aquí un pequeño ejemplo de código en PHP para generar thumbnails de un vídeo que tiene franjas negras arriba y abajo:

PHP
$cropDetect = shell_exec('ffmpeg -ss 150 -i fichero.mp4 -vframes 1 -vf cropdetect -f null - 2>&1');
preg_match('/.*crop=([0-9:]+).*/', $cropDetect, $matches);

/*
Esto nos serviría por si queremos hacer algo con los datos de cropdetect
antes de cortar las franjas negras. Por ejemplo, cortar más para mantener una relación de aspecto.

$parts = explode(':', $matches[1]);

$output = array();
$output['width'] = (int) $parts[0];
$output['height'] = (int) $parts[1];
$output['x'] = (int) $parts[2];
$output['y'] = (int) $parts[3];
*/

exec('ffmpeg -ss 150 -i fichero.mp4 -vframes 1 -vf "crop='.$matches[1].'" thumbnail.jpg 2>&1');

Para no recibir una inmensa cantidad de resultados de cropping, hemos utilizado el parámetro -vframes 1, que limita nuestro comando a un solo fotograma. Además, como el primer fotograma es muy probable que sea todo de color negro, saltaremos 150 segundos mediante el parámetro -ss 150. Estos datos dependerán del tipo de vídeos a los que vayamos a hacer cropping, no es lo mismo un anuncio de 40 segundos que una película de 120 minutos.

El resultado, el siguiente:

Captura de vídeo sin franjas negras

Como podéis ver, las barras negras ya no están. Si queremos una consistencia entre los thumbnails en vez de que cada uno tenga un grosor distinto en nuestros thumbnails, este es el paso a seguir.

Por supuesto, esto solo genera fotos al mismo tamaño que el vídeo, si queremos thumbnails tenemos que añadir la parte del redimensionado para hacer las fotos más pequeñas.

Compartir en