Skip to content
Developers / Talking Photo API

Talking Photo API

Send one photo and one audio file, get back an MP4 where the face speaks the audio: lips, head and expression move with the voice. No watermark, no length limit, no subscription. You pay per second of video from prepaid credits, and you bring your own voice or TTS.

Pricing

Per minute of video480p720p1080p
Standard$0.10 (10 credits)$0.20 (20 credits)$0.25 (25 credits)
Pro$0.30 (30 credits)$0.40 (40 credits)$0.60 (60 credits)

At 720p: 10 seconds $0.05 Standard / $0.07 Pro · 1 minute $0.20 Standard / $0.40 Pro · 10 minutes $2.00 Standard / $4.00 Pro · 1 hour $12.00 Standard / $24.00 Pro.

  • 1 credit = 1 cent. Credit packs start at $10 and never expire.
  • Billed per started 10 seconds of finished video, 5 credits minimum per video.
  • We measure your audio before rendering and hold that amount. You are charged for the length we deliver, and a failed render returns every credit.
  • Standard and Pro are different models, not just resolutions: Pro is larger, with steadier, more natural faces, and takes about twice as long to render.

Quickstart

  1. Create an API key in dashboard settings.
  2. Add credits on the credits page.
  3. Start a job, then poll it or wait for the webhook.
Start a video
curl -X POST https://mcp.stork.ai/api/v1/talking-photo \
  -H "Authorization: Bearer sk_stork_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/face.jpg",
    "audio_url": "https://example.com/speech.mp3",
    "quality": "standard",
    "aspect_ratio": "9:16",
    "resolution": "720p",
    "webhook_url": "https://your-app.com/hooks/stork"
  }'
Response
HTTP/1.1 202 Accepted
{
  "id": "yh717dydntg7p6zj0fvr2e2jax8j6zxd",
  "object": "talking_photo",
  "status": "queued",
  "quality": "standard",
  "aspect_ratio": "9:16",
  "resolution": "720p",
  "audio_seconds": 20.06,
  "billed_seconds": 30,
  "credits_held": 10,
  "balance_credits": 990,
  "status_url": "https://mcp.stork.ai/api/v1/talking-photo?id=yh717dydntg7p6zj0fvr2e2jax8j6zxd"
}
Check status
curl "https://mcp.stork.ai/api/v1/talking-photo?id=yh717dydntg7p6zj0fvr2e2jax8j6zxd" \
  -H "Authorization: Bearer sk_stork_YOUR_KEY"
Finished
{
  "id": "yh717dydntg7p6zj0fvr2e2jax8j6zxd",
  "object": "talking_photo",
  "status": "succeeded",
  "quality": "standard",
  "aspect_ratio": "9:16",
  "resolution": "720p",
  "progress": 1,
  "billed_seconds": 30,
  "duration_seconds": 20,
  "credits_held": 0,
  "credits_charged": 7,
  "video_url": "https://…/api/storage/dc98d835-….mp4",
  "error": null,
  "created_at": "2026-11-14T03:35:23.723Z",
  "completed_at": "2026-11-14T03:37:04.960Z"
}
Python
import time, requests

KEY = "sk_stork_YOUR_KEY"
H = {"Authorization": f"Bearer {KEY}"}
URL = "https://mcp.stork.ai/api/v1/talking-photo"

job = requests.post(URL, headers=H, json={
    "image_url": "https://example.com/face.jpg",
    "audio_url": "https://example.com/speech.mp3",
    "quality": "pro",
}).json()

while True:
    s = requests.get(URL, headers=H, params={"id": job["id"]}).json()
    if s["status"] in ("succeeded", "failed"):
        break
    time.sleep(10)

print(s["video_url"] or s["error"])

Reference

POST /api/v1/talking-photo

  • image_url (required): public https URL of a JPG, PNG or WebP with one clear face, up to 12 MB.
  • audio_url (required): public https URL of speech audio (MP3, WAV, M4A, OGG, WebM), up to 200 MB. Any length.
  • quality: "standard" (default) or "pro".
  • aspect_ratio: "original" (default, the photo's own shape), "16:9", "9:16" or "1:1". We crop around the face; if the face wouldn't fit, the whole photo is placed on a blurred fill.
  • resolution: "480p", "720p" (default) or "1080p", the short side of the frame (720p 16:9 = 1280x720, 720p 9:16 = 720x1280).
  • webhook_url: https URL we POST the finished job to.

GET /api/v1/talking-photo?id=<id>

Returns the job. status is queued, running, succeeded or failed. progress goes from 0 to 1 while rendering. video_url is set once it succeeds.

Webhooks

If you pass webhook_url, we POST once when the job finishes. We retry twice, a minute apart, if your endpoint doesn't return 2xx.

POST https://your-app.com/hooks/stork
Content-Type: application/json
User-Agent: Stork-Webhooks/1

{ "type": "talking_photo.succeeded", "data": { ...same object as GET... } }

Errors

Errors return { "error": { "code", "message" } }.

401missing_api_key / invalid_api_keyNo key, or the key is wrong or revoked.
402insufficient_creditsThe wallet can't cover this video. The body has credits_required, balance_credits and top_up_url.
400invalid_requestimage_url and audio_url are required https URLs.
400invalid_qualityquality is "standard" or "pro".
400image_fetch_failed / audio_fetch_failedWe couldn't download a URL. It must be public and https.
400audio_not_audio / audio_unreadableThe file isn't audio we can read. Use MP3, WAV, M4A, OGG or WebM.
413image_too_large / audio_too_largeImages up to 12 MB, audio up to 200 MB.
429too_many_in_flight5 videos are already rendering on your account. Wait for one to finish.
503temporarily_unavailable / probe_unavailableRetry in a minute.

Limits

  • Up to 5 videos rendering at once per account; more are refused with 429.
  • Render time: a short clip takes about a minute. Standard renders roughly as fast as the clip plays, and Pro takes about twice as long. Add up to 2 minutes if the renderer has been idle.
  • Output: MP4 (H.264 + AAC, 25 fps) at the aspect ratio and resolution you ask for.
  • video_url works for 30 days. Store your copy. We keep the inputs and output after that; email support@stork.ai to have them deleted.

Acceptable use

Only animate faces you own or have permission to use. Don't use the API to deceive, impersonate or harass anyone, and tell viewers the video is AI-generated. We may suspend keys that break these rules.

Want to try it without code? Use the AI Talking Photo tool.