Captioning API · v1
Picute Captioning API
Gửi một URL video, nhận về MP4 có phụ đề, tệp SRT và JSON bản chép lời qua liên kết tải xuống có chữ ký.
Quick start
Pick your language. The snippets below submit a caption job using your API key — replace the placeholder before running.
curl -X POST https://picute.net/api/v1/captions \
-H "Authorization: Bearer pk_live_<your_key>" \
-H "Content-Type: application/json" \
-d '{
"video_url": "https://cdn.example.com/clip.mp4",
"language": "ko",
"target_language": "en",
"preset": "default",
"style": { "font_size": 28, "position": "bottom_center", "outline_width": 2 },
"callback_url": "https://api.your-app.com/webhooks/picute"
}'Tham chiếu API
Tất cả endpoint, schema yêu cầu và mã lỗi của v1. Nhấp vào bất kỳ thao tác nào để mở rộng schema yêu cầu và phản hồi.
Webhooks
Picute POSTs a signed webhook to your callback URL when a caption job reaches a terminal state. Verify the X-Picute-Signature header before trusting the payload.
Events
caption.completed— Caption job succeeded. data is the full Caption resource with output URLs populated.caption.failed— Caption job failed. data.error has the error code and message.
Verify the signature
Compute HMAC-SHA256 over the raw 'timestamp.body' string with your webhook secret, then constant-time compare against the hex digest in the v1= field of the header.
import hmac, hashlib, time
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = "<your_webhook_secret_from_dashboard>"
TOLERANCE_SECONDS = 5 * 60
def verify(req):
header = req.headers.get("X-Picute-Signature", "")
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
timestamp = int(parts.get("t", "0"))
received = parts.get("v1", "")
if abs(time.time() - timestamp) > TOLERANCE_SECONDS:
return False
signed = f"{timestamp}.{req.get_data(as_text=True)}".encode("utf-8")
expected = hmac.new(SECRET.encode("utf-8"), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, received)
@app.post("/webhooks/picute")
def hook():
if not verify(request):
abort(401)
payload = request.get_json()
print(payload["event"], payload["data"]["id"])
return "", 204