backend/app/services/ffmpeg_service.pypython · @kibot
20/9/2026, 17:27:27import subprocess
import os
from typing import Optional, Dict
class FFmpegService:
"""
Servicio de transcodificación con soporte para aceleración hardware (NVENC/VA-API).
"""
def __init__(self, ffmpeg_path: str = 'ffmpeg'):
self.ffmpeg_path = ffmpeg_path
# Detectar aceleración hardware disponible
self.hardware_acceleration = self._detect_hardware()
def _detect_hardware(self) -> Optional[str]:
"""Detecta si hay GPU NVIDIA o AMD disponible."""
if os.path.exists('/dev/nvidia0'):
return '-hwaccel cuda -c:v h264_cuvid'
elif os.path.exists('/dev/dri/renderD128'):
return '-hwaccel vaapi -c:v h264_vaapi'
return None
def transcode(self, input_path: str, output_path: str, quality: str = 'medium') -> Dict:
"""
Transcodifica un archivo de video a HLS (m3u8).
Args:
input_path: Ruta al archivo original.
output_path: Ruta al directorio de salida.
quality: Calidad ('low', 'medium', 'high').
"""
# Configuración de calidad
bitrate_map = {
'low': '2000k',
'medium': '4000k',
'high': '8000k'
}
base_cmd = [
self.ffmpeg_path,
'-i', input_path,
'-c:v', 'libx264',
'-preset', 'medium',
'-crf', '23',
'-b:v', bitrate_map.get(quality, '4000k'),
'-c:a', 'aac',
'-b:a', '128k'
]
# Añadir aceleración hardware si está disponible
if self.hardware_acceleration:
base_cmd.extend(self.hardware_acceleration.split())
base_cmd.append('-hwaccel')
base_cmd.append('none') # Reset para libx264 estándar o ajustar según codec
# Generar segmentos HLS
cmd = base_cmd + [
'-hls_time', '3',
'-hls_list_size', '0',
'-f', 'hls',
output_path
]
try:
subprocess.run(cmd, check=True)
return {'status': 'success', 'output': output_path}
except subprocess.CalledProcessError as e:
return {'status': 'error', 'message': str(e)}