Skip to main content
View as Markdown

Complete Server-Side Workflow - Avatar Videos

Complete Server-Side Workflow​

This example creates an avatar video from scratch using only the server-side API:

AVATAR_API="https://video-avatar.nvp1.ovp.kaltura.com/api/v1"

# 1. Create an avatar with a color background
AVATAR=$(curl -s -X POST "$AVATAR_API/avatar/upsert" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d '{
"templateId": "jane",
"background": { "type": "color", "color": "#CEEEDB" }
}')
AVATAR_ID=$(echo "$AVATAR" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

# 2. Create a video project with scenes
VIDEO=$(curl -s -X POST "$AVATAR_API/video/add" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"Product Update\",
\"avatarId\": \"$AVATAR_ID\",
\"scenes\": [
{
\"layoutType\": \"full-screen\",
\"narration\": { \"text\": \"Hello! Today I will walk you through our latest product updates.\" }
},
{
\"layoutType\": \"full-screen\",
\"narration\": { \"text\": \"We have three major features to cover. Let us get started.\" }
}
]
}")
VIDEO_ID=$(echo "$VIDEO" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

# 3. Preview audio for the first scene
curl -s -X POST "$AVATAR_API/video/previewAudio" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$VIDEO_ID\", \"sceneId\": 0}" \
--output scene0_preview.mp3

# 4. Generate the video
curl -s -X POST "$AVATAR_API/video/generate" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$VIDEO_ID\"}"

# 5. Poll until ready
while true; do
RESULT=$(curl -s -X POST "$AVATAR_API/video/get" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$VIDEO_ID\"}")
STATUS=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
echo "Status: $STATUS"
[ "$STATUS" = "ready" ] || [ "$STATUS" = "generate-error" ] && break
sleep 10
done

# 6. Get the generated Kaltura entry ID
ENTRY_ID=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('entryId',''))")
echo "Generated Kaltura entry: $ENTRY_ID"

Manual Storyboard with Multi-Source B-Roll​

When you need precise control over the narrative and which video clips appear in each scene, author the scenes yourself instead of using AI composition (section 7). This approach lets you pick exact source entries, set b-roll start times, and interleave full-screen and b-roll layouts in any order.

The key difference: with AI composition (video/compose), you provide source entries and the AI decides how to structure the narrative and which clips to reference. With a manual storyboard, you write each scene's narration and explicitly assign b-roll entries and timestamps — the output matches your storyboard exactly.

AVATAR_API="https://video-avatar.nvp1.ovp.kaltura.com/api/v1"

# 1. Create (or reuse) an avatar
AVATAR=$(curl -s -X POST "$AVATAR_API/avatar/upsert" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d '{
"templateId": "jane",
"background": { "type": "color", "color": "#1A1A2E" }
}')
AVATAR_ID=$(echo "$AVATAR" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

# 2. Create a video with manually authored scenes mixing two source entries
# - Scenes 0 and 5: full-screen (avatar on background, no b-roll)
# - Scenes 1 and 4: b-roll from $SOURCE_ENTRY_A (e.g., a keynote recording)
# - Scenes 2 and 3: b-roll from $SOURCE_ENTRY_B (e.g., a tutorial)
VIDEO=$(curl -s -X POST "$AVATAR_API/video/add" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"Cloud AI Meets Neural Networks\",
\"avatarId\": \"$AVATAR_ID\",
\"scenes\": [
{
\"layoutType\": \"full-screen\",
\"narration\": { \"text\": \"Welcome to this deep dive into two pillars of modern artificial intelligence. Today we connect the dots between cloud infrastructure powering AI at scale and the neural network architectures that make it all possible.\" }
},
{
\"layoutType\": \"broll\",
\"narration\": { \"text\": \"At AWS re:Invent 2023, Amazon unveiled its vision for generative AI infrastructure. Purpose-built chips like Trainium and Inferentia are redefining how we train and deploy large language models in the cloud.\" },
\"broll\": { \"entryId\": \"$SOURCE_ENTRY_A\", \"startTime\": 30 }
},
{
\"layoutType\": \"broll\",
\"narration\": { \"text\": \"But what exactly are these AI models learning? At their core, neural networks process data through layers of interconnected nodes, each layer extracting increasingly abstract features from raw input.\" },
\"broll\": { \"entryId\": \"$SOURCE_ENTRY_B\", \"startTime\": 10 }
},
{
\"layoutType\": \"broll\",
\"narration\": { \"text\": \"Consider digit recognition. A neural network takes pixel values as input, detects edges and curves in hidden layers, and outputs a prediction. This elegant architecture is the foundation of modern computer vision.\" },
\"broll\": { \"entryId\": \"$SOURCE_ENTRY_B\", \"startTime\": 60 }
},
{
\"layoutType\": \"broll\",
\"narration\": { \"text\": \"Now scale that up to the cloud. Enterprises can run these neural networks across thousands of custom accelerators, making real-time AI inference accessible to any application, anywhere in the world.\" },
\"broll\": { \"entryId\": \"$SOURCE_ENTRY_A\", \"startTime\": 180 }
},
{
\"layoutType\": \"full-screen\",
\"narration\": { \"text\": \"The convergence of scalable cloud infrastructure and intelligent neural architectures is accelerating AI innovation faster than ever. Thank you for watching.\" }
}
]
}")
VIDEO_ID=$(echo "$VIDEO" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

# 3. Preview a b-roll scene's narration audio before committing to generation
curl -s -X POST "$AVATAR_API/video/previewAudio" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$VIDEO_ID\", \"sceneId\": 1}" \
--output scene1_preview.mp3

# 4. Generate — skips compose entirely, goes straight from draft to generating
curl -s -X POST "$AVATAR_API/video/generate" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$VIDEO_ID\"}"

# 5. Poll until ready
while true; do
RESULT=$(curl -s -X POST "$AVATAR_API/video/get" \
-H "Authorization: Bearer $KS" \
-H "Content-Type: application/json" \
-d "{\"id\": \"$VIDEO_ID\"}")
STATUS=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
echo "Status: $STATUS"
[ "$STATUS" = "ready" ] || [ "$STATUS" = "generate-error" ] && break
sleep 10
done

ENTRY_ID=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('entryId',''))")
echo "Generated Kaltura entry: $ENTRY_ID"

When to use each approach:

ApproachWhen to use
Manual storyboard (above)You know exactly what the avatar should say in each scene, which source video clips to show, and at which timestamps. Use for curated presentations, training modules, or any video where the storyboard is predetermined
AI composition (section 7)You have source entries and want the AI to analyze their captions and generate a coherent narrative automatically. Use for quick highlights, summaries, or when you do not have a specific script in mind
HybridUse AI composition to generate a first draft, then call video/update to refine the scenes — rewrite narration text, swap b-roll entries, adjust start times, or reorder scenes before generating