Animate Photo API
POST /animate_photo
About this tool
Static key art sells stories better with subtle motion loops, cinematic zooms, or faux parallax. `/animate_photo` ingests `photo_url` JPEG/PNG masters and outputs MP4, WebM, or GIF via `output_format`, letting marketing teams programmatically widen asset libraries. Control pacing with `duration` knobs and subtle `zoom_direction` (`none`, `in`, `out`). Everything posts as JSON referencing HTTPS stills; no multipart; and subscription API keys authorize each render just like heavyweight video jobs. Document brand-safe zoom ranges in design systems so motion never crops regulated disclaimers.
GIF exports trade quality for autoplay loops; MP4 excels for ads, while WebM suits internal Chrome-first previews. FFmpeg scripts honor color transforms documented beside this slug, yet banding still appears when 8-bit sRGB stills slam into ruthlessly quantized GIF palettes. Burst campaigns deserve prewarming because dozens of motions per minute fan out across shared FFmpeg clusters governed by subscription throttles that protect every tenant evenly.
Workflow integrations often originate from DAM webhooks: new hero still arrives, Lambda fires JSON, polled tasks drop derivatives back into buckets. Designers preview via the panel below without reading curl manuals, while coders templatize payloads in Terraform-reviewed repos. Consumers hunting “free meme animators” won’t find unmanaged usage here; FFmpeg minutes map to billed subscription units. CRM-driven merchandising teams reuse the exact JSON schema across storefront regions, stamping locale-specific `photo_url` values while freezing `zoom_direction`, which keeps motion branding consistent continent to continent. Embed checksums when syncing stills across CDNs so workers never animate stale thumbnails during flash sales.
Quality-control teams should clamp `duration` to platform limits; stories punish heavy files even if motion looks smooth. Logs include FFmpeg filter traces if zoom math clips edges unexpectedly, and automated golden-image diffing against prior releases helps catch accidental padding changes when CDN URLs rotate between marketing seasons.
Security remains mundane: sanitize `photo_url` domains, disallow private RFC1918 ranges if your wrappers allow operator input, and rotate API keys anytime contractors depart.
Try it now
How it works
Publish an HTTPS still
Upload the photo asset to reachable storage with stable TLS. Gather direct object URLs rather than ephemeral HTML wrappers.
Tune motion JSON
Select `output_format`, `duration`, and `zoom_direction` per creative brief; each influences FFmpeg graph construction before encode.
POST `/animate_photo`
Authenticate with subscription keys and await the async scaffolding response; binary never rides the POST.
Poll and distribute loops
Download finished MP4/WebM/GIF files, automate CDN invalidation, and embed them in storefronts.
Frequently asked questions
Which export formats support transparency?
GIF and WebM can carry alpha in some cases; MP4 does not. Check the docs and test in your target platform if transparency matters.
Will zoom-in distort faces at the edge of the frame?
Zoom applies a centered scale. Tall portraits or tight crops may clip subjects; pad the image or choose zoom out for context.
Why are GIF exports so much slower than MP4?
GIF encoding is CPU-heavy and produces large files. Use MP4 or WebM for web players; reserve GIF for chat apps that require it.
Can I animate a TIFF or RAW photo?
Use JPG or PNG URLs listed in the API docs. Convert exotic formats to a supported raster type before submitting.
How long should the loop run?
Three to eight seconds works for social and chat. Longer loops increase file size, especially for GIF output.
Does Elite treat GIF jobs differently for billing?
GIF encoding costs more CPU than MP4. Heavy GIF batches may run slower on lower tiers; plan concurrency accordingly.
How do I use the Animate Photo API?
POST to /animate_photo with a JSON body containing photo_url, output_format, duration and your X-API-Key header. The API returns a task_id; poll GET /task/{task_id} until status is "completed" to retrieve the download_url.
Via the REST API
curl -X POST https://droidapps.one/animate_photo \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_KEY" \
-d '{
"photo_url": "https://cdn.example.com/hero.jpg",
"output_format": "YOUR_OUTPUT_FORMAT",
"duration": 6,
"zoom_direction": "YOUR_ZOOM_DIRECTION"
}'Via the MCP server (droidapps-ffmpeg)
const job = await mcp.callTool("submit_job", {
path: "/animate_photo",
body: {
photo_url: "https://cdn.example.com/hero.jpg",
output_format: "YOUR_OUTPUT_FORMAT",
duration: 6,
zoom_direction: "YOUR_ZOOM_DIRECTION"
}
})
// Returns: { task_id: "abc123", status: "queued" }
const result = await mcp.callTool("wait_for_task", {
task_id: job.task_id
})
// Returns: { status: "completed", download_url: "https://..." }