AI

Building a Repeatable AI Video Testing Workflow with Python and Seedance 2.5

·
5 min read
·
Human-written

AI tooling disclosure

The author reports no meaningful generative-AI assistance.

Building a Repeatable AI Video Testing Workflow with Python and Seedance 2.5

The first AI-generated video is rarely the difficult part. The trouble starts when you need to improve it.

A camera movement looks right, but the subject changes shape. The next attempt fixes the subject but introduces different lighting. After several generations, the output folder contains a dozen clips, and nobody remembers which reference image produced the most promising one.

This is partly a generation problem, but it is also a documentation problem.

Tools such as Seedance 2.5 support video creation from text, images, and reference-guided inputs. Those options are useful for creative experimentation, but they also introduce more variables to track.

A small Python-based experiment log can make that process easier to manage.

1. Start with a Simple Experiment Record

Every generation should answer a specific question.

For example:

  • Does adding an image reference improve composition?

  • Does a slower camera instruction produce more suitable motion?

  • Does changing the background affect the subject's appearance?

Instead of naming outputs final_v2_new.mp4, assign each experiment a unique ID.

A useful record includes:

  • Experiment ID and timestamp

  • Model or service name

  • Prompt and reference files

  • Reference file hashes

  • Output filename

  • Review status and notes

The goal is traceability, not guaranteed reproducibility. AI models can produce different results from similar inputs, even when prompts and references remain unchanged.

2. Organize the Project

Start with a small directory structure:

video-project/
├── references/
│   └── product.png
├── prompts/
│   └── product_intro.txt
├── outputs/
├── experiments.jsonl
└── track.py

The references directory contains approved source assets. Prompts are stored separately, and generated clips go into outputs.

The JSONL file acts as a lightweight experiment history. Each line contains one complete JSON record.

3. Build a Python Experiment Tracker

The following script uses only Python's standard library.

It supports three operations:

  1. Create an experiment record.

  2. Attach a generated output file.

  3. Record a review decision.

Save it as track.py.

import argparse
import hashlib
import json
from datetime import datetime, timezone
from pathlib import Path
from uuid import uuid4

LOG = Path("experiments.jsonl")


def sha256(path):
    digest = hashlib.sha256()
    with open(path, "rb") as file:
        for chunk in iter(lambda: file.read(65536), b""):
            digest.update(chunk)
    return digest.hexdigest()


def load_records():
    if not LOG.exists():
        return []

    with LOG.open(encoding="utf-8") as file:
        return [json.loads(line) for line in file if line.strip()]


def save_records(records):
    with LOG.open("w", encoding="utf-8") as file:
        for record in records:
            file.write(json.dumps(record, ensure_ascii=False) + "\n")


def create(prompt_file, model, references):
    prompt_path = Path(prompt_file)
    prompt = prompt_path.read_text(encoding="utf-8")

    assets = [
        {"path": str(path), "sha256": sha256(path)}
        for path in references
    ]

    record = {
        "id": uuid4().hex[:12],
        "created_at": datetime.now(timezone.utc).isoformat(),
        "model": model,
        "prompt": prompt,
        "references": assets,
        "output": None,
        "status": "pending",
        "review_notes": ""
    }

    records = load_records()
    records.append(record)
    save_records(records)

    print(record["id"])


def update(experiment_id, output=None, status=None, notes=None):
    records = load_records()

    for record in records:
        if record["id"] == experiment_id:
            if output is not None:
                output_path = Path(output)
                record["output"] = {
                    "path": str(output_path),
                    "sha256": sha256(output_path)
                }

            if status is not None:
                record["status"] = status

            if notes is not None:
                record["review_notes"] = notes

            save_records(records)
            print("Updated:", experiment_id)
            return

    raise ValueError(f"Experiment not found: {experiment_id}")


parser = argparse.ArgumentParser()
sub = parser.add_subparsers(dest="command", required=True)

new = sub.add_parser("new")
new.add_argument("--prompt", required=True)
new.add_argument("--model", required=True)
new.add_argument("--references", nargs="*", default=[])

review = sub.add_parser("update")
review.add_argument("--id", required=True)
review.add_argument("--output")
review.add_argument(
    "--status",
    choices=["pending", "review", "approved", "rejected"]
)
review.add_argument("--notes")

args = parser.parse_args()

if args.command == "new":
    create(args.prompt, args.model, args.references)
else:
    update(args.id, args.output, args.status, args.notes)

This script records experiments locally. It does not generate videos or call an external API.

It assumes a single user updates the log at a time. For concurrent workflows, a database such as SQLite would be more appropriate.

4. Run a Small Test

First, create a prompt file named prompts/product_intro.txt:

A minimalist desk lamp on a wooden table,
warm evening lighting, slow camera push-in,
stable product composition, subtle background movement.

Place an image you have permission to use at references/product.png.

Then create an experiment:

python track.py new \
  --prompt prompts/product_intro.txt \
  --model "Seedance 2.5" \
  --references references/product.png

The script prints an experiment ID, such as:

a82f13c9d701

Use that ID for the following steps. Your actual ID will be different.

Generate the video using the selected service and save the result in the outputs directory.

Then attach the output:

python track.py update \
  --id a82f13c9d701 \
  --output outputs/exp_001.mp4 \
  --status review

After reviewing the clip, record the decision:

python track.py update \
  --id a82f13c9d701 \
  --status rejected \
  --notes "Camera moves too quickly; composition is acceptable."

The experiment now has a prompt, reference hash, output hash, and review decision.

The ID and filenames above are illustrative. They are not results from an actual Seedance 2.5 generation.

5. Compare Inputs Without Changing Everything

Consider a small test involving three planned generations.

Test

Input

Question

A

Text prompt only

Is the composition suitable?

B

Same prompt + product image

Does the reference help preserve the intended appearance?

C

Same references + revised camera instruction

Is the camera movement closer to the brief?

This is a possible workflow for evaluating Seedance 2.5, not a claim about measured model performance.

The important rule is to change as few variables as practical between experiments.

If the image, prompt, lighting, and camera instructions all change together, it becomes difficult to understand which modification influenced the result.

For each test, keep a short note explaining what changed and why.

6. Review the Output, Not Just the Prompt

A technically successful generation is not necessarily a usable video.

Before approving a clip, check:

  • Subject and object consistency

  • Product shape and color

  • Text and logo accuracy

  • Camera movement and pacing

  • Unexpected visual artifacts

  • Continuity between frames

  • Rights and permissions for reference materials

For commercial content, factual information such as prices, specifications, and dates must be verified independently.

Reference images are guidance, not a guarantee of pixel-perfect reproduction.

Only upload materials that you are authorized to use. Confidential assets, internal screenshots, identifiable real people, and copyrighted materials require appropriate permissions and compliance with the service's current policies.

7. Understand the Limits of Reproducibility

Hashing a reference file proves which file was recorded, but it does not guarantee that the same prompt will generate the same video.

Model updates, randomness, hidden parameters, and service configuration can all affect the output.

For better traceability, record any available generation settings, model versions, and job identifiers.

The tracker above is deliberately minimal. It does not capture these automatically, and its JSONL storage is best suited to small, single-user experiments.

For larger teams, the next improvements would be structured settings, atomic writes, concurrent access control, and a searchable review interface.

Conclusion

AI video experimentation becomes difficult to manage when prompts, references, and generated clips accumulate without a clear history.

A lightweight tracking workflow helps answer three practical questions:

What inputs produced this clip?

What changed between versions?

Why was one result accepted or rejected?

Seedance 2.5 is one example of a reference-guided AI video workflow where these questions matter.

The goal is not to make generation perfectly reproducible. It is to make creative decisions easier to trace, compare, and improve.

Sometimes the most useful upgrade to an AI video workflow is not another prompt. It is a better record of the prompts already tested.

Comments(0)

Join the discussion by logging into your account.

No comments yet. Be the first to comment!

sarah wilson

Passionate developer sharing knowledge about modern web technologies and best practices.

Subscribe to sarah wilson's Newsletter

Direct email dispatches when new stories are published. Zero algorithms.