Guide: Simple Python App for Generating Videos from HeyGen Templates

In this guide, we'll explore how to generate a dynamic video presentation with Python using HeyGen's V2 Template API. We'll focus on a template called Fruit Presentation, comprising 5 scenes. By inputting specific fruit details, we'll customize and generate engaging presentation videos.

Here's an overview of the Fruit Presentation timeline and its associated variables and scripts:

  • Scene 1: FRUIT_NAME, Subtitle, scene_1_image_1

    Welcome to the FRUIT_NAME presentation.

  • Scene 2: scene_2_bg_image

    scene_2_script

  • Scene 3: scene_3_image_1, scene_3_image_2, scene_3_image_3

    scene_3_script

  • Scene 4: scene_4_bg_image, scene_4_image_1, scene_4_image_2, scene_4_image_3

    scene_4_script

  • Scene 5: scene_5_bg_image, scene_5_image_1, scene_5_image_2, scene_5_image_3

    scene_5_script

Now, let's proceed to the Python code.

Step 1. Obtain the Template ID

See detailed API reference
Using the following API request you will get a list of your templates that you have created in the HeyGen interface, obtain your template_id from here.

curl --location 'https://api.heygen.com/v2/templates' \
     --header 'accept: application/json' \
     --header 'x-api-key: <your-api-key>'
{
  "error": null,
  "data": {
    "templates": [
      {
        "template_id": "<template_id>",
        "name": "Fruits Presentation",
        "thumbnail_image_url": "https://resource.heygencdn.com/image/313f99089bf3410bb7f3ffcadf9b8864/original"
      },
      ...
    ]
  }
}
template_list_url = "https://api.heygen.com/v2/templates"
headers = {"accept": "application/json", "x-api-key": api_key}
response = requests.get(template_list_url, headers=headers)
template_id = response.json()["data"]["templates"][0]["template_id"] # Get the first template_id

Step 2. Obtain Video Elements

See detailed API reference
To retrieve video elements for a specific template, use this API request to get the variable you want to change.

curl --location 'https://api.heygen.com/v2/template/<template_id>' \
     --header 'accept: application/json' \
     --header 'x-api-key: <your-api-key>'
{
  "error": null,
  "data": {
    "variables": {
      "Subtitle": {
        "name": "Subtitle",
        "type": "text",
        "properties": {
          "content": ""
        }
      },
      "FRUIT_NAME": {
        "name": "FRUIT_NAME",
        "type": "text",
        "properties": {
          "content": ""
        }
      },
      "scene_2_script": {
        "name": "scene_2_script",
        "type": "text",
        "properties": {
          "content": ""
        }
      },
      "scene_3_script": {
        "name": "scene_3_script",
        "type": "text",
        "properties": {
          "content": ""
        }
      },
      "scene_4_script": {
        "name": "scene_4_script",
        "type": "text",
        "properties": {
          "content": ""
        }
      },
      "scene_5_script": {
        "name": "scene_5_script",
        "type": "text",
        "properties": {
          "content": ""
        }
      },
      "scene_1_image_1": {
        "name": "scene_1_image_1",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/c0d751f0-ef87-4ee5-b5f4-6ad080b21de2",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_3_image_1": {
        "name": "scene_3_image_1",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/e2265816-4531-49eb-8e75-4ba8a7cf6305",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_3_image_2": {
        "name": "scene_3_image_2",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/a7e01dbd-ea84-41cc-b1b7-cb843bf6f9c8",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_3_image_3": {
        "name": "scene_3_image_3",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/29cd0a23-1885-4727-b695-ef17cfa0813e",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_4_image_1": {
        "name": "scene_4_image_1",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/e2265816-4531-49eb-8e75-4ba8a7cf6305",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_4_image_2": {
        "name": "scene_4_image_2",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/a7e01dbd-ea84-41cc-b1b7-cb843bf6f9c8",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_4_image_3": {
        "name": "scene_4_image_3",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/29cd0a23-1885-4727-b695-ef17cfa0813e",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_5_image_1": {
        "name": "scene_5_image_1",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/e2265816-4531-49eb-8e75-4ba8a7cf6305",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_5_image_2": {
        "name": "scene_5_image_2",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/a7e01dbd-ea84-41cc-b1b7-cb843bf6f9c8",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_5_image_3": {
        "name": "scene_5_image_3",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/29cd0a23-1885-4727-b695-ef17cfa0813e",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_2_bg_image": {
        "name": "scene_2_bg_image",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/332c8f13-63e6-4378-9f01-293f13e4314c",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_4_bg_image": {
        "name": "scene_4_bg_image",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/332c8f13-63e6-4378-9f01-293f13e4314c",
          "asset_id": null,
          "fit": "none"
        }
      },
      "scene_5_bg_image": {
        "name": "scene_5_bg_image",
        "type": "image",
        "properties": {
          "url": "blob:https://app.heygen.com/332c8f13-63e6-4378-9f01-293f13e4314c",
          "asset_id": null,
          "fit": "none"
        }
      }
    }
  }
}
template_url = f"https://api.heygen.com/v2/template/{template_id}"
response = requests.get(template_url, headers=headers)

Step 3. Prepare Variable Values

Define variable values like fruit names, subtitles, and scripts.

api_key = "<your-api-key>"
headers = {"Accept": "application/json", "X-API-KEY": api_key}
template_id = "<template_id>"

FRUIT_NAME = "APPLE"
Subtitle = "The Wonderful World of Apples"
scene_2_script = "Apples are one of the most widely consumed fruits worldwide. They come in various colors, shapes, and sizes, with over 7,500 known apple cultivars around the world."
scene_3_script = (
    "Some popular varieties include Granny Smith, Red Delicious, Gala, and Fuji."
)
scene_4_script = "They are a rich source of dietary fiber, vitamin C, and antioxidants. Eating apples regularly has been linked to numerous health benefits, including improved digestion, lowered risk of heart disease, and enhanced immune function..."
scene_5_script = "Additionally, apples are often associated with folklore and cultural traditions. They symbolize knowledge, temptation, and forbidden fruit in various mythologies and stories."

# and images...

Step 4. Generate Video from Template

Send a payload to the Generate endpoint for video creation.

generate_url = f"https://api.heygen.com/v2/template/{template_id}/generate"
payload = {
    "test": True,
    "caption": False,
    "title": FRUIT_NAME + " | Fruit Presentation",
    "variables": {
        "Subtitle": {
            "name": "Subtitle",
            "type": "text",
            "properties": {"content": Subtitle},
        },
        "FRUIT_NAME": {
            "name": "FRUIT_NAME",
            "type": "text",
            "properties": {"content": FRUIT_NAME},
        },
        "scene_2_script": {
            "name": "scene_2_script",
            "type": "text",
            "properties": {"content": scene_2_script},
        },
        "scene_3_script": {
            "name": "scene_3_script",
            "type": "text",
            "properties": {"content": scene_3_script},
        },
        "scene_4_script": {
            "name": "scene_4_script",
            "type": "text",
            "properties": {"content": scene_4_script},
        },
        "scene_5_script": {
            "name": "scene_5_script",
            "type": "text",
            "properties": {"content": scene_5_script},
        },
        "scene_1_image_1": {
            "name": "scene_1_image_1",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1567974772901-1365e616baa9",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_3_image_1": {
            "name": "scene_3_image_1",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/bD6x1R5.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_3_image_2": {
            "name": "scene_3_image_2",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/GmT8jqJ.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_3_image_3": {
            "name": "scene_3_image_3",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/kFXc1Dg.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_4_image_1": {
            "name": "scene_4_image_1",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1552255349-450c59a5ec8e",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_4_image_2": {
            "name": "scene_4_image_2",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1570913149827-d2ac84ab3f9a",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_4_image_3": {
            "name": "scene_4_image_3",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/OeCAhPD.png",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_5_image_1": {
            "name": "scene_5_image_1",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/pFJPqUx.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_5_image_2": {
            "name": "scene_5_image_2",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/8MwSsQG.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_5_image_3": {
            "name": "scene_5_image_3",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/HxAM8yR.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_2_bg_image": {
            "name": "scene_2_bg_image",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1545160788-dc8fd1971a96",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_4_bg_image": {
            "name": "scene_4_bg_image",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1620992467768-3cb360bf2aac",
                "asset_id": None,
                "fit": "crop",
            },
        },
        "scene_5_bg_image": {
            "name": "scene_5_bg_image",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1605153322277-dd0d7f608b4d",
                "asset_id": None,
                "fit": "crop",
            },
        },
    },
}
headers["Content-Type"] = "application/json"
response = requests.post(generate_url, headers=headers, json=payload)
if not response.json()["data"]:
    print(response)
    print(response.json()["error"])
    exit()
video_id = response.json()["data"]["video_id"]
print("video_id:", video_id)

Step 5. Check Video Status and Download the Video

Implement logic to check video status and download the video upon successful completion, we will print the video url and thumbnail url to the console and save the video to storage.

video_status_url = f"https://api.heygen.com/v1/video_status.get?video_id={video_id}"
while True:
    response = requests.get(video_status_url, headers=headers)
    status = response.json()["data"]["status"]

    if status == "completed":
        video_url = response.json()["data"]["video_url"]
        thumbnail_url = response.json()["data"]["thumbnail_url"]
        print(
            f"Video generation completed! \nVideo URL: {video_url} \nThumbnail URL: {thumbnail_url}"
        )

        # Save the video to a file
        video_filename = "generated_video.mp4"
        with open(video_filename, "wb") as video_file:
            video_content = requests.get(video_url).content
            video_file.write(video_content)

        break
    elif status == "processing" or status == "pending":
        print("Video is still processing. Checking status...")
        time.sleep(5)  # Sleep for 5 seconds before checking again
    elif status == "failed":
        error = response.json()["data"]["error"]
        print(f"Video generation failed. '{error}'")
        break

Final Result

Here is the complete Python code:

import requests
import time

api_key = "<your-api-key>"
headers = {"Accept": "application/json", "X-API-KEY": api_key}
template_id = "<template_id>"

FRUIT_NAME = "APPLE"
Subtitle = "The Wonderful World of Apples"
scene_2_script = "Apples are one of the most widely consumed fruits worldwide. They come in various colors, shapes, and sizes, with over 7,500 known apple cultivars around the world."
scene_3_script = (
    "Some popular varieties include Granny Smith, Red Delicious, Gala, and Fuji."
)
scene_4_script = "They are a rich source of dietary fiber, vitamin C, and antioxidants. Eating apples regularly has been linked to numerous health benefits, including improved digestion, lowered risk of heart disease, and enhanced immune function..."
scene_5_script = "Additionally, apples are often associated with folklore and cultural traditions. They symbolize knowledge, temptation, and forbidden fruit in various mythologies and stories."

# Modify Template Elements and Generate Video
generate_url = f"https://api.heygen.com/v2/template/{template_id}/generate"
payload = {
    "test": True,
    "caption": False,
    "title": FRUIT_NAME + " | Fruit Presentation",
    "variables": {
        "Subtitle": {
            "name": "Subtitle",
            "type": "text",
            "properties": {"content": Subtitle},
        },
        "FRUIT_NAME": {
            "name": "FRUIT_NAME",
            "type": "text",
            "properties": {"content": FRUIT_NAME},
        },
        "scene_2_script": {
            "name": "scene_2_script",
            "type": "text",
            "properties": {"content": scene_2_script},
        },
        "scene_3_script": {
            "name": "scene_3_script",
            "type": "text",
            "properties": {"content": scene_3_script},
        },
        "scene_4_script": {
            "name": "scene_4_script",
            "type": "text",
            "properties": {"content": scene_4_script},
        },
        "scene_5_script": {
            "name": "scene_5_script",
            "type": "text",
            "properties": {"content": scene_5_script},
        },
        "scene_1_image_1": {
            "name": "scene_1_image_1",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1567974772901-1365e616baa9",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_3_image_1": {
            "name": "scene_3_image_1",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/bD6x1R5.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_3_image_2": {
            "name": "scene_3_image_2",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/GmT8jqJ.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_3_image_3": {
            "name": "scene_3_image_3",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/kFXc1Dg.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_4_image_1": {
            "name": "scene_4_image_1",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1552255349-450c59a5ec8e",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_4_image_2": {
            "name": "scene_4_image_2",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1570913149827-d2ac84ab3f9a",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_4_image_3": {
            "name": "scene_4_image_3",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/OeCAhPD.png",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_5_image_1": {
            "name": "scene_5_image_1",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/pFJPqUx.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_5_image_2": {
            "name": "scene_5_image_2",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/8MwSsQG.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_5_image_3": {
            "name": "scene_5_image_3",
            "type": "image",
            "properties": {
                "url": "https://i.imgur.com/HxAM8yR.jpg",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_2_bg_image": {
            "name": "scene_2_bg_image",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1545160788-dc8fd1971a96",
                "asset_id": None,
                "fit": "contain",
            },
        },
        "scene_4_bg_image": {
            "name": "scene_4_bg_image",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1620992467768-3cb360bf2aac",
                "asset_id": None,
                "fit": "crop",
            },
        },
        "scene_5_bg_image": {
            "name": "scene_5_bg_image",
            "type": "image",
            "properties": {
                "url": "https://images.unsplash.com/photo-1605153322277-dd0d7f608b4d",
                "asset_id": None,
                "fit": "crop",
            },
        },
    },
}
headers["Content-Type"] = "application/json"
response = requests.post(generate_url, headers=headers, json=payload)
if not response.json()["data"]:
    print(response)
    print(response.json()["error"])
    exit()

video_id = response.json()["data"]["video_id"]
print("video_id:", video_id)

# Check Video Generation Status
video_status_url = f"https://api.heygen.com/v1/video_status.get?video_id={video_id}"
while True:
    response = requests.get(video_status_url, headers=headers)
    status = response.json()["data"]["status"]

    if status == "completed":
        video_url = response.json()["data"]["video_url"]
        thumbnail_url = response.json()["data"]["thumbnail_url"]
        print(
            f"Video generation completed! \nVideo URL: {video_url} \nThumbnail URL: {thumbnail_url}"
        )

        # Save the video to a file
        video_filename = "generated_video.mp4"
        with open(video_filename, "wb") as video_file:
            video_content = requests.get(video_url).content
            video_file.write(video_content)

        break
    elif status == "processing" or status == "pending":
        print("Video is still processing. Checking status...")
        time.sleep(5)  # Sleep for 5 seconds before checking again
    elif status == "failed":
        error = response.json()["data"]["error"]
        print(f"Video generation failed. '{error}'")
        break

Here is the final video output:

Images are sourced from Unsplash and Wikipedia Commons under creative commons license.