Turn a roleplay debrief into an avatar feedback clip in Python

Take the written debrief from a roleplay or survey session and render it as a 16:9 Sume avatar clip with a retry-safe key, a 12 to 168 word check and polling.

5 min readSume
All posts

To turn a written roleplay debrief into a spoken avatar clip on Sume, POST the text as script to /v1/avatar-1.0/talking-video with a saved avatar handle, then poll the status URL from the response until data.sume_status is completed. The sample below does that for a debrief that estimates between 4 and 60 seconds, using an idempotency key so a retry does not bill twice.

Where the debrief comes from is up to you. A live roleplay product such as Synthesia's Sessions, launched October 1, 2026, produces its own analysis in its own interface; this post assumes you have already copied the text into your system.

The code

It needs SUME_API_KEY and a ready avatar handle. The word check uses the docs' 2.8 words per second estimate, so 12 to 168 words is roughly 4 to 60 seconds.

What the sample uses, from the Sume avatar video docs (read 2026-10-08)
ItemValue
EndpointPOST /v1/avatar-1.0/talking-video
Retry safetyIdempotency-Key header
Terminal statusescompleted, failed, canceled
Duration window4 to 60 seconds
Standard rate$0.184 a second, no product image
import os, time, requests
from urllib.parse import urljoin
BASE = "https://api.sume.com"
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
def feedback_clip(handle, debrief, key):
    n = len(debrief.split())
    if not 12 <= n <= 168:
        raise ValueError(f"{n} words: outside the 4-60 s window")
    body = {"avatar_handle": handle, "script": debrief,
            "quality": "standard", "aspect_ratio": "16:9"}
    r = requests.post(BASE + "/v1/avatar-1.0/talking-video",
                      headers={**H, "Idempotency-Key": key},
                      json=body, timeout=30)
    r.raise_for_status()
    d = r.json()["data"]
    while True:
        s = requests.get(urljoin(BASE, d["status_url"]), headers=H, timeout=30)
        status = s.json()["data"]["sume_status"]
        if status == "completed":
            break
        if status in ("failed", "canceled"):
            raise RuntimeError(status)
        time.sleep(5)
    res = requests.get(urljoin(BASE, d["result_url"]), headers=H, timeout=30)
    return res.json()

if __name__ == "__main__":
    text = "You opened well and named the budget concern early. " * 3
    print(feedback_clip("my_avatar", text, "debrief-2026-10-08-001"))

Before you run it

Create the avatar first and wait until it is ready; the avatar docs describe creation as its own job with the $0.95 charge, and GET /v1/avatar-1.0/avatars lists the handles you can use. The script above uses my_avatar as a placeholder, so replace it with a real handle.

The loop polls every 5 seconds with no timeout, which is fine for a sketch. In production, add a deadline and log the status URL so a stuck job can be found later.

Notes on the sample

The key should be unique per debrief: reuse it only to retry the same request. The result is printed as returned; the avatar docs say completed results can include public media.sume.com video artifacts, so read the video URL from that JSON rather than assuming a field name.

At 100 words (about 36 seconds) a Standard clip is about $6.57. A 168-word debrief hits the 60-second ceiling and costs about $11.04; anything longer needs splitting, which the planner post shows.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume