Leve os clipes renderizados para o TikTok, Instagram, YouTube e mais
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:
export CUTPRO_API_KEY="sua_chave"1. Analise o vídeo
Seção intitulada “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" }'{ "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.
2. Envie para clipagem
Seção intitulada “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 } }'{ "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.
3. Acompanhe até concluir
Seção intitulada “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"{ "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.
4. Busque os clipes gerados
Seção intitulada “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
Seção intitulada “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"{ "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.
6. Acompanhe o render
Seção intitulada “6. Acompanhe o render”curl https://api.cut.pro/api/v1/renders/7412908490112774 \ -H "X-Api-Key: $CUTPRO_API_KEY"{ "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.
7. Baixe o MP4
Seção intitulada “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
Seção intitulada “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.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);import osimport time
import requests
API = "https://api.cut.pro/api/v1"HEADERS = {"X-Api-Key": os.environ["CUTPRO_API_KEY"]}
def call(path, method="GET", **kwargs): response = requests.request(method, f"{API}{path}", headers=HEADERS, **kwargs) body = response.json() if not response.ok: raise RuntimeError(f"{response.status_code} {body.get('code')}") return body
video = call("/clips/info", "POST", json={"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"})print(f"{video['title']}: {video['credits_cost']} créditos")
submission = call("/clips", "POST", json={"video_id": video["video_id"]})
base = f"/clips/{video['video_id']}/submissions/{submission['submission_id']}"state = submissionwhile state["status"] != "completed": if state["status"] == "failed": raise RuntimeError(state["error_code"]) time.sleep(15) state = call(base)
clips = call(f"{base}/clips")["clips"]best = max(clips, key=lambda clip: clip["rating"])
render = call(f"{base}/clips/{best['id']}/render", "POST")download = render["download_url"] if render["from_cache"] else Nonewhile not download: time.sleep(10) job = call(f"/renders/{render['render_id']}") if job["status"] == "completed": download = call(f"/renders/{render['render_id']}/download")["url"] elif job["status"] not in ("queued", "active"): raise RuntimeError(job["status"])
print(best["title"], download)E agora?
Seção intitulada “E agora?”Entenda o consumo de créditos e como consultar o saldo