Week 4 of 16

Build: Multi-Platform Comparison

Generate prompts for Kling, Runway, and Veo simultaneously — then compare them side by side

Day 19 60 minutes Build Day

Day 19 of 80

What You'll Build Today

A script called prompt_compare.py that:

New Concepts in This Build

Key Concept: Functions (Preview)

Yesterday, your API call code sat directly in the script. Today you wrap it in a function — a named block of code you can call multiple times with different arguments.

Instead of copy-pasting the API call three times (once for Kling, once for Runway, once for Veo), you write it once as generate_prompt(shot, platform) and call it in a loop. If you ever need to change the system prompt or the model, you change it in one place — not three.

This is a preview of Week 5's main topic. Don't worry about mastering functions today — just see how they make repetitive work disappear.

Key Concept: Collecting Results in a Dictionary

You'll use results = {} as a "collection box" — loop through the platforms, generate a prompt for each one, and store it: results[platform] = generated_text. At the end of the loop, results is a dictionary mapping platform names to their generated prompts. Then you loop through it again to display everything.

This separation — first collect, then display — is a clean pattern you'll use constantly. Don't mix collecting and printing in the same loop.

The Full Script

Create prompt_compare.py in the same folder as your other scripts.

prompt_compare.py — imports and setup Python
import anthropic
import json
from dotenv import load_dotenv

load_dotenv()
client = anthropic.Anthropic()

PLATFORMS = ["Kling", "Runway", "Veo"]
PLATFORMS is a constant — by convention, constants are written in ALL_CAPS. This tells anyone reading your code "this value isn't meant to change." Defining it at the top means you can add or remove platforms in one place if needed. If you later want to include Pika or Sora, just add it to this list — nothing else in the script needs to change.
prompt_compare.py — the helper function Python
def generate_prompt(shot, platform):
    """Call Claude to generate an AI video prompt for the given platform."""
    message = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=300,
        system="You are an expert AI video prompt engineer who writes concise, "
               "production-ready prompts for AI video generation platforms.",
        messages=[{
            "role": "user",
            "content": f"""Write a production-ready {platform} prompt for this shot:
{shot}

Requirements:
- Include camera movement, lighting, mood, and style details
- Match {platform}'s prompt style and strengths
- Keep it under 100 words
- Return ONLY the prompt text, nothing else"""
        }]
    )
    return message.content[0].text
This is the same API call from Day 18 — wrapped in a function.
  • def generate_prompt(shot, platform): — defines the function. shot and platform are parameters (inputs).
  • The triple-quoted string on line 2 is a docstring — a description of what the function does. Not required, but professional.
  • return message.content[0].text — the function gives back the generated text to whoever called it. Without return, the result would be lost.
Now you can write generate_prompt("wide aerial shot", "Kling") anywhere and get a generated prompt back. No copy-paste needed.
prompt_compare.py — collecting results Python
print("=== DVP Multi-Platform Comparison ===\n")
shot = input("Describe your shot: ")
print()

results = {}

for platform in PLATFORMS:
    print(f"Generating {platform}...")
    try:
        results[platform] = generate_prompt(shot, platform)
    except Exception as e:
        results[platform] = f"[Error: {e}]"
The collection loop:
  • results = {} starts as an empty dictionary — the collection box.
  • The for loop runs three times, once per platform. Each iteration calls generate_prompt() and stores the result: results["Kling"] = "...", results["Runway"] = "...", etc.
  • except Exception as e catches any error for this platform and stores an error message in results instead of crashing the whole script. In production you'd be more specific (catching anthropic.APIError), but for a learning project this broad catch keeps things running. Note the tradeoff.
By the time the loop finishes, results has all three prompts (or error messages) ready to display.
prompt_compare.py — display comparison Python
print("\n" + "=" * 50)
print("COMPARISON RESULTS")
print("=" * 50)

for platform, prompt in results.items():
    print(f"\n[{platform}]")
    print(prompt)
    print("-" * 40)
Display loop: results.items() gives you both the key and value in each iteration — platform is the key ("Kling"), prompt is the value (the generated text). "=" * 50 creates a separator line 50 characters wide — string multiplication. Clean, no imports needed.
prompt_compare.py — selective save Python
print("\nWhich to save? (all / none / comma-separated list like: kling,veo)")
choice = input("Save: ").strip().lower()

if choice == "none" or choice == "":
    print("Nothing saved.")
else:
    if choice == "all":
        to_save = [p.lower() for p in PLATFORMS]
    else:
        to_save = [c.strip().lower() for c in choice.split(",")]

    try:
        with open("prompts.json", "r") as f:
            prompts = json.load(f)
    except FileNotFoundError:
        prompts = []

    saved_count = 0
    for platform, prompt in results.items():
        if platform.lower() in to_save:
            prompts.append({
                "platform": platform,
                "shot": shot,
                "prompt": prompt
            })
            saved_count += 1

    with open("prompts.json", "w") as f:
        json.dump(prompts, f, indent=2)

    print(f"Saved {saved_count} prompts. Library now has {len(prompts)} total.")
Comma-separated input parsing: [c.strip().lower() for c in choice.split(",")] is a list comprehension that splits "kling, veo" on commas, strips whitespace from each piece, and converts to lowercase — all in one line. This gives you ["kling", "veo"] regardless of how the user typed it. Then you compare platform.lower() in to_save to decide what to save.

Run It

Terminal
$ python prompt_compare.py
=== DVP Multi-Platform Comparison ===

Describe your shot: handheld tracking shot following a golfer walking to the green

Generating Kling...
Generating Runway...
Generating Veo...

==================================================
COMPARISON RESULTS
==================================================

[Kling]
Handheld tracking shot follows a golfer walking purposefully toward the green.
Warm afternoon sun creates long shadows across manicured turf. Shallow focus,
slight camera shake, intimate and focused energy. Cinematic 4K.
----------------------------------------

[Runway]
Documentary-style tracking shot. Camera follows golfer at eye level, slight
handheld movement. Golden hour lighting, rich greens and warm tones. Focused
and deliberate movement. Photorealistic, 4K, cinematic.
----------------------------------------

[Veo]
Smooth handheld tracking shot behind golfer approaching putting green. Late
afternoon light, vivid green grass, realistic textures. Camera slightly shakes
with footsteps. Naturalistic color grading, cinematic feel.
----------------------------------------

Which to save? (all / none / comma-separated list like: kling,veo)
Save: kling,runway
Saved 2 prompts. Library now has 5 total.
Compare the Outputs

Notice how each platform generates slightly different vocabulary and emphasis. This is intentional — Claude knows each platform has different strengths. Kling tends toward cinematic language; Runway toward documentary realism; Veo toward naturalistic detail. This comparison is genuinely useful when you're choosing a platform for a specific shot.

End of Day Checklist

Tomorrow

Week 4 Review and Milestone. You'll consolidate everything — APIs, the Claude SDK, token-aware prompt engineering, and error handling. Then a vocabulary test and self-check to lock it all in before Week 5.