| --- |
| title: AI Talking Photo |
| emoji: ποΈ |
| colorFrom: indigo |
| colorTo: purple |
| sdk: gradio |
| sdk_version: 6.9.0 |
| app_file: app.py |
| pinned: false |
| suggested_hardware: cpu-basic |
| startup_duration_timeout: 10m |
| fullWidth: true |
| --- |
| |
| # AI Talking Photo |
|
|
| Banuba AI Talking Photo lets users create realistic talking videos from a single |
| photo, with a simple, intuitive workflow that anyone can understand. It transforms |
| static images into lifelike talking avatars with natural lip-sync, facial |
| expressions, and full-body motion β delivering studio-quality presentations, |
| lessons, and other videos without cameras, actors, or editing. It supports any |
| language, and reliably outputs content up to 1 hour long. |
|
|
| This Space is a free, hosted demo built on the **Banuba AI Tasks API**: no video |
| generation happens in the Space itself β it uploads your reference image and audio, |
| creates a `video.lipsync` task, and shows the result video once it is ready. |
|
|
| > **Demo limits:** this showcase outputs **480p** video capped at **1β10 seconds** |
| > (set by the *Maximum duration* field, default 4s). The full product supports the |
| > longer, higher-resolution output described above β for production use email |
| > [support@banuba.com](mailto:support@banuba.com) or use the contact form at |
| > [banuba.com](https://www.banuba.com). |
|
|
| ## How to use |
|
|
| 1. **Upload a reference image** β a clear, front-facing portrait works best. |
| 2. **Upload a reference audio** clip β the voice the photo will lip-sync to. |
| (Or click one of the ready-made examples under the inputs.) You can trim the |
| clip directly in the audio player if you want a specific section. |
| 3. *(Optional)* **Edit the Prompt.** The field is pre-filled with a sensible |
| default. The prompt guides how the avatar performs β framing, delivery, |
| gestures, lighting and background. Leave it as-is, or tweak it to change the |
| style. If you clear it, the default is used. |
| 4. *(Optional)* Set the **Maximum duration** (default 4 seconds, 1β10s) β the |
| length of the generated video. |
| 5. Click **Generate Talking Photo**. |
| 6. Wait while the task runs β generation usually takes a couple of minutes. You |
| can leave the page and return from the same browser; the Space resumes and |
| keeps polling your latest task. |
| 7. The finished video appears in the **Output** panel. Press play to watch it. |
|
|
| ## About the API |
|
|
| The Space is built on the Banuba AI Tasks API (`https://ai.banuba.net/api/v1`). |
| Calling it requires a `client_id` / `client_secret` issued by Banuba. |
|
|
| The end-to-end flow is four steps. |
|
|
| **1. Get an access token** (OAuth2 client credentials) |
|
|
| ```bash |
| curl -X POST https://ai.banuba.net/auth/v1/token \ |
| -H "Content-Type: application/x-www-form-urlencoded" \ |
| -d "grant_type=client_credentials" \ |
| -d "scope=tasks:write tasks:read" \ |
| -d "client_id=$CLIENT_ID" \ |
| -d "client_secret=$CLIENT_SECRET" |
| ``` |
|
|
| **2. Request an upload URL, then upload each asset** |
|
|
| ```bash |
| # Ask for a presigned upload location |
| curl -X POST https://ai.banuba.net/api/v1/upload \ |
| -H "Authorization: Bearer $TOKEN" \ |
| -H "Content-Type: application/json" \ |
| -d '{"filename": "portrait.png", "content_type": "image/png"}' |
| # -> { "url": "<asset-url>", "upload_url": "<presigned-put-url>" } |
| |
| # Upload the file bytes to the presigned URL |
| curl -X PUT "<presigned-put-url>" \ |
| -H "Content-Type: image/png" \ |
| --data-binary @portrait.png |
| ``` |
|
|
| Repeat for the audio file. Keep each returned `url` β those are the asset URLs |
| you pass to the task. |
|
|
| **3. Create a `video.lipsync` task** |
|
|
| ```bash |
| curl -X POST https://ai.banuba.net/api/v1/tasks \ |
| -H "Authorization: Bearer $TOKEN" \ |
| -H "Content-Type: application/json" \ |
| -d '{ |
| "type": "video.lipsync", |
| "input": { |
| "assets": { |
| "image": { "url": "<image-asset-url>" }, |
| "audio": { "url": "<audio-asset-url>" } |
| }, |
| "seconds": 4, |
| "seed": 7, |
| "prompt": "Waist-up, direct-to-camera, natural gestures, neutral background" |
| } |
| }' |
| # -> { "id": "<task-id>", ... } |
| ``` |
|
|
| `seconds`, `seed`, and `prompt` are optional. Omit `seconds` to let the API use |
| `min(audio_duration_seconds, 10)`. |
|
|
| The **`prompt`** is a free-text instruction that steers the performance β |
| framing, delivery, gestures, lighting and background. If you omit it, the API |
| applies its own defaults. This Space sends the following prompt unless you edit |
| the field in the UI: |
|
|
| > Waist-up, direct-to-camera. I read the script confidently and friendly, with |
| > natural hand gestures timed to speech, brief pauses, subtle facial |
| > expressions. Even lighting, neutral background, steady camera. |
|
|
| **4. Poll the task until it finishes** |
|
|
| ```bash |
| curl https://ai.banuba.net/api/v1/tasks/<task-id> \ |
| -H "Authorization: Bearer $TOKEN" |
| # -> { "status": "COMPLETED", |
| # "result": { "result_file_url": "<video-url>", "content_type": "video/mp4" } } |
| ``` |
|
|
| When `status` is `COMPLETED`, download the video from `result.result_file_url`. |
|
|