TL;DR
Crea una integración REST que convierta una fuente en video en unos 10 minutos y gestiona después el renderizado asíncrono real con el estado del trabajo guardado, consultas de estado seguras y reintentos.
Este tutorial sobre una API de texto a video convierte una URL pública en un trabajo de motion graphics en inglés de 30 segundos y formato 16:9 mediante TapVid. La integración es breve: sube el material, crea un trabajo, consulta su estado y solicita una URL de descarga firmada. El renderizado es asíncrono y no se garantiza que termine en 10 minutos. La prueba controlada tardó mucho más; precisamente por eso, el código de producción que aparece a continuación guarda el ID del trabajo y tolera fallos transitorios de red.
01
Qué significa API de texto a video aquí
"Texto a vídeo" cubre varios productos diferentes. Algunas API convierten un breve prompt en un clip cinematográfico de cinco segundos. Otros animan una imagen, colocan un presentador digital sobre un guión o ensamblan imágenes de archivo. TapVid se encarga de un trabajo diferente: transformar el material fuente propiedad del creador en un vídeo informativo estructurado y de varias escenas. En este tutorial, la entrada no es un prompt visual vago. Es la API pública TapVid y la página MCP más un resumen que define la audiencia, la duración, la relación de aspecto, el mensaje y las afirmaciones prohibidas. El objetivo de salida es un vídeo informativo completo de 30 segundos en lugar de una toma aislada. Para agencias y pequeñas empresas, la edición de escenas basadas en el prompt también significa que se puede regenerar una escena mientras el resto permanece intacta.
La frase "construirlo en 10 minutos" se refiere a la integración de las cuatro operaciones REST, que no prometen un renderizado de 10 minutos. La generación de vídeo es asíncrona. El punto final de creación devuelve `202 Aceptado` inmediatamente, el estado puede permanecer sin cambios durante largos períodos y la preparación de exportación puede continuar después de que se completen los informes de generación. Un cliente veraz separa la latencia de la solicitud de la latencia de generación. Muestra que el trabajo fue aceptado, almacena la identificación, informa del estado actual y se reanuda más tarde. Nunca reemplaza un trabajo activo con un duplicado solo porque una pestaña del navegador o una conexión de red haya desaparecido.
Esta es la salida real de TapVid de 30 segundos hecha desde la API pública y la página MCP con el resumen utilizado en este tutorial. Verificamos el proyecto de cinco escenas completado en TapVid Studio, reproducimos el resultado completo y descargamos este MP4 local. Prueba el flujo de trabajo de fuente a vídeo terminado y la salida descargable. No convierte retroactivamente la encuesta REST interrumpida anteriormente en un punto de referencia REST completado.
02
Conoce el contrato antes del código
La puerta de enlace oficial actual es `https://api.tapvid.ai/api/public/v1`, y cada solicitud utiliza `Authorization: Bearer YOUR_KEY` sobre HTTPS. Cree la clave en TapVid API Keys y expóngalo al código local como `process.env.TAPVID_API_KEY`. No lo codifique en el script que se muestra en un blog, repositorio, paquete frontend, captura de pantalla o aplicación del lado del cliente. El flujo de creación acepta de uno a 30 ID de material, un prompt requerido, título opcional, `16:9` o `9:16`, duraciones de `30s` a `5m` y un idioma opcional. Estos son valores de cable, por lo que la ortografía y la puntuación importan.
- Usa la base REST pública de la API de TapVid `https://api.tapvid.ai/api/public/v1` mediante HTTPS.
- Lee `process.env.TAPVID_API_KEY` en servidor.
- Envía URL o archivo, no ambos.
- Persiste `materialId` y `videoId` tras 202.
- Consulta según `pollAfterSeconds` con timeout reanudable.
| Campo | Límite | Nota |
|---|---|---|
| Archivo | 100 MB | multipart |
| URL | HTTPS, 4.096 caracteres | sin hosts internos |
| Materiales | 30 | guardar IDs |
| Prompt | 12.000 caracteres | fiel a fuente |
| Formato | `16:9` o `9:16` | enum exacto |
| Duración | `30s`, `60s`, `2m`, `3m`, `4m` o `5m` | enum exacto |
03
Paso 1: carga URL o archivo
Empieza con una sola forma de fuente para la API MCP de TapVid. Para una URL, envía JSON con una `url` HTTPS. Para un archivo, envía datos de formulario multipart con un único archivo de hasta 100 MB. Las cadenas URL pueden tener hasta 4,096 caracteres y no pueden apuntar a hosts internos. El ejemplo usa `https://tapvid.ai/api-mcp` porque es público, suficientemente estable para esta prueba y describe el servicio explicado. La respuesta de carga devuelve `materialId`. Trátalo como estado privado de la aplicación. No es un slug legible y no debe aparecer en etiquetas analíticas ni registros públicos.
export TAPVID_API_KEY="replace-with-your-local-secret"
curl -X POST https://api.tapvid.ai/api/public/v1/materials \
-H "Authorization: Bearer ${TAPVID_API_KEY}" \
-H "Content-Type: application/json" \
-d '{ "url": "https://tapvid.ai/api-mcp" }'El ejemplo de cURL establece una variable de entorno solo para que la solicitud sea fácil de seguir. En una máquina compartida o sistema CI, utilice la tienda secreta de la plataforma en lugar de exportar un valor de larga duración a un historial de shell. La respuesta JSON debe contener `materialId` y `type`. Guarde ambos con el registro de trabajo que está a punto de crear. Si la carga falla con `payload_too_large`, cambiar el mensaje de creación no ayudará. Arregla el material. Si la URL es rechazada, verifique HTTPS, longitud, accesibilidad, redirecciones y si se permite obtener la fuente.
04
Paso 2: crea el trabajo asíncrono
Cree el vídeo solo después de que la carga de la fuente tenga éxito. El `userPrompt` requerido puede contener hasta 12.000 caracteres, pero la longitud no es un sustituto de un resumen comprobable. Indique la audiencia, el límite de la fuente, la duración prevista, la relación de aspecto, el lenguaje, la secuencia obligatoria y las afirmaciones prohibidas. El ejemplo solicita 30 segundos y 16:9 explícitamente en lugar de confiar en opciones automáticas. La respuesta llega como HTTP 202 con `videoId`, `status` y `createdAt`. La especificación oficial HTTP Semantics define 202 como aceptado para su procesamiento, no completado. No significa que el vídeo se pueda descargar o aprobar.
curl -X POST https://api.tapvid.ai/api/public/v1/video/create \
-H "Authorization: Bearer ${TAPVID_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"materialIds": ["MATERIAL_ID_FROM_UPLOAD"],
"userPrompt": "Create a concise 30-second English explainer for developers. Stay faithful to the supplied source and do not invent claims.",
"title": "TapVid API developer explainer",
"aspectRatio": "16:9",
"duration": "30s",
"language": "en"
}'

Persista `videoId` antes de la siguiente llamada de red. Esta línea es el cambio de producción más importante identificado por la prueba controlada. Un proceso puede bloquearse después de la creación y antes de su primera respuesta de estado. Si el ID existe solo en la memoria, la aplicación no puede reanudarse y puede crear un segundo trabajo remunerado. Almacene el ID junto a su propio ID de solicitud, ID de material, revisión de solicitud, configuración solicitada y usuario. El punto final de estado espera el parámetro de consulta `video_id`, mientras que la respuesta de creación utiliza `videoId` en mayúsculas. Copie los nombres oficiales actuales de los cables exactamente en lugar de normalizarlos de memoria.
05
Paso 3: persiste, consulta y descarga
Encuesta `GET /video/status` usando el ID aceptado y respeta `pollAfterSeconds`. Los estados del terminal documentados son "completado" y "fallado"; los estados intermedios incluyen "en cola" y "en ejecución". El progreso es una fracción de 0 a 1, no un tiempo estimado restante. Una vez completado, sondee una vez más si `creditsUsed` sigue siendo nulo porque la liquidación puede seguir a la actualización del terminal. A continuación, solicite `GET /video/download` con opciones de resolución, marca de agua y subtítulos. La `downloadUrl` firmada caduca en aproximadamente una hora. Almacene el ID de vídeo duradero, no la URL firmada, y actualice la URL cuando un usuario la necesite de nuevo.
import { writeFile } from 'node:fs/promises'
const apiKey = process.env.TAPVID_API_KEY
if (!apiKey) throw new Error('TAPVID_API_KEY is required')
const base = 'https://api.tapvid.ai/api/public/v1'
const headers = { Authorization: `Bearer ${apiKey}` }
async function request(path, init = {}, { attempts = 1 } = {}) {
let lastError
for (let attempt = 1; attempt <= attempts; attempt += 1) {
try {
const response = await fetch(`${base}${path}`, {
...init,
headers: { ...headers, ...init.headers },
})
const data = await response.json()
if (response.ok) return { response, data }
if (response.status !== 429 && response.status < 500) {
const error = new Error(`HTTP ${response.status}: ${data.code ?? 'unknown'}`)
error.retryable = false
throw error
}
lastError = new Error(`retryable HTTP ${response.status}`)
} catch (error) {
if (error?.retryable === false) throw error
lastError = error
}
if (attempt === attempts) break
await new Promise((resolve) => setTimeout(resolve, attempt * 1000))
}
throw lastError
}
const { data: material } = await request('/materials', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: 'https://tapvid.ai/api-mcp' }),
})
const { response: createResponse, data: video } = await request('/video/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
materialIds: [material.materialId],
userPrompt: 'Create a concise 30-second English explainer for developers. Stay faithful to the source.',
title: 'TapVid API developer explainer',
aspectRatio: '16:9',
duration: '30s',
language: 'en',
}),
})
if (createResponse.status !== 202) throw new Error('Expected 202 Accepted')
// Persist before the next network call. A lost poll must not cause a duplicate create.
await writeFile('.tapvid-job.json', JSON.stringify({ videoId: video.videoId }))
let status
for (let poll = 0; poll < 180; poll += 1) {
const result = await request(
`/video/status?video_id=${encodeURIComponent(video.videoId)}`,
{},
{ attempts: 4 },
)
status = result.data
if (status.status === 'completed' || status.status === 'failed') break
await new Promise((resolve) =>
setTimeout(resolve, Math.max(status.pollAfterSeconds ?? 5, 5) * 1000),
)
}
if (!status) throw new Error('No status received')
if (status.status === 'failed') throw new Error(status.error?.code ?? 'generation_failed')
if (status.status !== 'completed') throw new Error('Polling timeout; resume with the saved videoId')
const query = new URLSearchParams({
video_id: video.videoId,
resolution: '1080P',
watermark: 'true',
subtitle: 'false',
})
const { data: download } = await request(`/video/download?${query}`, {}, { attempts: 4 })
console.log({ status: download.status, expiresAt: download.expiresAt })El ejemplo de Node.js envuelve las lecturas en reintentos limitados y escribe el ID de vídeo aceptado en el disco antes de la encuesta. En un servicio real, reemplace el archivo JSON local con una fila de base de datos y use un trabajador de colas. El ayudante vuelve a intentar errores de red, HTTP 429 y errores del servidor. No vuelve a intentar un 400 o 401 normal como si el tiempo reparara los malos argumentos o credenciales. El techo de 180 encuestas crea una clara condición terminal para el trabajador. Si se alcanza ese límite, el código mantiene la identificación e informa de un tiempo de espera reanudable en lugar de enviar otra solicitud de creación.
06
Qué mostró la prueba REST
La prueba REST del 7 de agosto de 2026 utilizó la misma fuente, prompt, duración de 30 segundos, relación 16:9 e idioma inglés que la prueba MCP. La carga de material devolvió HTTP 200 en aproximadamente 1,4 segundos. Crear HTTP 202 devuelto y puesto en cola en unos 0,3 segundos. El primer estado de funcionamiento apareció a unos 81 segundos. A unos 331 segundos, el trabajo todavía se reportaba funcionando al 50 por ciento. El proceso local de Node luego recibió `ECONNRESET` antes de que se estableciera una conexión TLS. Eso fue un fallo de cliente de votación, no un fallo de trabajo de vídeo documentado.



El primer script de prueba mantuvo el ID de vídeo privado solo en la memoria del proceso, por lo que después de que el proceso salió no pudo reanudar el trabajo aceptado. No se creó un trabajo duplicado. El contador de uso de la cuenta ya había aumentado de 90 a 180 créditos en las ejecuciones de MCP y REST, igualando 90 créditos por creación y el techo total aprobado. Esta es la razón por la que la muestra final persiste el ID antes de la encuesta y da un reintento limitado a las solicitudes GET. También es por eso que este artículo no afirma que la ejecución REST produjo un archivo descargable en 10 minutos. La evidencia apoya la aceptación rápida de la solicitud, no una promesa fija de tiempo de renderizado.
07
Gestiona errores sin duplicar gasto
Manejar errores de acuerdo con lo que significan. `unauthorized` llama a verificar o revocar la clave. `invalid_request` llama a corregir campos. `payload_too_large` llama a reducir materiales. `insufficient_credits` pide detener y obtener autorización antes de cambiar un límite. `rate_limited` llama a honrar `Retry-After`. `internal_error` y las fallas de transporte pueden recibir reintentos limitados. `invalid_state` en descarga generalmente significa que la generación o la exportación no están listas. Una creación duplicada dentro de los cinco segundos puede ser rechazada, pero esa no es una estrategia de idempotencia completa para los bloqueos que ocurren más tarde.
| Condición | ¿Retry? | Acción |
|---|---|---|
| unauthorized | No | Corregir clave |
| invalid_request | No | Corregir body |
| insufficient_credits | No | Detener |
| rate_limited | Sí | Retry-After |
| Red o servidor | Limitado | Reintentar lectura |
| Respuesta create perdida | No recrear | Reanudar por ID |
08
Checklist de producción
Una integración confiable necesita más que un fragmento de camino feliz que funcione. Secretos de la tienda del lado del servidor. Persiste las identificaciones aceptadas atómicamente. Registre las transiciones de estado, la latencia de la solicitud, latencia de generación, créditos y códigos de error seguros. Añade una ventana de encuesta máxima y un estado reanudable. Permiso de carga de origen separado, permiso de generación-gasto, permiso de exportación y permiso de publicación. Actualice las URL firmadas en lugar de almacenarlas como activos permanentes. Pruebe tanto el 429 como los reinicios de red. Mostrar a los usuarios el último estado confirmado. Finalmente, revise el vídeo explicativo generado para la fidelidad de la fuente, la duración real, el orden de la escena, la legibilidad de los subtítulos, el audio, los derechos y la marca antes del lanzamiento externo.
- Clave solo en servidor.
- IDs atómicos.
- Latencias separadas.
- Intervalo y timeout.
- Separar reads y writes.
- Renovar URL firmada.
- Registrar credits sin secretos.
- Persona revisa y publica.
09
API para explainers completos, no clips aleatorios
Utilice esta API de texto a vídeo cuando el trabajo sea convertir el contenido aprobado en un vídeo explicativo coherente con múltiples escenas, narración, movimiento y una salida descargable. No lo describa como un punto de referencia de modelo sin procesar ni prometa el comportamiento visual de un motor cinematográfico de prompt a recorte. Si desea explorar el prompt de forma conversacional, el complemento Claude y TapVid MCP tutorial muestra la misma fuente y resumen a través de MCP. Si desea un control de aplicación duradero, mantenga el flujo REST aquí y revise la descripción general actual de la API y MCP de TapVid antes de enviarla.
10
Preguntas frecuentes
¿Siempre termina en 10 minutos?
No. La integración de cuatro operaciones se puede construir rápidamente, pero la generación y la exportación son asíncronas. La ejecución controlada del MCP tardó unos 28 minutos en completarse, y el sondeador REST perdió su conexión antes del estado del terminal.
¿Qué significa HTTP 202?
Significa que la solicitud de creación fue aceptada para el procesamiento asíncrono. Persiste el videoID devuelto y el estado de la encuesta; no significa que el vídeo esté completo.
¿Cada cuánto consultar?
Utilice el valor pollAfterSeconds devuelto por el estado. Agregue un reintento limitado para fallas transitorias y un tiempo de espera general que puede reanudarse desde el ID de vídeo almacenado.
¿Cuánto dura la URL?
La documentación indica aproximadamente una hora.
¿Puedo quitar watermark?
Está activo por defecto y quitarlo requiere suscripción.




