
Upscalar video con Python: pipeline batch y costos
Upscalar videos en lotes con Python: pipeline de 80 líneas, control de tasa, estimaciones desde $0.002/s y reanudación segura en API de video.
Para upscalar video con Python a cualquier volumen real, el problema no es la llamada a la API. Un clip es un POST y un bucle de polling, veinte líneas, listo. El problema es la versión de cien clips: mantenerse bajo el límite de tasa mientras se hace polling, conocer la factura antes de enviar y reanudar un lote que falló en el clip 61 sin pagar de nuevo por los clips 1 a 60.
Esta guía construye ese pipeline contra los puntos finales de mejora de video de reAPI, donde Topaz Video Upscaler corre a $0.044/s de video fuente en el nivel estándar y enhance-video-1.0 comienza en $0.002054/s[1][2]. Todos los números y detalles de contrato a continuación provienen de las páginas en vivo de los modelos en agosto de 2026. Si prefieres la comparación de herramientas en su lugar (código abierto, desktop, API), esa es una guía separada: cómo upscalar video con IA.
TL;DR
- El contrato de API es amigable con lotes por diseño: el envío asincrónico devuelve un id de tarea inmediatamente, la facturación es por segundo de video fuente sondado por el servidor y las tareas fallidas se reembolsan automáticamente, así que un lote fallido nunca cobra doble[1].
- La única restricción dura es 5 solicitudes/segundo por usuario, incluido el polling[1]. Cuatro workers haciendo polling cada 2.5 segundos usa aproximadamente un tercio de ese presupuesto y deja espacio para envíos.
- Estima antes de enviar: 100 clips de un minuto cuestan $264 a través de Topaz estándar, $24.64 a través de enhance-video-1.0 a 1080p estándar[1][2]. La decisión de nivel vale diez veces más que cualquier optimización de código.
- Persiste ids de tarea en disco mientras envías. Reanudar luego no cuesta nada: las tareas completadas ya están pagadas y sus URLs de salida aún se resuelven.
- El pipeline completo es alrededor de 80 líneas, librería estándar más
requests.
Qué el contrato de API da a un trabajo batch
Tres detalles del contrato dan forma al diseño completo, todos de la referencia propia del modelo[1]:
El envío es asincrónico. POST /api/v1/videos/generations devuelve {"id", "status": "processing"} inmediatamente; la renderización ocurre del lado del servidor y haces polling a GET /api/v1/tasks/<id> hasta que status sea completed o failed. Un lote es por lo tanto un conjunto de tareas abiertas que rastrear, no una cola en la que bloquear.
La facturación sigue el clip fuente, no la salida. La plataforma sondea la longitud del video fuente del lado del servidor y factura por segundo: $0.044/s estándar o $0.077/s máximo para upscaling Topaz, $0.002054/s a $0.016429/s para enhance-video nivel estándar dependiendo de la resolución objetivo[1][2]. Eso hace que el costo sea una función pura de la duración del metraje, por eso el estimador de abajo funciona.
Los fallos se reembolsan a sí mismos. Los créditos se reservan al enviar y se reembolsan completamente cuando falla una tarea[1]. El cliente nunca necesita lógica de compensación; solo necesita registrar qué falló y decidir si reenviar.
Estima la factura antes de enviar
La duración es la única entrada que importa. Si los clips son locales antes de cargar, ffprobe lo lee en una llamada; si ya están alojados, toma duraciones de tus propios metadatos.
import subprocess, json
def probe_seconds(path: str) -> float:
out = subprocess.run(
["ffprobe", "-v", "quiet", "-print_format", "json",
"-show_format", path],
capture_output=True, text=True, check=True,
)
return float(json.loads(out.stdout)["format"]["duration"])
RATES = { # $ per second of source, August 2026
"topaz-standard": 0.044,
"topaz-max": 0.077,
"enhance-720p": 0.002054,
"enhance-1080p": 0.004107,
"enhance-4k": 0.016429,
}
def estimate(paths, rate_key):
total = sum(probe_seconds(p) for p in paths)
return total, total * RATES[rate_key]Lo que esa aritmética se ve como para 100 clips de un minuto:
| Nivel | Tasa | 100 × 60 s |
|---|---|---|
| enhance-video-1.0, estándar 720p | $0.002054/s | $12.32[2] |
| enhance-video-1.0, estándar 1080p | $0.004107/s | $24.64[2] |
| enhance-video-1.0, estándar 4K | $0.016429/s | $98.57[2] |
| Topaz Video Upscaler, estándar | $0.044/s | $264.00[1] |
| Topaz Video Upscaler, máximo | $0.077/s | $462.00[1] |
La propagación de 37× entre la fila más barata y la más cara es la superficie de optimización real. Ningún apretón de Python aprieta una factura como elegir el nivel correcto; la lógica de selección es simple de codificar como una regla (fuente limpia subiendo en resolución: nivel enhance; fuente degradada necesitando recuperación de detalle: Topaz).
Upscalar video con Python: pipeline batch de 80 líneas
El diseño: envía todo de una vez (los envíos son baratos y rápidos), persiste el mapa de tareas en disco inmediatamente, luego haz polling con un pequeño pool de workers. El estado vive en un archivo JSON indexado por URL fuente.
import json, pathlib, time
from concurrent.futures import ThreadPoolExecutor
import requests
API = "https://reapi.ai/api/v1"
HEADERS = {"Authorization": "Bearer rk_live_..."}
STATE = pathlib.Path("batch_state.json")
POLL_INTERVAL = 2.5 # 4 workers / 2.5s ≈ 1.6 req/s, well under the 5/s cap
WORKERS = 4
def load_state():
return json.loads(STATE.read_text()) if STATE.exists() else {}
def save_state(state):
STATE.write_text(json.dumps(state, indent=2))
def submit(video_url, state):
if video_url in state: # already submitted on a previous run
return
r = requests.post(f"{API}/videos/generations", headers=HEADERS, json={
"model": "topaz-video-upscaler",
"video_url": video_url,
"upscale_factor": "2",
}, timeout=30)
r.raise_for_status()
state[video_url] = {"task_id": r.json()["id"], "status": "processing"}
save_state(state) # persist before moving on
def poll_one(video_url, entry):
while True:
r = requests.get(f"{API}/tasks/{entry['task_id']}", headers=HEADERS)
body = r.json()
if body["status"] in ("completed", "failed"):
return video_url, body
time.sleep(POLL_INTERVAL)
def run(video_urls):
state = load_state()
for url in video_urls:
submit(url, state)
time.sleep(0.25) # submits: 4/s, inside the budget
open_items = [
(u, e) for u, e in state.items() if e["status"] == "processing"
]
with ThreadPoolExecutor(max_workers=WORKERS) as pool:
for url, body in pool.map(lambda p: poll_one(*p), open_items):
state[url]["status"] = body["status"]
if body["status"] == "completed":
state[url]["output"] = body["output"]
else:
state[url]["error"] = body.get("error")
save_state(state)
done = sum(1 for e in state.values() if e["status"] == "completed")
failed = [u for u, e in state.items() if e["status"] == "failed"]
print(f"{done} completed, {len(failed)} failed")
for u in failed:
print("FAILED:", u, state[u].get("error"))
run([
"https://your-cdn.com/clip-001.mp4",
"https://your-cdn.com/clip-002.mp4",
])Intercambia el payload por enhance-video-1.0 (tool_version, scene, resolution en lugar de upscale_factor) y nada más cambia[2]. Las URLs fuente deben ser públicas HTTPS; los uploads en base64 se rechazan en toda la plataforma.
El presupuesto de límite de tasa, explícitamente
La plataforma limita cada usuario a 5 solicitudes/segundo, y el polling cuenta[1]. El gasto del pipeline:
- Envíos: limitados a 4/s durante la fase de envío, que es corta.
- Polling: 4 workers × una solicitud por 2.5 s = 1.6 req/s estado estacionario.
- Margen: ~3.4 req/s dejados para un segundo script, un dashboard o verificaciones curl manuales.
Aumentar WORKERS a 12 con un intervalo de 2.5 s empujaría solo polling a 4.8 req/s y comenzaría a devolver 429s en el momento en que cualquier otra cosa toque la API. Más workers no terminan renderizaciones más rápido de cualquier manera; el tiempo de renderización es del lado del servidor. Los workers solo limitan cuán rápido notas la finalización y notar 2.5 segundos tarde no cuesta nada.
Manejar fallos sin pagar doble
El contrato de fallo de la plataforma hace el trabajo pesado: una tarea fallida reembolsa sus créditos reservados completamente, automáticamente[1]. El trabajo del pipeline se reduce a contabilidad:
- Registra el fallo, incluyendo el objeto
errorcon sucode,messageerequest_id(la referencia de código de error vive en los docs de API[3]). - No reenvíes ciegamente. Un clip que falló porque la URL fuente devuelve 404 fallará de nuevo al mismo costo de cero, pero una pared de reintentos quema tu presupuesto de tasa. Arregla la entrada, luego reejecutar el script; el archivo de estado salta todo lo ya completado.
- Confía en reanudar. Las entradas completadas conservan sus URLs de salida, que apuntan a archivos rehosted en CDN que no expiran[1], así que un lote interrumpido en el clip 61 se reinicia con 60 resultados pagados intactos y solo el resto pendiente.
FAQ
¿Cómo upscalo video con Python de forma gratuita?
No a través de una API alojada; la renderización cuesta a alguien tiempo de GPU. La ruta gratuita es ejecutar upscalers de código abierto como video2x o Real-ESRGAN en tu propia GPU, lo que intercambia dinero por hardware y configuración, cubierto en nuestra comparación de herramientas. La ruta de API comienza en $0.002054 por segundo fuente[2], y los créditos de registro cubren las primeras llamadas de prueba.
¿Cuántos clips puedo procesar en paralelo?
Envía tantos como quieras; la restricción es tasa de solicitud, no tareas abiertas. Mantén el rendimiento total de solicitudes, envíos más polling, por debajo de 5 por segundo[1]. Cuatro workers de polling a un intervalo de 2.5 segundos es un estado estacionario cómodo.
¿Cuánto cuesta upscalar 100 videos?
La duración decide. A un minuto por clip: de $12.32 (enhance-video, 720p) a $462 (Topaz máximo)[1][2]. Ejecuta el estimador en duraciones reales antes de enviar; son cuatro líneas de ffprobe.
¿Puedo reanudar un lote después de que mi script se bloquea?
Sí, si los ids de tarea fueron persistidos en el momento del envío. Las tareas completadas permanecen completadas y pagadas, sus URLs de salida siguen siendo válidas y las tareas fallidas ya fueron reembolsadas[1]. El patrón de archivo de estado anterior hace de la reanudación el comportamiento predeterminado en lugar de una característica de recuperación.
¿Debería upscalar a 4K en un trabajo batch?
Solo cuando la pantalla de destino lo exige. El nivel 4K cuesta 8× el nivel 720p en enhance-video[2], y los feeds sociales re-comprimen descargas de todos modos. Un patrón común es hacer batch de todo a 1080p y reejecutar el puñado de clips hero a 4K.
¿Cómo sé cuál es la duración de origen que la plataforma facturará?
La plataforma sondea el archivo alojado del lado del servidor y factura su longitud real[1]. ffprobe local en el mismo archivo da el mismo número; las discrepancias significan que la copia alojada difiere de la local, lo que vale la pena atrapar antes de enviar cien de ellas.
Ejecutar el primer lote
Comienza con tres clips, no cien: uno limpio, uno degradado, uno largo. Esa ejecución valida el archivo de estado, muestra costos reales por clip contra la estimación y revela problemas de entrada mientras cuestan centavos. Luego apunta el script a la lista completa y deja que el contrato de reembolso y el archivo de estado absorban lo que salga mal. El punto completo de hacer esto en Python es que para upscalar video con Python una segunda vez, el comando es solo reejecutar el script, y la segunda ejecución solo paga por lo que la primera no terminó.
References
- reAPI. Topaz Video Upscaler — model page: live pricing, task lifecycle, rate limits. Retrieved August 2026 from reapi.ai/models/topaz-video-upscaler
- reAPI. Enhance Video 1.0 — model page: live per-second tier pricing. Retrieved August 2026 from reapi.ai/models/enhance-video-1-0
- reAPI. API error codes reference. Retrieved August 2026 from reapi.ai/docs/api/errors
Further reading
- reAPI. Upscale video with AI: open source, desktop, or API. reapi.ai/blog/upscale-video-with-ai
- reAPI. Topaz Video Upscaler API docs. reapi.ai/docs/topaz-video-upscaler
Autor

Categorías
Más publicaciones

Alternativas Sora 2 API: duración, audio, costo
Comparamos alternativas Sora 2 API en lo que importa: duración máxima de clips, facturación de audio y tarifas reales por segundo, verificado en agosto 2026.


Hailuo H3: especificaciones MiniMax H3, precios y API (2026)
Conoce cómo se relacionan Hailuo H3, MiniMax H3 y Hailuo 03, con especificaciones 2K verificadas, audio nativo, precios, límites API y código de integración.


Cómo usar Claude Opus 4.8: codificación, honestidad y coste
Claude Opus 4.8: tabla de referencia oficial, mejoras de honestidad, Dynamic Workflows y planificación de migración desde Opus 4.7 con cambio de esfuerzo.
