promptstringObbligatorioDi’ cosa prendere da ciascun riferimento. Scrivi video 1, video 2 per i video di riferimento e audio 1, audio 2 per le clip audio, numerati nell’ordine di caricamento.
- Predefinito
- Non specificato
- Vincoli
- minLength:1
pruna-ai/p-video-2-pro/reference-to-videoIl reference-to-video di P-Video 2 Pro crea una clip da 5 a 15 secondi a 480p o 768p da fino a 3 video di riferimento e 3 clip audio, citati nel prompt come video 1 e audio 1, più un fotogramma iniziale e finale facoltativi. Nessun filtro sui contenuti.
Gli esempi usano le definizioni pubbliche dei parametri dell’endpoint selezionato. Sostituisci la chiave API e i media di esempio, poi invia la richiesta dal tuo server.
SDK e integrazionihttps://api.spicyapi.ai/api/v1/jobs/createTaskTieni la chiave API nella variabile d’ambiente del server SPICY_API_KEY. Per le richieste JSON usa l’autenticazione Bearer e Content-Type: application/json.
Authorization: Bearer $SPICY_API_KEY# Generate the idempotency key once; reuse it when retrying after a lost response.
export SPICY_IDEMPOTENCY_KEY="${SPICY_IDEMPOTENCY_KEY:-$(uuidgen)}"
curl -X POST https://api.spicyapi.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
-d '{
"model": "pruna-ai/p-video-2-pro/reference-to-video",
"input": {
"aspect_ratio": "auto",
"duration_seconds": 5,
"generation_mode": "speed",
"prompt": "A slow aerial shot drifting over a misty pine forest at sunrise",
"prompt_optimization_mode": "off",
"resolution": "768p"
}
}'
# Copy data.taskId from the response into TASK_ID, then poll the status.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.spicyapi.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
-H "Authorization: Bearer $SPICY_API_KEY"Generato dallo schema di input di questo modello, lo stesso su cui l’API valida ogni richiesta.
Metti questi campi dentro l’oggetto input del corpo della richiesta. Nomi e tipi corrispondono all’API. Quando un valore predefinito non è indicato, non darlo per scontato.
promptstringObbligatorioDi’ cosa prendere da ciascun riferimento. Scrivi video 1, video 2 per i video di riferimento e audio 1, audio 2 per le clip audio, numerati nell’ordine di caricamento.
seedintegerFacoltativoMantiene confrontabili le prove mentre cambi il prompt. Non garantisce una clip identica fotogramma per fotogramma.
prompt_optimization_modestringFacoltativooff (default) invia il prompt parola per parola; turbo e max lasciano al servizio di riscriverlo prima. Non cambia il prezzo.
"off""turbo""max"duration_secondsintegerFacoltativoIncide sul prezzoSecondi interi, da 5 a 15 (default 5). Determina il prezzo.
keep_reference_audiobooleanFacoltativoDisattivato di default. Attivo usa la tua clip audio come colonna sonora invece di generare un suono nuovo; richiede esattamente una clip audio.
generation_modestringFacoltativoIncide sul prezzocost (più economica, un po’ più lenta) o speed (default, più veloce a parità di qualità).
"cost""speed"resolutionstringFacoltativoIncide sul prezzo480p o 768p (default 768p). 768p costa di più al secondo.
"480p""768p"aspect_ratiostringFacoltativoauto (default) si adatta ai riferimenti; oppure scegli 16:9, 9:16, 4:3, 3:4, 3:2, 2:3 o 1:1. Non cambia il prezzo.
"auto""16:9""9:16""4:3""3:4""3:2""2:3""1:1"reference_audio_urlsarray<string>FacoltativoIncide sul prezzoFino a 3 clip audio, 15 secondi in totale, per una voce, un dialogo o una musica. Richiede anche un fotogramma iniziale o un video di riferimento. Aggiunge una tariffa fissa.
reference_video_urlsarray<string>FacoltativoIncide sul prezzoFino a 3 video, di 2 secondi o più ciascuno e 15 secondi in totale, per movimento, inquadratura e ritmo. I loro secondi vengono addebitati, più un secondo per l’arrotondamento.
last_image_urlstringFacoltativoIncide sul prezzoFotogramma finale facoltativo su cui termina la clip. Aggiunge un piccolo costo.
image_urlstringFacoltativoIncide sul prezzoFotogramma iniziale facoltativo: chi e dove inizia l’inquadratura. Aggiunge un piccolo costo.
{
"additionalProperties": false,
"properties": {
"aspect_ratio": {
"default": "auto",
"description": "Output aspect ratio; auto adapts to the references.",
"enum": [
"auto",
"16:9",
"9:16",
"4:3",
"3:4",
"3:2",
"2:3",
"1:1"
],
"type": "string",
"x-ui": {
"order": 80,
"widget": "select"
}
},
"duration_seconds": {
"default": 5,
"description": "Output length in whole seconds, from 5 to 15. Billed per second.",
"maximum": 15,
"minimum": 5,
"type": "integer",
"x-ui": {
"affects_price": true,
"order": 60,
"step": 1,
"unit": "s",
"widget": "slider"
}
},
"generation_mode": {
"default": "speed",
"description": "cost is cheaper and slower, speed (the default) is faster at the same quality.",
"enum": [
"cost",
"speed"
],
"type": "string",
"x-ui": {
"affects_price": true,
"order": 65,
"widget": "radio"
}
},
"image_url": {
"contentMediaType": [
"image/jpeg",
"image/png",
"image/webp",
"image/gif"
],
"description": "Optional opening frame. Adds a small per-image charge.",
"format": "uri",
"type": "string",
"x-ui": {
"affects_price": true,
"order": 92,
"widget": "upload"
}
},
"keep_reference_audio": {
"default": false,
"description": "Use the reference audio as the soundtrack instead of generating new sound. Needs exactly one audio clip.",
"type": "boolean",
"x-ui": {
"order": 63,
"widget": "switch"
}
},
"last_image_url": {
"contentMediaType": [
"image/jpeg",
"image/png",
"image/webp",
"image/gif"
],
"description": "Optional closing frame. Adds a small per-image charge.",
"format": "uri",
"type": "string",
"x-ui": {
"affects_price": true,
"order": 91,
"widget": "upload"
}
},
"prompt": {
"description": "Say what the shot should take from each reference. Refer to reference videos as video 1, video 2 and to audio clips as audio 1, audio 2, numbered in upload order.",
"minLength": 1,
"type": "string",
"x-ui": {
"order": 100,
"primary": true,
"reference_tokens": {
"reference_audio_urls": "audio {index}",
"reference_video_urls": "video {index}"
},
"widget": "textarea"
}
},
"prompt_optimization_mode": {
"default": "off",
"description": "Let the service rewrite and expand the prompt first: off follows it word for word, turbo is a quick rewrite, max a fuller one. Does not change the price.",
"enum": [
"off",
"turbo",
"max"
],
"type": "string",
"x-ui": {
"advanced": true,
"affects_price": false,
"order": 30,
"widget": "radio"
}
},
"reference_audio_urls": {
"description": "Reference audio for a voice, dialogue or music: up to 3 clips, 15 seconds in total. Needs an opening frame or a reference video as well. Refer to them as audio 1, audio 2.",
"items": {
"contentMediaType": [
"audio/mpeg",
"audio/wav"
],
"format": "uri",
"type": "string"
},
"maxItems": 3,
"minItems": 1,
"type": "array",
"x-ui": {
"accept": [
"audio/mpeg",
"audio/wav"
],
"affects_price": true,
"max_total_duration_seconds": 15,
"order": 88,
"widget": "multi-upload"
}
},
"reference_video_urls": {
"description": "Reference videos for motion, camera and pacing: up to 3, 2 seconds or longer each and 15 seconds in total. Refer to them as video 1, video 2. Their seconds are billed too.",
"items": {
"contentMediaType": [
"video/mp4",
"video/webm",
"video/quicktime"
],
"format": "uri",
"type": "string"
},
"maxItems": 3,
"minItems": 1,
"type": "array",
"x-ui": {
"accept": [
"video/mp4",
"video/webm"
],
"affects_price": true,
"max_total_duration_seconds": 15,
"order": 90,
"widget": "multi-upload"
}
},
"resolution": {
"default": "768p",
"description": "Output resolution. 768p costs more per second than 480p.",
"enum": [
"480p",
"768p"
],
"type": "string",
"x-ui": {
"affects_price": true,
"order": 70,
"widget": "radio"
}
},
"seed": {
"description": "Random seed for controlled comparisons, not a frame-identical guarantee.",
"maximum": 2147483647,
"minimum": 0,
"type": "integer",
"x-ui": {
"order": 10,
"widget": "number"
}
}
},
"required": [
"prompt"
],
"type": "object",
"x-pricing": {
"billingMode": "formula",
"variantFields": [
"generation_mode",
"resolution"
]
}
}HTTP 202 significa che l’attività è stata accettata, non che sia finita. Salva il taskId restituito e interroga quell’attività. Non crearne un’altra mentre aspetti il risultato.
HTTP/1.1 202 Accepted
Location: /api/v1/jobs/recordInfo?taskId=job_01k3m8x9q2z4v7n5p6r8s0t1w3
{
"code": 200,
"msg": "success",
"request_id": "req_example_create",
"data": {
"taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
"state": "queued",
"estimatedCost": "0.750000"
}
}La risposta di accettazione include la stima, così la tua applicazione può mostrare lo stesso importo nella cronologia delle attività e nella fatturazione.
curl --get "https://api.spicyapi.ai/api/v1/jobs/recordInfo" \
--data-urlencode "taskId=$TASK_ID" \
-H "Authorization: Bearer $SPICY_API_KEY"Comincia a interrogare ogni 2 secondi circa e allunga l’intervallo man mano. Fermati a uno stato terminale. Dopo una caduta di connessione, interroga il taskId originale. Ripeti la creazione solo con la chiave di idempotenza e il corpo originali.
import { verifyWebhook } from "@spicyapi/sdk";
// express.raw keeps the bytes we signed; express.json never matches.
app.post("/hooks/spicy", express.raw({ type: "application/json" }), (req, res) => {
const { payload } = verifyWebhook({
rawBody: req.body,
timestamp: req.header("X-Webhook-Timestamp"),
signature: req.header("X-Webhook-Signature"),
payloadVersion: Number(req.header("X-Webhook-Payload-Version")),
secret: process.env.SPICY_WEBHOOK_SECRET,
});
res.status(200).end();
void handleFinishedTask(payload);
});Passa callBackUrl quando crei l’attività e il record finito ti arriva via POST: nessun ciclo di polling. Ogni consegna porta X-Webhook-Timestamp, X-Webhook-Signature e X-Webhook-Payload-Version. La firma è un HMAC-SHA256 in base64 su taskId.timestamp.sha256(body), quindi va verificata sui byte grezzi: se analizzi il JSON e lo riserializzi i byte cambiano e la verifica fallisce. Le consegne fallite vengono ritentate, quindi lo stesso taskId può arrivare due volte: rendi idempotente il gestore. Rispondi prima con un 2xx e fai il lavoro dopo; un gestore lento viene trattato come una consegna fallita.
Usa l’output solo quando lo stato è succeeded. In caso di fallimento, indaga con errorCode, errorMessage e request_id. Costi e stati degli esempi non rappresentano un addebito reale.
{
"code": 200,
"msg": "success",
"request_id": "req_example_record",
"data": {
"taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
"model": "pruna-ai/p-video-2-pro/reference-to-video",
"state": "succeeded",
"output": {
"assets": [
{
"key": "tasks/2026/08/28/job_01k3m8x9q2z4v7n5p6r8s0t1w3/3f7a1c9e5b2d48f0a6c1e3d5b7f9a1c3.mp4",
"mime": "video/mp4",
"url": "https://example.r2.cloudflarestorage.com/results/job_01k3m8x9q2z4v7n5p6r8s0t1w3/result.mp4?X-Amz-Signature=SIGNATURE_FROM_RESPONSE",
"expiresAt": "2026-08-28T12:20:08.000Z"
}
]
},
"cost": "0.750000",
"settled": true,
"createdAt": "2026-08-28T12:00:00Z",
"completedAt": "2026-08-28T12:00:30Z"
}
}Per ogni asset disponibile, apri o scarica assets[].url direttamente, senza l’header Authorization dell’API. L’URL firmato scade a expiresAt; interroga di nuovo l’attività per rinnovarlo finché l’asset resta entro il periodo di conservazione. Un asset in attesa o non disponibile non ha URL. Tratta gli URL firmati come privati.
Usa SpicyAPI nella tua app, nel terminale, con un assistente IA o in un workflow visivo. Scegli una guida di configurazione.
Altre integrazioni
Non sei obbligato a scrivere niente del codice qui sopra. Collega una volta il server MCP e qualsiasi agente che parla MCP – Claude Code, Codex, Cursor, Windsurf, VS Code, Gemini CLI, Cline, LibreChat – può eseguire questo modello chiamandolo per nome, oppure lo esegui dalla shell con un solo comando.
Usa pruna-ai/p-video-2-pro/reference-to-video per fare un’inquadratura di cinque secondi di un tetto al neon all’imbrunire, con carrellata lenta in avanti, e salvala in ./out/.
L’agente cerca il modello nel catalogo in tempo reale, carica per te il file locale, poi mostra il preventivo esatto con l’addebito massimo e aspetta la tua conferma. Niente viene addebitato finché non dici di sì.
claude mcp add spicyapi -e SPICY_API_KEY=$SPICY_API_KEY \
-- npx --yes --package=@spicyapi/mcp spicyapi-mcp
npx skills add spicyapi-ai/spicy-skillLa prima riga dà gli strumenti all’agente; la seconda gli dà la Skill, cioè le regole con cui usarli: preventivare prima di addebitare, caricare i file locali invece di incollarne i byte, leggere l’URL dell’asset finito invece di indovinarlo. Tutti gli altri client prendono lo stesso server dal proprio file di configurazione: vedi l’area sviluppatori.
npx @spicyapi/cli tasks create --model pruna-ai/p-video-2-pro/reference-to-video \
--input-json '{"aspect_ratio":"auto","duration_seconds":5,"generation_mode":"speed","prompt":"A slow aerial shot drifting over a misty pine forest at sunrise","prompt_optimization_mode":"off","resolution":"768p"}' \
--waitL’input è lo schema di questo endpoint, lo stesso degli esempi qui sopra. --wait interroga finché l’attività non è finita e poi la stampa; aggiungi --yes per saltare la richiesta di conferma in CI. Imposta prima SPICY_API_KEY: una sola chiave vale per l’API, per la CLI e per il server MCP.
npx @spicyapi/cli tasks create --model pruna-ai/p-video-2-pro/reference-to-video \
--input-json '{…}' --retention 1h --wait
npx @spicyapi/cli tasks get $TASK_ID # read back the retention that applied--retention può solo accorciare la finestra: 30m, 1h, 7d, oppure 0 per cancellare appena l’attività raggiunge uno stato terminale. Il valore che vale davvero è il più corto fra la tua richiesta, le impostazioni del tuo account e il massimo di piattaforma, quindi rileggilo dal record dell’attività invece di dare per scontato il numero che hai chiesto. Passare una finestra più lunga di quanto consente il tuo account non ha nessun effetto.
Installa i nodi SpicyAPI da ComfyUI Manager o con il comando qui sotto, poi cerca P-Video 2 Pro · Reference to Video sulla tela. Il nodo ha le stesse opzioni di questa pagina e mostra il prezzo prima dell’esecuzione.
cd ComfyUI/custom_nodes
git clone https://github.com/spicyapi-ai/comfyui-spicyapiIl pannello incorporato legge lo stesso schema di questa pagina, quindi non può discostarsi dall’API. Se nella tua documentazione i contenuti devono essere ricercabili, leggi il JSON sotto /api/embed/models/ e renderizzalo per conto tuo.
<iframe src="https://spicyapi.ai/embed/it/models/p-video-2-pro/api?model=pruna-ai%2Fp-video-2-pro%2Freference-to-video" width="100%" height="560" loading="lazy" title="Esempio di richiesta" style="border:1px solid rgba(0,0,0,.12)"></iframe>