Home / Guides / Bulk audio to video

How to convert an audio library to video in bulk

Converting one track is a one-line command. Converting two hundred consistently is a different problem โ€” and the part that goes wrong is never the encoding.

Updated 18 August 2026 ยท 7 min read

If you have a catalogue of audio you want on YouTube, Reels, TikTok and Shorts, you need a video per track, usually in two shapes, all looking like they came from the same place. Doing that by hand is where people give up. Here is how to script it properly.

The simple loop

The naive version works and is worth starting from:

for f in audio/*.mp3; do
  name=$(basename "$f" .mp3)
  ffmpeg -loop 1 -i cover.jpg -i "$f" \
    -c:v libx264 -tune stillimage -pix_fmt yuv420p \
    -c:a aac -b:a 320k -shortest -movflags +faststart \
    "out/${name}.mp4"
done

Run that overnight on a hundred tracks and you will have a hundred videos. You will also discover the five things below, which is why this guide exists.

The five things that go wrong at scale

1. It re-renders everything, every time

Add ten new tracks and the loop redoes all hundred. Skip files that already have output:

[ -f "out/${name}.mp4" ] && continue

2. One bad file kills the run

A corrupt MP3 at track 40 stops everything, and you find out in the morning. Let each track fail on its own and keep going, and log what failed:

if ! ffmpeg -v error -i "$f" ... "out/${name}.mp4"; then
  echo "FAILED: $f" >> failures.log
  continue
fi

3. Filenames break things

Spaces, apostrophes, em-dashes and non-ASCII characters in track titles will each break something downstream โ€” an upload form, a CSV, a scheduler. Decide on a slug format early and stick to it:

slug=$(echo "$name" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-|-$//g')

4. You need two aspect ratios, not one

YouTube and Facebook want 16:9. Reels, TikTok, Shorts and Pinterest want 9:16. The same file cannot serve both โ€” a horizontal video on Reels gets letterboxed into a strip and performs badly. Render both from the same source in the same pass, into separate folders, so they stay in sync.

5. Silent truncation

The worst failure, because it looks like success. A wrong -shortest interaction or a malformed input can produce a valid MP4 that stops after ten seconds. Verify every output before you trust it:

ffprobe -v error -show_entries format=duration \
  -of csv=p=0 "out/${name}.mp4"

Compare that number to the source audio's duration. If it is short, the render failed regardless of what the exit code said.

Check every file before uploading. Distribution platforms reject undersized or truncated files, and by then you have already spent the time. A verification pass over the whole output folder costs seconds and saves a rejected batch.

Making them look like one release

Consistency is what makes a catalogue look professional rather than assembled. In practice that means, for every track:

-af loudnorm=I=-14:TP=-1.5:LRA=11

-14 LUFS is what YouTube, Spotify and most platforms normalise to anyway; matching it means they leave your audio alone.

How long it takes

Approach100 tracks, both ratios
By hand in an editorDays
A basic loop, then fixing the failuresAn overnight run plus a day of cleanup
A verified pipeline with resumeOne overnight run, walk away

The pipeline, already built

Social Video Factory takes a folder of audio and background clips and produces finished branded videos in both aspect ratios โ€” logo, QR code, titles from filenames, loudness matched, every output verified. A downloadable Claude skill, one purchase.

See how it works

Related guides