Batch Transcode Videos with Find, Xargs, and FFmpeg
Transcoding large collections of video files can be automated
efficiently in Unix-like operating systems using a combination of
find, xargs, and ffmpeg. This
guide provides a direct, practical method for locating video files
across nested directories, passing them safely to xargs,
and batch processing them with ffmpeg while handling spaces
in filenames and controlling parallel execution.
The Complete Batch Transcoding Command
Run the following command in your terminal, replacing the directory path, file extension, and ffmpeg encoding parameters to fit your requirements:
find /path/to/videos -type f -name "*.mkv" -print0 | xargs -0 -n 1 -P 2 -I {} bash -c '
input="$1"
output="${input%.*}.mp4"
ffmpeg -nostdin -y -i "$input" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k "$output"
' _ {}Breakdown of the Command
1. Locating Files with
find
/path/to/videos: The target directory wherefindwill search recursively.-type f: Restricts search results exclusively to files, ignoring directories.-name "*.mkv": Filters for files ending with the specified extension. You can match multiple extensions using-name "*.mkv" -o -name "*.mov".-print0: Separates results with a null character (\0) rather than a newline. This ensures file paths containing spaces, single quotes, or newlines are parsed without breaking downstream commands.
2. Managing the Pipeline
with xargs
-0: Instructsxargsto expect null-terminated items, directly matching the-print0flag fromfind.-n 1: Passes one file at a time to the execution command.-P 2: Controls concurrency by setting the maximum number of parallel processes. Adjust this number according to your CPU core count and GPU capabilities. A value of1processes videos sequentially.-I {}: Defines{}as a placeholder for the file path passed to the shell.
3. Execution and
Naming with bash and ffmpeg
bash -c '...' _ {}: Executes a subshell where$1is assigned the current file path represented by{}.output="${input%.*}.mp4": Uses POSIX shell parameter expansion to strip the original file extension and append the new desired extension (.mp4).-nostdin: Preventsffmpegfrom consuming input from standard input, which would otherwise disrupt thexargsexecution loop.-y: Automatically overwrites existing output files with the same name. Remove this flag if you wantffmpegto skip or prompt before overwriting.-c:v libx264 -crf 23 -preset medium: Encodes the video stream to H.264 using standard constant rate factor and speed settings.-c:a aac -b:a 128k: Encodes the audio stream to AAC at a 128 kbps bitrate.
Preserving or Deleting the Original Files
By default, the script creates a new transcoded file in the same
directory alongside the original. If you want to automatically delete
the source file after a successful conversion, append
&& rm "$input" directly after the
ffmpeg command inside the subshell:
find /path/to/videos -type f -name "*.mkv" -print0 | xargs -0 -n 1 -P 2 -I {} bash -c '
input="$1"
output="${input%.*}.mp4"
ffmpeg -nostdin -y -i "$input" -c:v libx264 -crf 23 -c:a aac "$output" && rm "$input"
' _ {}Using && ensures that the original file is only
removed if ffmpeg returns an exit status of 0,
protecting your source media against removal in the event of an encoding
failure.