Python
Render videos in PythonBeta
Render a video template as an MP4 and follow its progress with the Python SDK.
A video template renders as an MP4. Each second of the video counts as one generation, and as two at 60 fps. Generate videos explains how to design one.
render_video and render_and_wait_video take a template id and keyword arguments.
The id of a video template, for example tpl_xxx.
The values to put into the template’s layers. A video layer takes a src, and an audio track takes a src with its name. Modifications lists the fields each layer accepts.
Render and wait for the URL
render_and_wait_video returns {"result": url} or {"error": {...}}.
result = client.render_and_wait_video(
"tpl_xxx",
modifications=[
{"name": "headline", "text": "Summer sale"},
{"name": "music", "src": "https://example.com/song.mp3"},
],
)
if "error" in result:
raise RuntimeError(result["error"]["message"])
print(result["result"])
Follow the progress
render_video yields event dicts. The last event is done or error.
for event in client.render_video("tpl_xxx", modifications=[{"name": "headline", "text": "Summer sale"}]):
if event["type"] == "queued":
print(f"{event['ahead']} videos before this one")
elif event["type"] == "progress":
print(f"{event['progress']:.0%}")
elif event["type"] == "done":
print(event["url"])
elif event["type"] == "error":
print(event["error"]["message"])
| Event | Fields |
|---|---|
created |
id: the id of the video, for example vid_xxx |
queued |
ahead: the number of videos before this one |
progress |
frame, totalFrames, and progress from 0 to 1 |
done |
url: the URL of the MP4 |
error |
error: code, message, and requestId |
A refused request, such as an invalid API key or a used-up quota, gives one error event. The client timeout applies only to the connection, because a video can wait in line for minutes.
Reconnect after a dropped connection
The video renders to its end, even when the connection drops. Then render_video reads the same video again by the id from the created event, and it continues to yield events. It never sends the render again, so you do not pay for a second video.
| Attempt | Wait before it |
|---|---|
| 1 | 1 second |
| 2 | 2 seconds |
| 3 | 4 seconds |
| 4 | 8 seconds |
When the attempts run out, or the connection drops before the created event, the last event is an error with the code TIMEOUT_ERROR. render_and_wait_video reconnects in the same way.
Start a video without waiting
create_video starts the video and returns its id at once. It does not wait for the render. Then read the video with get_video or watch_video.
result = client.create_video("tpl_xxxxxxxxx", modifications=[{"name": "title", "text": "Hi"}])
if "error" in result:
raise RuntimeError(result["error"]["message"])
print(result["result"]["id"]) # vid_xxx, with the status queued
create_video sends the render only once. A second request renders a second video.
Read a video again
Keep the id from the created event. get_video returns the status of the video, and its URL when it is done.
result = client.get_video("vid_xxx")
if "error" in result:
raise RuntimeError(result["error"]["message"])
video = result["result"]
print(video["status"], video.get("url"))
status is queued, rendering, done, or failed. A failed video has an error string. An unknown id gives an error with the code NOT_FOUND.
watch_video yields the events of the video again, from the latest one. It has no created event, and it reconnects as render_video does.
for event in client.watch_video("vid_xxx"):
if event["type"] == "done":
print(event["url"])