If you're using Jellyfin the open-source media server you may have come across this annoying issue: some .mp4
files just won’t play, even though they open fine in VLC or other players. This is typically due to codec incompatibilities or unusual encoding parameters that Jellyfin’s media engine can't handle well.
I recently faced this with a batch of .mp4
files. Instead of manually checking and re-encoding them one-by-one, I created a simple Bash script using ffmpeg
to batch re-encode all MP4 files from a directory while preserving the original folder structure.
Below is the script and a walk through of how it works.
🔧 The Script: Re-encode MP4s for Jellyfin Compatibility
#!/bin/bash
# Input and output directories
INPUT_DIR="/home/user/video_origin"
OUTPUT_DIR="/home/user/video"
# Create output directory if it doesn't exist
mkdir -p "$OUTPUT_DIR"
echo "🔁 Starting MP4 re-encoding..."
echo "Input: $INPUT_DIR"
echo "Output: $OUTPUT_DIR"
# Find and re-encode all .mp4 files
find "$INPUT_DIR" -type f -iname "*.mp4" | while read -r FILE; do
REL_PATH="${FILE#$INPUT_DIR/}"
OUTPUT_FILE="$OUTPUT_DIR/$REL_PATH"
OUTPUT_DIR_PATH=$(dirname "$OUTPUT_FILE")
# Skip if file already exists
if [[ -f "$OUTPUT_FILE" ]]; then
echo "⏭️ Skipping (already exists): $REL_PATH"
continue
fi
mkdir -p "$OUTPUT_DIR_PATH"
echo "🎞️ Encoding: $REL_PATH"
# FFmpeg encoding: video (H.264) + audio (AAC)
ffmpeg -nostdin -y -i "$FILE" \
-c:v libx264 -preset veryfast -crf 23 \
-c:a aac -b:a 192k \
"$OUTPUT_FILE"
echo "✅ Done: $REL_PATH"
done
echo "🎉 All MP4 files have been re-encoded and saved to: $OUTPUT_DIR"
🐧 Platform Compatibility
⚠️ This script works on Linux or Unix-like systems (e.g., Ubuntu, Debian, Fedora, macOS, or Windows with WSL). It uses Bash and common tools like ffmpeg
, find
, and mkdir
.
If you're using Windows without WSL, you can:
Install Git Bash and run the script there (with some path adjustments), or
Use a tool like HandBrake CLI for batch re-encoding.
🧠 Why This Works
H.264 for video (
libx264
) and AAC for audio are widely supported by Jellyfin’s default playback engine and most devices.The script keeps original directory structures intact, which is handy if you organize by folders or genres.
It skips already-processed files, saving time on reruns.
-crf 23
withveryfast
preset gives a balance between size and quality (tweakable if needed).
⚡ Prerequisites
Make sure you have:
ffmpeg
installed (sudo apt install ffmpeg
on Debian-based systems)Sufficient disk space for the re-encoded copies
Executed this script in a safe place (so your originals remain untouched)
🚀 Running the Script
Update the paths in
INPUT_DIR
andOUTPUT_DIR
.Save the script as
reencode_mp4s.sh
.Make it executable:
chmod +x reencode_mp4s.sh
4. Run it:
./reencode_mp4s.sh
✅ Result
After running the script, all your .mp4
videos will be re-encoded into a format that Jellyfin can stream smoothly—no playback errors, no surprises.
📝 Final Notes
If you want smaller file sizes, increase
-crf
(e.g., to 28); lower values improve quality but increase size.You can also customize it to handle
.mkv
or.avi
by changing the file extension match infind
.