Captioning API · v1

Picute Captioning API

Gửi một URL video, nhận về MP4 có phụ đề nhúng sẵn, SRT đã ký và JSON bản chép lời. Toàn bộ bề mặt v1 được tài liệu hóa bên dưới — Quick Start, tham chiếu tương tác và xác minh webhook.

Bắt đầu nhanh

Chọn ngôn ngữ của bạn. Các đoạn mã bên dưới gửi một job tạo phụ đề bằng API key của bạn — thay placeholder trước khi chạy.

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": "auto",
    "preset": "default",
    "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.

Webhook

Picute gửi POST một webhook đã ký đến callback URL của bạn khi job tạo phụ đề đạt trạng thái cuối. Hãy xác minh header X-Picute-Signature trước khi tin tưởng payload.

Sự kiện

  • caption.completedJob tạo phụ đề thành công. data là toàn bộ tài nguyên Caption với các URL đầu ra đã được điền.
  • caption.failedJob tạo phụ đề thất bại. data.error chứa mã lỗi và thông báo lỗi.

Xác minh chữ ký

Tính HMAC-SHA256 trên chuỗi raw 'timestamp.body' bằng webhook secret của bạn, sau đó so sánh ở thời gian hằng số với hex digest nằm trong trường v1= của 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