FFmpeg is the essential tool for converting, resizing, and re-encoding video — the foundation behind most self-hosted streaming and media server transcoding operations. This guide covers building a basic transcoding pipeline.
What Transcoding Solves
Different devices and network conditions need different video formats, resolutions, and bitrates — transcoding converts a source video into the appropriate variants for adaptive delivery or device compatibility.
Prerequisites
- Ubuntu 22.04/24.04 VPS with adequate CPU for your expected transcoding load
Step 1 — Install FFmpeg
sudo apt install ffmpeg -y
Step 2 — Basic Format Conversion
ffmpeg -i input.mov -c:v libx264 -c:a aac output.mp4
Step 3 — Resize to a Specific Resolution
ffmpeg -i input.mp4 -vf scale=1280:720 -c:a copy output-720p.mp4
Step 4 — Generate Multiple Quality Levels (For Adaptive Streaming)
ffmpeg -i input.mp4 \
-vf scale=1920:1080 -b:v 5000k output-1080p.mp4 \
-vf scale=1280:720 -b:v 2500k output-720p.mp4 \
-vf scale=854:480 -b:v 1000k output-480p.mp4
Step 5 — Convert to HLS Segments
ffmpeg -i input.mp4 \
-codec: copy \
-start_number 0 \
-hls_time 10 \
-hls_list_size 0 \
-f hls output.m3u8
See How to Set Up HLS Streaming with Nginx for serving these segments to viewers.
Step 6 — Extract a Thumbnail
ffmpeg -i input.mp4 -ss 00:00:05 -vframes 1 thumbnail.jpg
Automating Transcoding with a Watch Folder Script
sudo nano /usr/local/bin/transcode-watch.sh
#!/bin/bash
WATCH_DIR="/var/uploads/raw"
OUTPUT_DIR="/var/uploads/processed"
inotifywait -m -e create "$WATCH_DIR" | while read path action file; do
ffmpeg -i "$WATCH_DIR/$file" -vf scale=1280:720 -c:v libx264 "$OUTPUT_DIR/${file%.*}.mp4"
done
Requires inotify-tools installed; automatically transcodes any new file dropped into the watch directory.
Using Hardware Acceleration (If Available)
ffmpeg -hwaccel cuda -i input.mp4 -c:v h264_nvenc output.mp4
Significantly faster than software encoding if your VPS includes compatible GPU hardware — verify driver/CUDA support is properly installed first.
Monitoring Transcoding Load
FFmpeg transcoding is CPU-intensive — monitor server load during batch operations and consider queuing/limiting concurrent transcoding jobs to avoid overwhelming the server, especially if it's also serving live traffic.
Common Errors
Output video has no audio — verify the audio codec is correctly specified (or using -c:a copy to preserve the original audio stream without re-encoding it).
Transcoding is extremely slow — software encoding at high quality settings is inherently CPU-intensive; consider a faster preset (-preset fast) as a speed/quality trade-off, or hardware acceleration if available.
Continue Reading
- How to Set Up HLS Streaming with Nginx
- How to Install PeerTube (Self-Hosted YouTube Alternative)
- VPS Requirements for Media Streaming Servers
Browse more articles in Media & Streaming Servers.