Pular para o conteúdo

Quickstart: seu primeiro clipe

Sete requisições separam um link do YouTube de um clipe vertical renderizado. Este guia mostra as sete, na ordem, com a resposta de cada uma.

Antes de começar, gere uma chave de API e exporte-a no seu terminal:

Terminal window
export CUTPRO_API_KEY="sua_chave"

POST /clips/info lê os metadados do link e calcula o custo. Analisar não consome créditos.

Terminal window
curl -X POST https://api.cut.pro/api/v1/clips/info \
-H "X-Api-Key: $CUTPRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }'
Resposta
{
"video_id": "7412908365112823",
"title": "Entrevista completa: 2 horas sobre carreira",
"author": "Canal Exemplo",
"platform": "youtube",
"duration": 7245,
"credits_cost": 121,
"current_balance": 480,
"credits_unlimited": false,
"force_watermark": false
}

Guarde o video_id: é ele que identifica o vídeo em todas as chamadas seguintes.

POST /clips cria a submissão. Os créditos são debitados aqui, no valor que o passo anterior mostrou.

Terminal window
curl -X POST https://api.cut.pro/api/v1/clips \
-H "X-Api-Key: $CUTPRO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"video_id": "7412908365112823",
"timeframe": { "start": 0, "end": 1800 }
}'
Resposta 201
{
"submission_id": "7412908371004912",
"video_id": "7412908365112823",
"status": "queued",
"credits_charged": 30
}

O timeframe é opcional: omita para processar o vídeo inteiro, ou restrinja a um trecho (em segundos) para gastar menos. Acima, a primeira meia hora custou 30 créditos em vez de 121.

Faça polling na submissão a cada 10 ou 15 segundos. O status passa por queued, downloading, transcribing, video_analysis, analyzing e finalizing até chegar em completed (ou failed).

Terminal window
curl https://api.cut.pro/api/v1/clips/7412908365112823/submissions/7412908371004912 \
-H "X-Api-Key: $CUTPRO_API_KEY"
Resposta
{
"submission_id": "7412908371004912",
"video_id": "7412908365112823",
"status": "analyzing",
"error_code": null,
"clips_count": 0,
"queue_position": 2,
"estimated_time": 340
}

Enquanto o vídeo está na fila, queue_position e estimated_time (em segundos) dizem quanto falta. Quando o status vira completed, clips_count traz quantos clipes a IA gerou.

Terminal window
curl https://api.cut.pro/api/v1/clips/7412908365112823/submissions/7412908371004912/clips \
-H "X-Api-Key: $CUTPRO_API_KEY"
Resposta
{
"clips": [
{
"id": "7412908412887301",
"title": "O erro que custou a primeira empresa",
"rating": 9.2,
"start_time": 412.5,
"end_time": 461.8,
"language": "pt",
"play_url": "https://media.cut.pro/preview/...",
"download_url": "https://media.cut.pro/clip/...",
"has_template_applied": false
}
],
"pagination": { "current_page": 1, "total_pages": 1, "total_count": 12, "has_next_page": false }
}

O rating é a nota da IA de 0 a 10: quanto maior, maior o potencial do corte. Ordene por ele para pegar os melhores primeiro.

POST .../render gera o MP4 final. Para aplicar um dos seus visuais antes, chame POST .../apply_template na submissão.

Terminal window
curl -X POST \
https://api.cut.pro/api/v1/clips/7412908365112823/submissions/7412908371004912/clips/7412908412887301/render \
-H "X-Api-Key: $CUTPRO_API_KEY"
Resposta 202
{
"render_id": "7412908490112774",
"edit_setting_id": "7412908490112775",
"status": "queued",
"output_resolution": "1080p",
"has_watermark": false,
"from_cache": false,
"download_url": null
}

Quando from_cache for true, a resposta vem com 200 e o download_url já preenchido: esse clipe já tinha sido renderizado com as mesmas configurações e você pode pular os dois passos seguintes.

Terminal window
curl https://api.cut.pro/api/v1/renders/7412908490112774 \
-H "X-Api-Key: $CUTPRO_API_KEY"
Resposta
{
"render_id": "7412908490112774",
"edit_setting_id": "7412908490112775",
"status": "active",
"progress": 64,
"output_resolution": "1080p"
}

O status passa por queued, active e completed, e progress vai de 0 a 100.

Terminal window
curl https://api.cut.pro/api/v1/renders/7412908490112774/download \
-H "X-Api-Key: $CUTPRO_API_KEY"
Resposta
{
"url": "https://media.cut.pro/render/7412908490112774.mp4?signature=...",
"filename": "o-erro-que-custou-a-primeira-empresa.mp4"
}

A url é assinada e vale por uma hora. Baixe o arquivo dentro desse prazo ou peça outra.

Os sete passos encadeados, com o polling já resolvido. Troque a URL do vídeo e rode.

const API = "https://api.cut.pro/api/v1";
const headers = {
"X-Api-Key": process.env.CUTPRO_API_KEY,
"Content-Type": "application/json",
};
async function call(path, init) {
const response = await fetch(`${API}${path}`, { ...init, headers });
const body = await response.json();
if (!response.ok) throw new Error(`${response.status} ${body.code}`);
return body;
}
const wait = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
const video = await call("/clips/info", {
method: "POST",
body: JSON.stringify({ url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }),
});
console.log(`${video.title}: ${video.credits_cost} créditos`);
const submission = await call("/clips", {
method: "POST",
body: JSON.stringify({ video_id: video.video_id }),
});
const base = `/clips/${video.video_id}/submissions/${submission.submission_id}`;
let state = submission;
while (state.status !== "completed") {
if (state.status === "failed") throw new Error(state.error_code);
await wait(15);
state = await call(base);
}
const { clips } = await call(`${base}/clips`);
const best = [...clips].sort((a, b) => b.rating - a.rating)[0];
const render = await call(`${base}/clips/${best.id}/render`, { method: "POST" });
let download = render.from_cache ? render.download_url : null;
while (!download) {
await wait(10);
const job = await call(`/renders/${render.render_id}`);
if (job.status !== "completed") {
if (job.status === "queued" || job.status === "active") continue;
throw new Error(job.status);
}
download = (await call(`/renders/${render.render_id}/download`)).url;
}
console.log(best.title, download);