Generación de multimedia
POST /api/media/generate — generación asíncrona de imágenes, video, TTS, música y contenido 3D. Parámetros model, prompt, opts. Consulta el estado mediante GET /api/media/jobs/{id}.
Generación asíncrona de contenido multimedia: imágenes, video, voz superpuesta (TTS), conversión de voz a texto, música y 3D. Creas una tarea y consultas el resultado. La lista completa de modelos está en el catálogo de media-models; los webhooks, errores y la facturación están en la sección de webhooks.
Crear parámetros
| Parámetro | Tipo | Descripción |
|---|---|---|
modelreq. | string | El nombre de un modelo multimedia, por ejemplo veo-3.1 o gpt-image-2 (consulta el catálogo). |
promptreq. | string | Descripción de texto. |
opts | object | Opciones de generación adicionales (dependen del modelo): resolución, duración, etc. |
Crear y consultar
La creación devuelve 202 con { ok: true, jobId, status: "processing" }. Consulta GET /api/media/jobs/{jobId} hasta status: "success" y luego toma resultUrls.
# 1. create a generation job
curl https://getvibeapi.com/api/media/generate \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "veo-3.1",
"prompt": "a cat on a skateboard, slow motion"
}'
# → {"ok":true,"jobId":"...","status":"processing"}ok: false y no se cobra nada. Los precios del sitio son indicativos; el cargo exacto se devuelve en el encabezado x-pv-cost-rub de cada respuesta aceptada. Los cuerpos de los streams no cambian de forma predeterminada; envía x-pv-cost: 1 para añadir el costo al evento de uso final de ese protocolo.Parámetros avanzados (opts)
Además de model y prompt, puedes pasar opciones adicionales en opts. El conjunto depende del modelo. El contrato completo legible por máquinas está disponible mediante GET /api/model-capabilities (o GET /api/model-capabilities/{model} para un modelo específico).
| Parámetro | Tipo | Descripción |
|---|---|---|
aspect_ratio | string | Aspect ratio: 1:1, 16:9, 9:16, 4:3, 3:4. |
duration | string|number | Duración del video en segundos (5, 10, 15). |
resolution | string | Resolution: 480p, 720p, 1080p, 4K. |
image_url | cadena (URL) | Imagen de origen para I2V / imagen a imagen. |
negative_prompt | string | Qué excluir de la generación (qwen-image, wan-2-7). |
guidance | number | Escala de orientación: adherencia al prompt (flux-2, qwen-image, seedance). |
seed | number | Seed para obtener un resultado reproducible (flux-2). |
stability | number | Estabilidad 0–1 (hailuo, happyhorse, seedance, TTS). |
camera | string | Movimiento de cámara, por ejemplo, "desplazar a la izquierda" (kling-3.0, hailuo). |
first_frame_url | cadena (URL) | First frame for I2V (kling-3.0, wan-2-7). |
last_frame_url | cadena (URL) | Último fotograma para I2V (seedance, kling-3.0, wan-2-7). |
reference_image | cadena (URL) | Referencia de estilo/personaje (happyhorse). |
similarity_boost | number | Similitud de voz de 0–1 (ElevenLabs TTS). |
speed | number | Velocidad de habla 0.5–2 (ElevenLabs TTS). |
GET /api/model-capabilities/{model}.Tus propios archivos: base64 en lugar de un enlace
Las opciones de URL (image_url, input_urls, mask_url y las demás) son enlaces que el proveedor obtiene, por lo que solo aceptan direcciones https:// públicas. Se rechaza una cadena data:image/...;base64,… insertada directamente en uno de esos campos con 400.
Para enviar tu propio archivo, usa en su lugar el campo *_base64 correspondiente: el servicio almacena los bytes, los publica y pasa el enlace resultante al proveedor. Hasta 16 archivos por solicitud en input_base64.
| Parámetro | Tipo | Descripción |
|---|---|---|
image_base64 | string | Imagen de origen. Reemplaza image_url. |
mask_base64 | string | Máscara de relleno (solo image/*). Reemplaza mask_url. |
input_base64 | string[] | Referencias para imagen a imagen y múltiples entradas. Reemplaza input_urls. |
audio_base64 | string | Audio de origen. Reemplaza audio_url. |
video_base64 | string | Video de origen. Reemplaza video_url. |
data:image/png;base64,…, incluido el prefijo; el tipo de archivo se obtiene de ella.Contrato de solicitud: strict, quote_id, max_price_rub
POST /api/media/generate y POST /api/media/price aceptan el mismo cuerpo, así que puedes calcular el precio y después enviarlo sin cambios. No hay otros campos de nivel superior: cualquier campo desconocido se rechaza en ambos endpoints con 400 y el código unknown_field, que indica su nombre (field, fields), con o sin strict. Los parámetros de generación van dentro de opts.
| Parámetro | Tipo | Descripción |
|---|---|---|
modelreq. | string | Id. de modelo público o una de sus rutas (base:alias). |
prompt | string | Texto; solo es obligatorio cuando la operación del modelo lo requiere. |
opts | object | Opciones del modelo. Esquema exacto: operations[].requestJsonSchema en GET /v1/model-capabilities/{model}. |
strict | boolean | Modo estricto (o el encabezado x-getvibe-strict: 1): una solicitud que no se ejecutaría exactamente como está escrita (un parámetro omitido, un valor limitado al rango permitido, una clave fuera del contrato del modelo) se rechaza con 422 strict_validation_failed y una lista de infracciones, antes de cualquier cotización o cargo. Un campo documentado que el modelo acepta e ignora (duration en modelos cuya duración depende de la fuente) no constituye una infracción: se devuelve como una advertencia param_ignored. |
quote_id | string | mq_… de POST /api/media/price. El trabajo se ejecuta únicamente a ese precio; una cotización obsoleta, usada o redirigida se rechaza con 409/422 antes de que se ejecute nada. |
max_price_rub | number | Límite máximo para este trabajo en la moneda de la cuenta. Si la cotización es superior: 422 media_max_price_exceeded y no se ejecuta nada. A un trabajo medido nunca se le cobra por encima de este límite. |
webhook_url | string | URL https pública que recibe una notificación de finalización firmada. |
Archivos por id (Files API)
Cualquier archivo de origen se puede enviar de tres formas: como un enlace (image_url, audio_url, video_url…), como bytes insertados (image_base64, audio_base64, video_base64…) o como el id de tu propio archivo de POST /v1/files. Los campos de id aparecen en cada requestJsonSchema de operación y se aceptan en modo estricto.
| Parámetro | Tipo | Descripción |
|---|---|---|
image_file_id | string | En lugar de image_url. |
audio_file_id | string | En lugar de audio_url. |
video_file_id | string | En lugar de video_url. |
mask_file_id | string | En lugar de mask_url. |
first_frame_file_id / last_frame_file_id | string | Instead of first_frame_url / last_frame_url. |
input_file_ids | string[] | Se agrega a input_urls. |
reference_*_file_ids | string[] | Appended to reference_image_urls / reference_audio_urls / reference_video_urls. |
El video se cobra según la duración del archivo de entrada
Para los modelos cuya duración de salida sigue la duración de un archivo subido — kling-ai-avatar, omnihuman-v2, omnihuman-2-0, omnihuman-v1.5, omnihuman-1-5, volcengine-lipsync (audio), kling-motion-control, wan-animate, topaz-video-upscale, p-video-edit (video), lipsync-2-pro, sync-3, react-1 (ambas entradas) — /api/media/price y la comprobación previa de max_price_rub en /api/media/generate miden ese archivo en el servidor (enlace, URI data:, base64 o *_file_id) y calculan el precio según los segundos medidos. La respuesta incluye sourceSeconds (outputSeconds para lip-sync), y estimateReason indica que se midió la duración. Si no se puede leer el archivo, el precio conserva su base anterior (un segundo, la estimación del catálogo o el máximo de la ruta) y estimateReason lo indica. El cargo es la tarifa por segundo × los segundos renderizados realmente, sin superar nunca max_price_rub. opts.duration en estos modelos se acepta y se ignora, con una advertencia param_ignored.
Clonación de voz
Create: { name, consent: true, engine, audio_url | audio_base64 } or several recordings samples: [{ audio_url } | { audio_base64 }, …] (engine: "elevenlabs" only). An ElevenLabs voice is used by voice-clone-tts and by the Voice Changer (elevenlabs-voice-changer). Appending recordings to an ElevenLabs voice is free. Every recording is downloaded and measured before the supplier is called: a refusal changes and charges nothing.
| Parámetro | Tipo | Descripción |
|---|---|---|
one recording | ≤ 10 MB | wav/mp3, up to 60 s. Larger: 422 voice_sample_too_large / voice_sample_invalid. |
recordings per voice | ≤ 25 | Se cuentan los que ya se agregaron. Más información: 422 voice_samples_limit. |
voice length | ≤ 300 s | Todas las grabaciones juntas, incluidas las que ya se agregaron. Si son más largas: 422 voice_samples_limit; si son más cortas que el mínimo del motor: 422 voice_samples_invalid. |
recordings size | ≤ 50 MB | Todas las grabaciones de una solicitud juntas. Más información: 422 voice_samples_too_large. |
request body | ≤ 70 953 644 B | 50 MB de grabaciones como base64 (×4/3), más JSON. Más grandes: 413 payload_too_large (JSON, con max_body_bytes). Envía los conjuntos largos por partes mediante …/samples o como enlaces audio_url. |
additions per 24 h | 20 | Por cliente. Más información: 429 voice_samples_rate_limited. |
Cambiador de voz y alineación forzada
| Parámetro | Tipo | Descripción |
|---|---|---|
elevenlabs-voice-changer | model | opts.voice_id (your ElevenLabs voice) + the source recording opts.audio_url | audio_base64 | audio_file_id, up to 5 minutes. Priced on the measured length: 1 minute = 1000 characters. |
forced-alignment | model | prompt is the transcript, opts.audio_url | audio_base64 | audio_file_id the recording. Result: word timings in resultMeta.words and an SRT file in resultUrls. Priced per 1000 characters of text. |
Sandbox: resultado del envío desconocido
Cuando no llega la confirmación de inicio del proveedor, el trabajo permanece con status: "submitting", stage: "submission_unknown", errorCode: "media_submission_uncertain" y failure.advice: "reconcile_first". Sigue consultando el mismo jobId y no crees un duplicado. Para probar esta ruta sin costo, envía POST /api/media/generate con una clave de sandbox y el header x-pv-sandbox-outcome: submission_uncertain. La respuesta es un 202 normal con un jobId; al consultarlo, responde como un envío desconocido durante 60 segundos y después como un trabajo que nunca comenzó (failure.code: "submission_not_started", charged: false). No se almacena, envía a un proveedor ni cobra nada. Una clave normal con este header recibe 400 sandbox_outcome_requires_sandbox_key.
Conversión de voz a texto (transcripción)
El mismo endpoint que el resto de la generación: coloca el nombre del modelo STT en model, deja prompt como una cadena vacía y pasa la grabación en opts.audio_url. La transcripción llega en resultText en GET /api/media/jobs/{id}; resultUrls permanece vacío: la transcripción no produce ningún archivo.
# speech-to-text: create the job, then read the transcript
curl https://getvibeapi.com/api/media/generate \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "whisper-large-v3-turbo",
"prompt": "",
"opts": {
"audio_url": "https://example.com/meeting.mp3",
"language_code": "en"
}
}'
# → {"ok":true,"jobId":"JOB_ID","status":"processing","priceRub":0.03}
curl https://getvibeapi.com/api/media/jobs/JOB_ID \
-H "Authorization: Bearer $GETVIBE_API_KEY"
# → {"status":"success","resultText":"the transcribed text…","resultUrls":[],"priceRub":0.03}Modelos
whisper-large-v3-turbo— $0.00025 por minuto de audio. El más barato y rápido, 99 idiomas.nemotron-asr-multilingual— $0.00025 por minuto. ASR multilingüe de NVIDIA, puntúa automáticamente.whisper-large-v3— $0.000563 por minuto. Whisper completo: más lento que turbo, más preciso con audio ruidoso.universal-2— $0.003125 por minuto.speech-to-text— $0.01 por minuto (ElevenLabs Scribe). Admite diarización de hablantes y etiquetas de eventos de audio.
Parámetros
| Parámetro | Tipo | Descripción |
|---|---|---|
audio_urlreq. | cadena (URL) | Enlace https público que sirve el archivo directamente. Se rechazan las redirecciones y las direcciones de redes privadas. Usa audio_base64 si el archivo no está disponible en línea. |
audio_base64 | string | La grabación integrada como datos:audio/mpeg;base64,… Reemplaza audio_url. |
language_code | string | Código de idioma (en, ru, …). Se detecta automáticamente cuando se omite. |
duration_minutes | number | Duración de la grabación en minutos; se usa para la estimación del precio por adelantado. El cargo final se mide (consulta a continuación). |
diarize | boolean | Diarización de hablantes (universal-2, conversión de voz a texto). |
tag_audio_events | boolean | Etiqueta eventos de audio como risas o aplausos (conversión de voz a texto). |
keyterms | string[] | Lista de sugerencias de términos y nombres (voz a texto; precio +30%). |
Formatos y límites
Se aceptan mp3, wav, m4a/mp4, flac, ogg/opus y webm. El tamaño del archivo es de 25 MB como máximo: aproximadamente 26 minutos de mp3 a 128 kbps o varias horas de voz en opus. Todo lo que supere ese tamaño se rechaza inmediatamente con un mensaje explícito y no se factura; divide la grabación en su lugar.
whisper-large-v3-turbo, whisper-large-v3 y nemotron-asr-multilingual, el importe final se calcula a partir de la duración medida de la grabación, obtenida de la transcripción — no de lo que hayas enviado en duration_minutes. El cargo mínimo es un kopek. El importe exacto siempre se devuelve como priceRub cuando el trabajo finaliza.Webhook de disponibilidad (en lugar de sondeo)
Para evitar las consultas periódicas, registra una dirección mediaWebhookUrl en tu dashboard. Cuando la tarea finaliza (con éxito o error), el servicio realiza hasta cinco intentos de entrega de un POST con un cuerpo JSON:
// POST to your mediaWebhookUrl when a job finishes
{
"jobId": "...",
"status": "success", // or "fail"
"model": "veo-3.1",
"kind": "video", // image | video | audio | music | 3d
"resultUrls": ["https://getvibeapi.com/api/media/file/..."],
"failMsg": null,
"createdAt": "2026-06-17T10:00:00.000Z"
}Obteniendo el archivo: /api/media/file/{id}/{idx}
La URL del resultado de generación (imagen, video, audio o modelo 3D) de resultUrls. Úsala tal como la devuelve el servicio: se abre sin una clave de API y funciona en <img>, <video> o un navegador. El proveedor está oculto: la dirección ascendente se resuelve en el servidor y el cliente nunca la ve.
| Parámetro | Tipo | Descripción |
|---|---|---|
idreq. | cadena (ruta) | ID de tarea (jobId) de la respuesta de /api/media/jobs/{id}. |
idxreq. | integer (ruta) | Índice del resultado (base 0). Para un solo resultado: 0. |
query params | como en resultUrls | No construyas la URL manualmente ni modifiques los parámetros que devuelve el servicio. |
download | cadena (consulta) | download=1 devuelve el archivo como un adjunto cuyo nombre y extensión siguen el contenido (.glb para un modelo 3D). Sin esta opción, el archivo se abre en el navegador. |
# The signed URL is returned in resultUrls of the /api/media/jobs/{id} response
# or in the webhook body. Opens directly in the browser / <img> — no key needed.
https://getvibeapi.com/api/media/file/JOB_ID/0?sig=HMAC_SIGNATUREresultsExpireAt de /api/media/jobs/{id}). El archivo terminado se copia en nuestro almacenamiento y resultUrls cambia a una dirección permanente con el formato https://getvibeapi.com/media/r/…; una URL /api/media/file/… devuelta anteriormente también sigue funcionando. Ambas admiten solicitudes Range (para buscar dentro de videos y audios). Después de 7 días, el archivo se elimina y la URL responde con 410 Gone con el código media_result_expired. Descarga lo que necesites antes de ese momento.