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 video | 480p | 720p | 1080p |
|---|---|---|---|
| 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
- Create an API key in dashboard settings.
- Add credits on the credits page.
- Start a job, then poll it or wait for the webhook.
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"
}'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"
}curl "https://mcp.stork.ai/api/v1/talking-photo?id=yh717dydntg7p6zj0fvr2e2jax8j6zxd" \
-H "Authorization: Bearer sk_stork_YOUR_KEY"{
"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"
}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" } }.
| 401 | missing_api_key / invalid_api_key | No key, or the key is wrong or revoked. |
| 402 | insufficient_credits | The wallet can't cover this video. The body has credits_required, balance_credits and top_up_url. |
| 400 | invalid_request | image_url and audio_url are required https URLs. |
| 400 | invalid_quality | quality is "standard" or "pro". |
| 400 | image_fetch_failed / audio_fetch_failed | We couldn't download a URL. It must be public and https. |
| 400 | audio_not_audio / audio_unreadable | The file isn't audio we can read. Use MP3, WAV, M4A, OGG or WebM. |
| 413 | image_too_large / audio_too_large | Images up to 12 MB, audio up to 200 MB. |
| 429 | too_many_in_flight | 5 videos are already rendering on your account. Wait for one to finish. |
| 503 | temporarily_unavailable / probe_unavailable | Retry 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.
