affaan-m/ECC · error · ValueError

At least one video is required

Error message

At least one video is required

What it means

export_draft in capcut.py validates its inputs before building the CapCut draft: an empty files list means the timeline would have no video material, which the draft format cannot represent usefully.

Solutions

  1. Pass at least one existing video path in the files list
  2. Verify your concat file contains 'file <path>' lines if using read_concat
  3. Check that the glob/directory you sourced the list from actually contains videos (print len(files) before calling)
  4. Fix the working-directory or extension filter that emptied the list

Example fix

// before
files = read_concat('concat.txt')  # only comments inside
export_draft(files, name='edit')

// after
files = read_concat('concat.txt')
assert files, 'concat file produced no entries'
export_draft(files, name='edit')
Defensive patterns

Strategy: validation

Validate before calling

files = read_concat('concat.txt')
if not files:
    raise SystemExit('no video entries found; concat file is empty or comment-only')

Type guard

def has_videos(files):
    return bool(files) and all(Path(f).is_file() for f in files)

Try / catch

try:
    export_draft(files, name=name)
except ValueError as e:
    if 'At least one video' in str(e):
        sys.exit('concat manifest or glob produced no videos')

Prevention

When it happens

Trigger: Calling export_draft(files=[], ...) or passing a files list that ended up empty, e.g. because read_concat returned no 'file' lines from an empty or all-comment concat file.

Common situations: Concat file with only comments/blank lines; a glob like glob('*.mp4') matching nothing in the wrong working directory; upstream filtering removing all files before the call.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/08eee5b84c5759f8. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/media/capcut.py:63

    files,
    drafts,
    name,
    width=1920,
    height=1080,
    fps=30,
    overwrite=False,
    cc=None,
    probe=duration_of,
):
    geometry(width, height, fps)
    if overwrite:
        raise ValueError("CapCut draft replacement is unsafe; choose a new name")
    if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9_. -]{0,99}", name) or name.endswith(
        "."
    ):
        raise ValueError("Draft name must be a plain file name")
    if not files:
        raise ValueError("At least one video is required")
    prepared = []
    for filename in files:
        path = Path(filename).resolve(strict=True)
        duration = probe(path)
        if not math.isfinite(duration) or duration <= 0:
            raise ValueError(f"Invalid media duration: {path.name}")
        prepared.append((str(path), duration))
    if cc is None:
        import pycapcut as cc
    folder = cc.DraftFolder(str(drafts))
    script = folder.create_draft(name, width, height, fps=fps, allow_replace=False)
    script.add_track(cc.TrackType.video)
    elapsed = 0
    for filename, duration in prepared:
        script.add_segment(
            cc.VideoSegment(filename, cc.trange(f"{elapsed:.6f}s", f"{duration:.6f}s"))
        )
        elapsed += duration

View on GitHub (pinned to 8321021c54)