
Want to stream your own videos using **M3U8**? Maybe for a personal website, online course, or small streaming service? This guide will walk you through the entire process, from encoding videos to hosting playlists.
What You'll Need
Before starting, gather these tools:
- FFmpeg - For video encoding and segmentation (free)
- A web server - Apache, Nginx, or cloud hosting
- Your source video - MP4, MOV, AVI, whatever you have
- Text editor - Any will do
- Basic command line knowledge - We'll use terminal commands
Step 1: Install FFmpeg
Windows:
Download from ffmpeg.org. Extract to a folder like C:\ffmpeg. Add to system PATH for easy access.
Mac:
brew install ffmpeg
Linux (Ubuntu/Debian):
sudo apt update
sudo apt install ffmpeg
Verify installation:
ffmpeg -version
Step 2: Basic Video Segmentation
Let's start simple - convert one video to M3U8 format.
Basic command:
ffmpeg -i input.mp4 \
-codec: copy \
-start_number 0 \
-hls_time 10 \
-hls_list_size 0 \
-f hls \
output.m3u8
This creates:
output.m3u8- The playlist fileoutput0.ts, output1.ts, ...- Video segments
Each segment is 10 seconds (controlled by -hls_time 10).
Step 3: Creating Multiple Quality Levels
For adaptive streaming, encode multiple quality versions.
Create 1080p version:
ffmpeg -i input.mp4 \
-vf scale=1920:1080 \
-c:v libx264 -b:v 5000k \
-c:a aac -b:a 128k \
-hls_time 6 \
-hls_playlist_type vod \
-hls_segment_filename "1080p_%03d.ts" \
1080p.m3u8
Create 720p version:
ffmpeg -i input.mp4 \
-vf scale=1280:720 \
-c:v libx264 -b:v 2500k \
-c:a aac -b:a 128k \
-hls_time 6 \
-hls_playlist_type vod \
-hls_segment_filename "720p_%03d.ts" \
720p.m3u8
Create 480p version:
ffmpeg -i input.mp4 \
-vf scale=854:480 \
-c:v libx264 -b:v 1000k \
-c:a aac -b:a 96k \
-hls_time 6 \
-hls_playlist_type vod \
-hls_segment_filename "480p_%03d.ts" \
480p.m3u8
Step 4: Create Master Playlist
Now create a master playlist that lists all quality levels.
Create file master.m3u8:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080
1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720
720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=854x480
480p.m3u8
Players will load this master playlist first, then choose appropriate quality based on bandwidth.
Step 5: Organize Your Files
Keep things tidy:
video/
master.m3u8
1080p.m3u8
1080p_000.ts
1080p_001.ts
...
720p.m3u8
720p_000.ts
720p_001.ts
...
480p.m3u8
480p_000.ts
480p_001.ts
...
Or organize by quality:
video/
master.m3u8
1080p/
index.m3u8
segment_000.ts
segment_001.ts
720p/
index.m3u8
segment_000.ts
segment_001.ts
Step 6: Set Up Web Server
Simple Python Server (for testing):
Navigate to your video folder and run:
python3 -m http.server 8000
Access at http://localhost:8000/master.m3u8
Nginx Configuration:
For production, configure Nginx properly:
server {
listen 80;
server_name your-domain.com;
location /videos/ {
alias /path/to/videos/;
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
add_header Cache-Control "public, max-age=3600";
add_header Access-Control-Allow-Origin "*";
}
}
Step 7: Enable CORS
For web playback, enable Cross-Origin Resource Sharing.
Apache (.htaccess):
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, HEAD"
Nginx:
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, HEAD";
Step 8: Test Your Playlist
Test with multiple methods:
VLC Player:
vlc http://localhost:8000/master.m3u8
Browser:
Use our M3U8 player to test your playlist URL.
Command line validation:
ffmpeg -v error -i master.m3u8 -f null -
No output means no errors!
Step 9: Add Encryption (Optional)
Protect your content with AES-128 encryption.
Generate encryption key:
openssl rand 16 > encryption.key
Create key info file (enc.keyinfo):
http://your-domain.com/encryption.key
encryption.key
$(openssl rand -hex 16)
Encode with encryption:
ffmpeg -i input.mp4 \
-hls_key_info_file enc.keyinfo \
-hls_time 6 \
-hls_playlist_type vod \
output.m3u8
The playlist will include encryption tags. Players fetch the key automatically.
Step 10: CDN Distribution
For serious traffic, use a CDN.
Popular CDN Options:
- Cloudflare - Good free tier
- AWS CloudFront - Integrates with S3
- Fastly - High performance
Setup process (general):
- Upload videos to your origin server or S3
- Configure CDN to cache .m3u8 and .ts files
- Set appropriate cache TTLs
- Update playlist URLs to use CDN domain
Batch Processing Multiple Videos
Create a script to process many videos:
#!/bin/bash
for video in *.mp4; do
name="${video%.mp4}"
# Create output directory
mkdir -p "$name"
# Generate 1080p
ffmpeg -i "$video" \
-vf scale=1920:1080 \
-c:v libx264 -b:v 5000k \
-c:a aac -b:a 128k \
-hls_time 6 \
-hls_segment_filename "$name/1080p_%03d.ts" \
"$name/1080p.m3u8"
# Generate 720p
ffmpeg -i "$video" \
-vf scale=1280:720 \
-c:v libx264 -b:v 2500k \
-c:a aac -b:a 128k \
-hls_time 6 \
-hls_segment_filename "$name/720p_%03d.ts" \
"$name/720p.m3u8"
# Create master playlist
cat > "$name/master.m3u8" << EOF
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080
1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720
720p.m3u8
EOF
echo "Processed $video"
done
Optimization Tips
Choose right segment length:
- 6-10 seconds for VOD (good balance)
- 2-4 seconds for low-latency live
- Longer segments = less overhead, slower adaptation
Encoding settings:
- Use H.264 for maximum compatibility
- H.265 for better compression (check device support)
- AAC audio codec universally supported
Bitrate ladder:
Offer quality levels spaced 2-3x apart in bitrate. For example: 500k, 1500k, 4500k.
Monitoring and Analytics
Track playlist usage:
Server logs:
Analyze access logs to see popular videos, quality selection patterns, geographic distribution.
Player analytics:
Implement JavaScript tracking in your player to gather playback metrics.
Common Pitfalls to Avoid
- Don't use spaces in filenames - causes URL encoding issues
- Always test different quality levels individually
- Set correct MIME types on server
- Include CORS headers from the start
- Keep segment duration consistent within a playlist
Scaling Considerations
As your service grows:
Storage:
Multiple quality levels multiply storage needs. Budget accordingly.
Bandwidth:
Popular videos consume significant bandwidth. CDN becomes essential.
Encoding:
Consider cloud transcoding services (AWS MediaConvert, Zencoder) for large volumes.
Alternative: Simpler Solutions
If this seems complex, alternatives exist:
For simple use cases, platforms like Vimeo or YouTube handle all the technical details. You just upload.
If you need more control but less complexity, consider video hosting services like Mux or JW Player. They provide APIs for uploading and streaming.
Building your own infrastructure makes sense when you need full control, have specific requirements, or want to minimize ongoing costs.
Conclusion
Creating M3U8 playlists isn't as daunting as it first appears. FFmpeg does the heavy lifting. A basic web server hosts the files. Add a CDN for scale.
Start small - single quality, no encryption. Get that working first. Then add complexity as needed.
Once set up, you have full control over your video delivery. No platform restrictions, no unexpected fees, complete ownership.
If you want to test M3U8 playback without building infrastructure, try our online player. And if you need to go the other direction - converting M3U8 back to MP4 - our converter handles that easily.
Back to Blog