kiosko de imágenes con feh, ffmpeg, y processing

publicado el 2018-10-07

parte del proyecto: tortilla-stories


como parte del proyecto de tortilla stories, la idea era que mientras la función no hubiera iniciado o ya hubiera acabado, la pantalla de los subtítulos mostrara una secuencia de imágenes con información del evento.

foto de una pantalla en una mesa con mantel cuadriculador, en ella se lee el texto 'come talk to mel, to learn more'. al lado de la pantalla hay tres tornamesas de cartón.

detalle de la mesa en el evento con la pantalla en modo kiosko

como tiendo a complicarme escribí un programa que lo hacía, pero aquí también documento dos otras formas posibles de lograrlo.

feh

feh es un visor de imágenes ligero controlable por comandos de texto.

esta solución apenas se me ocurrió que sería posible, y después de revisar su manual aquí está:

$ feh -FD10 *png

la bandera F hace que las imágenes se muestren en pantalla completa (fullscreen), y la D indica el tiempo que queremos mostrar cada imagen en segundos (delay, en este caso 10 segundos).

el comando mostrará todas las imágenes png en el directorio en donde se ejecute.

ffmpeg

crear un video fue la primera solución que se me ocurrió, pero por cómo estábamos trabajando en la computadora para el escenario (una instalación de gnu/linux específica con los programas para la función), al final se volvió complicado instalar y usar un reproductor de video como vlc.

este comando tiene un resultado similar al anterior, pero aquí con el resultado en un video que habrá que poner en bucle:

$ ffmpeg -r 0.1 -i %d.png -r 30 video.ogv

hay que elegir el framerate de inicio (110 de imágenes por segundo), usar nombres numerados en orden (en este caso irían 1.png, 2.png, etc), y luego elegir el framerate del video de salida (30 imágenes por segundo).

sin el segundo framerate sí hay un video de salida, pero vlc tenía problemas reproduciéndolo debido a que es un número extraño.

processing

un poco por las prisas del momento, y por no abrir la mente a otras soluciones, esta fue la que terminé implementando; un programa en processing.

// kiosko de imágenes en processing
// versión a las prisas 

// número de imágenes
int nimg = 6;
// milisegundos por imagen
int timeImg = 10000;

PImage [] imgs;
int lastTime;
int ptrImg;

void setup(){
  fullScreen();
  imgs = new PImage[nimg];
  for(int i=0; i<nimg; i++){
	imgs[i] = loadImage(String.format("%d.png",i+1));
  }
  // para reducir la carga del programa (?)
  frameRate(10);

  lastTime = millis();
  ptrImg = 0;
}

void draw(){
  // dibuja la imagen actual
  image(imgs[ptrImg],0,0,width,height);

  // si ya pasó el tiempo, cambia de imagen
  if(millis() - lastTime > timeImg){
	ptrImg = (ptrImg+1)%nimg;
	lastTime = millis();
  }

}

el programa funciona creando un arreglo de imágenes (tipo PImage) y luego mostrando una imagen a la vez con una variable apuntadora (ptrImg) que cada cierto tiempo se incrementa o regresa al inicio.

bajé el framerate a 10 imágenes por segundo para reducir un poco la carga del programa, pues la idea era que siguiera corriera en el fondo (en otro “escritorio virtual”) mientras la función sucedía.

ahora que lo veo, probablemente lo pude haber bajado a 0.1 imágenes por segundo y ahorrarme toda la programación de los tiempos. algo así:

// kiosko de imágenes en processing
// versión mejorada (?)

// número de imágenes
int nimg = 6;

PImage [] imgs;
int ptrImg;

void setup(){
  fullScreen();
  imgs = new PImage[nimg];
  for(int i=0; i<nimg; i++){
	imgs[i] = loadImage(String.format("%d.png",i+1));
  }
  frameRate(0.1);

  ptrImg = 0;
}

void draw(){
  // dibuja la imagen actual
  image(imgs[ptrImg],0,0,width,height);

  // cambia de imagen
  ptrImg = (ptrImg+1)%nimg;
}

conclusión: hay muchas maneras de resolverlo con herramientas de software libre; tal vez me compliqué programándolo pero a la vez no fue tanto problema porque fue rápido y sé que podría adaptarlo a otras necesidades :)