8.1 KiB
8.1 KiB
| name | description | metadata | ||
|---|---|---|---|---|
| assets | Uploading images, videos, and audio for use in HeyGen video generation |
|
Asset Upload and Management
HeyGen allows you to upload custom assets (images, videos, audio) for use in video generation, such as backgrounds, talking photo sources, and custom audio.
Upload Flow
Asset uploads use a two-step process:
- Get a presigned upload URL from HeyGen
- Upload the file to the presigned URL
Getting an Upload URL
Request Fields
| Field | Type | Req | Description |
|---|---|---|---|
content_type |
string | ✓ | MIME type of file to upload |
curl
curl -X POST "https://api.heygen.com/v1/asset" \
-H "X-Api-Key: $HEYGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content_type": "image/jpeg"}'
TypeScript
interface AssetUploadRequest {
content_type: string; // Required
}
interface AssetUploadResponse {
error: null | string;
data: {
url: string;
asset_id: string;
};
}
async function getUploadUrl(contentType: string): Promise<AssetUploadResponse["data"]> {
const response = await fetch("https://api.heygen.com/v1/asset", {
method: "POST",
headers: {
"X-Api-Key": process.env.HEYGEN_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({ content_type: contentType }),
});
const json: AssetUploadResponse = await response.json();
if (json.error) {
throw new Error(json.error);
}
return json.data;
}
Python
import requests
import os
def get_upload_url(content_type: str) -> dict:
response = requests.post(
"https://api.heygen.com/v1/asset",
headers={
"X-Api-Key": os.environ["HEYGEN_API_KEY"],
"Content-Type": "application/json"
},
json={"content_type": content_type}
)
data = response.json()
if data.get("error"):
raise Exception(data["error"])
return data["data"]
Supported Content Types
| Type | Content-Type | Use Case |
|---|---|---|
| JPEG | image/jpeg |
Backgrounds, talking photos |
| PNG | image/png |
Backgrounds, overlays |
| MP4 | video/mp4 |
Video backgrounds |
| MP3 | audio/mpeg |
Custom audio input |
| WAV | audio/wav |
Custom audio input |
Uploading Files
TypeScript
import fs from "fs";
async function uploadFile(filePath: string, contentType: string): Promise<string> {
// 1. Get upload URL
const { url, asset_id } = await getUploadUrl(contentType);
// 2. Read file
const fileBuffer = fs.readFileSync(filePath);
// 3. Upload to presigned URL
const uploadResponse = await fetch(url, {
method: "PUT",
headers: {
"Content-Type": contentType,
},
body: fileBuffer,
});
if (!uploadResponse.ok) {
throw new Error(`Upload failed: ${uploadResponse.status}`);
}
return asset_id;
}
// Usage
const imageAssetId = await uploadFile("./background.jpg", "image/jpeg");
console.log(`Uploaded image asset: ${imageAssetId}`);
TypeScript (with streams for large files)
import fs from "fs";
import { stat } from "fs/promises";
async function uploadLargeFile(filePath: string, contentType: string): Promise<string> {
const { url, asset_id } = await getUploadUrl(contentType);
const fileStats = await stat(filePath);
const fileStream = fs.createReadStream(filePath);
const uploadResponse = await fetch(url, {
method: "PUT",
headers: {
"Content-Type": contentType,
"Content-Length": fileStats.size.toString(),
},
body: fileStream as any,
// @ts-ignore - duplex is needed for streaming
duplex: "half",
});
if (!uploadResponse.ok) {
throw new Error(`Upload failed: ${uploadResponse.status}`);
}
return asset_id;
}
Python
import requests
def upload_file(file_path: str, content_type: str) -> str:
# 1. Get upload URL
upload_data = get_upload_url(content_type)
url = upload_data["url"]
asset_id = upload_data["asset_id"]
# 2. Upload file
with open(file_path, "rb") as f:
response = requests.put(
url,
headers={"Content-Type": content_type},
data=f
)
if not response.ok:
raise Exception(f"Upload failed: {response.status_code}")
return asset_id
# Usage
image_asset_id = upload_file("./background.jpg", "image/jpeg")
print(f"Uploaded image asset: {image_asset_id}")
Uploading from URL
If your asset is already hosted online:
async function uploadFromUrl(sourceUrl: string, contentType: string): Promise<string> {
// 1. Download the file
const sourceResponse = await fetch(sourceUrl);
const buffer = await sourceResponse.arrayBuffer();
// 2. Get HeyGen upload URL
const { url, asset_id } = await getUploadUrl(contentType);
// 3. Upload to HeyGen
await fetch(url, {
method: "PUT",
headers: { "Content-Type": contentType },
body: buffer,
});
return asset_id;
}
Using Uploaded Assets
As Background Image
const videoConfig = {
video_inputs: [
{
character: {
type: "avatar",
avatar_id: "josh_lite3_20230714",
avatar_style: "normal",
},
voice: {
type: "text",
input_text: "Hello, this is a video with a custom background!",
voice_id: "1bd001e7e50f421d891986aad5158bc8",
},
background: {
type: "image",
url: `https://files.heygen.ai/asset/${imageAssetId}`,
},
},
],
};
As Talking Photo Source
const talkingPhotoConfig = {
video_inputs: [
{
character: {
type: "talking_photo",
talking_photo_id: photoAssetId,
},
voice: {
type: "text",
input_text: "Hello from my talking photo!",
voice_id: "1bd001e7e50f421d891986aad5158bc8",
},
},
],
};
As Audio Input
const audioConfig = {
video_inputs: [
{
character: {
type: "avatar",
avatar_id: "josh_lite3_20230714",
avatar_style: "normal",
},
voice: {
type: "audio",
audio_url: `https://files.heygen.ai/asset/${audioAssetId}`,
},
},
],
};
Complete Upload Workflow
async function createVideoWithCustomBackground(
backgroundPath: string,
script: string
): Promise<string> {
// 1. Upload background
console.log("Uploading background...");
const backgroundId = await uploadFile(backgroundPath, "image/jpeg");
// 2. Create video config
const config = {
video_inputs: [
{
character: {
type: "avatar",
avatar_id: "josh_lite3_20230714",
avatar_style: "normal",
},
voice: {
type: "text",
input_text: script,
voice_id: "1bd001e7e50f421d891986aad5158bc8",
},
background: {
type: "image",
url: `https://files.heygen.ai/asset/${backgroundId}`,
},
},
],
dimension: { width: 1920, height: 1080 },
};
// 3. Generate video
console.log("Generating video...");
const response = await fetch("https://api.heygen.com/v2/video/generate", {
method: "POST",
headers: {
"X-Api-Key": process.env.HEYGEN_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify(config),
});
const { data } = await response.json();
return data.video_id;
}
Asset Limitations
- File size: Varies by asset type (typically 10-100MB max)
- Image dimensions: Recommended to match video dimensions
- Audio duration: Should match expected video length
- Retention: Assets may be deleted after a period of inactivity
Best Practices
- Optimize images - Resize to match video dimensions before uploading
- Use appropriate formats - JPEG for photos, PNG for graphics with transparency
- Validate before upload - Check file type and size locally first
- Handle upload errors - Implement retry logic for failed uploads
- Cache asset IDs - Reuse assets across multiple video generations