DEV Community

Claire Hughes
Claire Hughes

Posted on Fully Autonomous

Before You Batch-Cut 100 Videos, Run This FFprobe Preflight

Cutting one video is easy. Cutting a folder full of mixed files is where unexpected edge cases show up.

Imagine a folder with 100 clips: some are vertical, some are horizontal, one is shorter than the requested cut duration, and another has no audio track. Starting the batch without checking the inputs can leave you sorting through confusing outputs later.

Here is a small read-only preflight you can run before a batch job. It does not edit, upload, or split any video.

First, see what FFprobe reports

FFprobe is shipped with FFmpeg. Try this command on one file:

ffprobe -v error -show_entries format=duration:stream=codec_type,codec_name,width,height -of json "input.mp4"
Enter fullscreen mode Exit fullscreen mode

The JSON lets you check three useful things before processing:

  • Duration: Is a source shorter than the segment length you want?
  • Video stream and dimensions: Does the container actually contain a video stream, and what is its resolution?
  • Audio streams: Is there an audio track? A silent video might be intentional, so this is a signal to review, not an automatic error.

A Python preflight for a whole folder

Save this as preflight.py. It reads metadata only and prints one line per file.

from pathlib import Path
import json
import subprocess
import sys

EXTS = {".mp4", ".mov", ".mkv", ".webm"}
folder = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("videos")
clip_seconds = float(sys.argv[2]) if len(sys.argv) > 2 else 20.0

if not folder.is_dir():
    raise SystemExit(f"Folder not found: {folder}")

for video in sorted(folder.iterdir()):
    if not video.is_file() or video.suffix.lower() not in EXTS:
        continue

    command = [
        "ffprobe", "-v", "error", "-show_entries",
        "format=duration:stream=codec_type,codec_name,width,height",
        "-of", "json", str(video),
    ]
    try:
        result = subprocess.run(command, capture_output=True, text=True)
    except FileNotFoundError:
        raise SystemExit("Install FFmpeg/FFprobe and add it to PATH")

    if result.returncode != 0:
        print(f"{video.name}: could not inspect file")
        continue

    try:
        info = json.loads(result.stdout)
    except json.JSONDecodeError:
        print(f"{video.name}: invalid metadata")
        continue

    streams = info.get("streams", [])
    v = next((s for s in streams if s.get("codec_type") == "video"), None)
    has_audio = any(s.get("codec_type") == "audio" for s in streams)
    try:
        duration = float(info.get("format", {}).get("duration"))
    except (TypeError, ValueError):
        duration = None

    if v is None:
        status = "NO VIDEO STREAM"
    elif duration is None:
        status = "UNKNOWN DURATION"
    elif duration < clip_seconds:
        status = "SHORTER THAN TARGET CLIP"
    else:
        status = "CHECK SAMPLE OUTPUT"

    dimensions = f"{v.get('width', '?')}x{v.get('height', '?')}" if v else "?"
    print(f"{video.name} | {duration or '?'}s | {dimensions} | audio={has_audio} | {status}")
Enter fullscreen mode Exit fullscreen mode

Run it in PowerShell or a terminal after installing FFmpeg and Python:

python preflight.py "D:\\Videos" 20
Enter fullscreen mode Exit fullscreen mode

That last number is your intended clip length in seconds. A two-second test file, for example, will be flagged as shorter than a 20-second target.

What this does not prove

Metadata checks do not guarantee that every frame decodes correctly, audio stays synchronized, or the final segment looks right. For that, test a small batch and inspect an early, middle, and final output clip. Also keep a clear way to trace each output back to the source.

A successful progress bar is not the same as a validated result.

One question for other developers

If a job creates 300 clips, which would you prioritize first: faster processing, a contact sheet of thumbnails, or clearer output filenames? I'd be interested in how you review large batches without opening every file.

Context: this standalone example is inspired by workflow questions around ChanPilo, a commercial batch video-processing project. It is not a claim that this example script is included in the current product. This post was prepared with GPT assistance; the FFprobe example was checked on a small synthetic video. No affiliate links.

Top comments (0)