dioney57/GestureTV
GestureTV en Gradio
Version del proyecto GestureTV servida como app web con Gradio, en vez del notebook de Colab. Reutiliza la misma logica (maquina de estados, seguimiento de una sola mano, control de pellizco, barra de volumen e icono de reproduccion) descrita en GestureTV_GestureRecognizer_Colab.ipynb.
Ejecutar en local
pip install -r requirements.txt
python app.pyAl abrir el link que imprime (http://127.0.0.1:7860), el navegador va a pedir permiso de camara. La primera vez que arranca descarga el modelo gesture_recognizer.task (~ unos MB) de los servidores de Google; si no hay conexion a internet en ese momento falla con un mensaje claro.
Para conseguir un link publico temporal (por ejemplo, para probarlo desde el celular) sin desplegarlo en ningun lado, cambiar la ultima linea por:
demo.launch(share=True)Publicarlo de forma permanente (Hugging Face Spaces)
- Crear una cuenta en huggingface.co si no se tiene, y crear un nuevo Space de tipo Gradio.
- Subir
app.py,requirements.txtypackages.txta ese Space (por la interfaz web, o congit pushal repo del Space). Elpackages.txtes necesario: sin el, MediaPipe falla al arrancar en la imagen base de los Spaces (ver "Solucion de problemas" mas abajo). - Hugging Face instala las dependencias y corre
app.pyautomaticamente; el modelo se descarga solo la primera vez que arranca. Al terminar, el Space queda con una URL publica estable del tipohttps://huggingface.co/spaces/<usuario>/<nombre-del-space>. - Si el Space tarda en "dormirse" por inactividad (comportamiento normal del plan gratuito), el primer acceso del dia puede demorar unos segundos en levantar de nuevo.
Solucion de problemas
- `OSError: libEGL.so.1: cannot open shared object file` (o `libGLESv2.so.2`) al arrancar en Hugging Face Spaces: la imagen base de los Spaces no trae las librerias graficas de sistema (EGL/GLES) que la libreria compilada de MediaPipe necesita cargar, aunque el modelo se use solo en modo
IMAGEsin GPU. Se soluciona con el archivopackages.txt(incluido en esta carpeta), que le indica al Space que instale esas librerias conapt-getantes de correrapp.py:
libegl1
libgles2 Si despues de subir packages.txt el Space vuelve a fallar por otra libreria .so distinta, es el mismo tipo de problema: buscar a que paquete de Debian/Ubuntu pertenece ese archivo (por ejemplo apt-file search libGL.so.1, o simplemente buscarlo en internet) y agregar ese paquete como una linea mas en packages.txt.
- `runtime error: No @spaces.GPU function detected during startup`: desde hace poco, las cuentas gratuitas de Hugging Face crean los Spaces de Gradio por defecto en hardware ZeroGPU (una GPU compartida/dinamica), y a veces ni siquiera dejan bajarlo a "CPU basic" sin cuenta PRO. ZeroGPU exige que el codigo declare al menos una funcion decorada con
@spaces.GPU, o falla al arrancar con ese mensaje — aunque, como en este proyecto, la app entera corra por CPU (MediaPipe ya usa el delegado XNNPACK de CPU, no hace falta GPU para nada).app.pyya incluye una funcion_zerogpu_probe()decorada con@spaces.GPUque nunca se llama desde el pipeline real: existe unicamente para que ese chequeo de arranque quede conforme, sin que el reconocimiento de gestos deje de correr por CPU. Si tu cuenta si te permite elegir "CPU basic" en Settings → Hardware, tambien podes simplemente cambiar el hardware del Space a eso en vez de depender de este truco.
Sobre la latencia (y por que no usamos WebRTC)
gr.Image(sources=["webcam"], streaming=True) reenvia cada cuadro como un pedido HTTP separado (captura → JPEG/base64 → pedido → respuesta), lo que se siente mas lento que una videollamada real. La alternativa natural es un componente de video en tiempo real basado en WebRTC — se probo el paquete `fastrtc` (sucesor del gradio_webrtc ya deprecado), pero no es viable hoy en un Space gratuito con hardware ZeroGPU: la ultima version de fastrtc (0.0.34) exige gradio<6.0, pero el propio proceso de build de Hugging Face para Spaces ZeroGPU fuerza gradio==6.28.0 (para que coincida con su runtime), sin importar lo que diga requirements.txt. Ese choque de versiones no tiene solucion desde este lado mientras el Space siga en ZeroGPU y fastrtc no publique una version compatible con Gradio 6. Si en el futuro fastrtc lanza una version compatible, o si el Space pasa a hardware "CPU basic" (por ejemplo con una cuenta PRO), vale la pena retomarlo.
Mientras tanto, la optimizacion de latencia que si quedo aplicada es reducir la resolucion antes de inferir: CONFIG["process_max_width"] (480 px por defecto) achica el cuadro antes de correr el GestureRecognizer. Como MediaPipe devuelve landmarks normalizados (0-1), esto no afecta la deteccion de gestos, y en una CPU compartida/gratuita baja bastante el tiempo de inferencia por cuadro — que en la practica pesa mas en la latencia total que el propio transporte HTTP de gr.Image.
Notas de diseno de esta version
- Sin puente JavaScript: el componente de camara de Gradio (
gr.Image(sources=["webcam"], streaming=True)) reemplaza por completo al puente JS/Python a medida del notebook de Colab; entrega cada cuadro ya como un array numpy en RGB. - Estado por sesion:
controller(la maquina de estados) ytracker(el seguimiento de una sola mano) se guardan en ungr.State, que Gradio aisla automaticamente por sesion de navegador. Sin esto, dos personas usando la app al mismo tiempo compartirian el mismo volumen/modo. - Un unico `GestureRecognizer`: el modelo se carga una sola vez al arrancar (cargarlo es lo mas lento) y se comparte entre sesiones protegido por un lock, en vez de crear una instancia nueva por persona.
