Quickstart: seu primeiro clipe
Do link do vídeo ao MP4 renderizado, com requisições reais
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:
export CUTPRO_API_KEY="sua_chave"Todos os exemplos usam a URL base https://api.cut.pro/api/v1 e enviam a chave no header X-Api-Key. Se a sua chave for multi-workspace, adicione também X-Workspace-Id.
1. Analise o vídeo
POST /clips/info lê os metadados do link e calcula o custo. Analisar não consome créditos.
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" }'{
"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 esse id: é o video_id de todas as chamadas seguintes.
Quer clipar um arquivo do seu computador em vez de uma URL? Veja Enviando um vídeo para o fluxo de upload.
2. Envie para clipagem
POST /clips cria a submissão. Os créditos são debitados aqui, no valor que o passo anterior mostrou.
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 }
}'{
"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.
strategy_id, template_id e source_language (auto, en, pt) também são opcionais. Liste seus templates com GET /templates para obter os IDs.
3. Acompanhe até concluir
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).
curl https://api.cut.pro/api/v1/clips/7412908365112823/submissions/7412908371004912 \
-H "X-Api-Key: $CUTPRO_API_KEY"{
"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.
4. Busque os clipes gerados
curl https://api.cut.pro/api/v1/clips/7412908365112823/submissions/7412908371004912/clips \
-H "X-Api-Key: $CUTPRO_API_KEY"{
"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.
5. Renderize um clipe
POST .../render gera o MP4 final. Para aplicar um dos seus visuais antes, chame POST .../apply_template na submissão.
curl -X POST \
https://api.cut.pro/api/v1/clips/7412908365112823/submissions/7412908371004912/clips/7412908412887301/render \
-H "X-Api-Key: $CUTPRO_API_KEY"{
"id": "7412908490112774",
"edit_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.
6. Acompanhe o render
curl https://api.cut.pro/api/v1/renders/7412908490112774 \
-H "X-Api-Key: $CUTPRO_API_KEY"{
"id": "7412908490112774",
"edit_id": "7412908490112775",
"status": "active",
"progress": 64,
"output_resolution": "1080p"
}O status passa por queued, active e completed, e progress vai de 0 a 100.
7. Baixe o MP4
curl https://api.cut.pro/api/v1/renders/7412908490112774/download \
-H "X-Api-Key: $CUTPRO_API_KEY"{
"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.
O fluxo inteiro em um arquivo
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.id }),
});
const base = `/clips/${video.id}/submissions/${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.id}`);
if (job.status !== "completed") {
if (job.status === "queued" || job.status === "active") continue;
throw new Error(job.status);
}
download = (await call(`/renders/${render.id}/download`)).url;
}
console.log(best.title, download);