To convert an HEVC MP4 file into an HLS stream using ffmpeg, you must first transcode the video to a widely compatible codec like H.264 and split it into small segments. This process ensures that modern devices with limited HEVC support can play the content smoothly via standard HTTP servers. The following guide details the exact commands and parameters required for this transformation.
Understanding the Conversion Requirements
Why Transcode HEVC?
While HEVC (H.265) offers superior compression efficiency, its support across web browsers and older mobile devices is inconsistent. HLS players often default to expecting H.264 video streams. By transcoding the source material, you guarantee broader compatibility without sacrificing too much quality if bitrate settings are managed correctly.
HLS Structure Explained
HTTP Live Streaming divides media into a playlist file (.m3u8) and multiple segment files (.ts). The playlist acts as an index, allowing clients to switch between different quality levels dynamically. This adaptive bitrate streaming is crucial for maintaining playback stability under varying network conditions.
Preparing Your Environment
Before running the conversion, ensure you have a recent version of ffmpeg installed that supports HEVC decoding. You can verify your installation by checking the build flags for
-libx264 and
-hevc support. If you are working with large files, consider having sufficient disk space, as intermediate segment files can accumulate quickly during the processing phase.
Executing the Conversion Command
The core command combines several options to handle both the audio and video streams effectively. Below is a robust template for converting a single HEVC MP4 into an HLS output directory.
ffmpeg -i input_hevc.mp4 \
-c:v libx264 -preset medium -crf 23 \
-b:v 1000k -maxrate 1200k -bufsize 2000k \
-c:a aac -b:a 128k -ar 44100 \
-f hls \
-hls_time 4 \
-hls_list_size 0 \
-hls_segment_filename segment_%03d.ts \
playlist.m3u8
Let’s break down these parameters:
- -c:v libx264: Specifies the H.264 encoder for video compatibility.
- -preset medium: Balances encoding speed and compression efficiency.
- -crf 23: Sets the Constant Rate Factor for visual quality; lower values mean higher quality but larger files.
- -b:v, -maxrate, -bufsize: Controls the video bitrate to prevent buffering issues on slower connections.
- -c:a aac: Encodes audio to AAC, which is universally supported in HLS streams.
- -f hls: Forces the output format to HLS.
- -hls_time 4: Sets each segment duration to 4 seconds, a common standard for smooth seeking.
- -hls_list_size 0: Includes all segments in the playlist, useful for VOD (Video on Demand).
For more advanced setups involving multiple resolutions, you would repeat this process with different bitrates and save outputs to separate directories. This approach allows the client player to select the appropriate stream based on bandwidth. If you need to add subtitles or additional metadata, refer to our guide on
adding subtitles to MP4 files, though note that HLS subtitle handling requires specific EXT-X-MAP tags in newer implementations.
Handling Audio and Sync Issues
Audio synchronization is critical when splitting streams. The
-ar 44100 flag ensures the sample rate matches standard expectations. If you notice drift between audio and video, check the original container's timestamps. Sometimes, forcing the start time with
-ss 0 before the input file helps reset timestamps cleanly. For complex audio tracks, such as converting DTS to AAC, see
converting French DTS audio tracks for detailed encoder settings.
Serving the Stream
Once the command completes, you will have a
playlist.m3u8 file and a series of
segment_*.ts files. These must be served from a web server that supports MIME types for
application/vnd.apple.mpegurl and
video/mp2t. Nginx or Apache can easily serve these static files. Ensure your server configuration does not cache the playlist aggressively, as clients should re-fetch it to detect any updates.
Troubleshooting Common Errors
If the resulting stream plays back with scrambled frames or black screens, the issue may lie in the keyframe alignment. HLS segments should ideally start with an I-frame (keyframe). FFmpeg handles this automatically in most cases, but if you encounter issues, adding
-g 48 (group of pictures size) can help align keyframes with segment boundaries. Additionally, verify that your input file is not corrupted; try playing it locally before conversion. For other frame-related issues, consult our troubleshooting article on
scrambled frames during EXR to MP4 conversion, as the principles of frame ordering apply similarly.
Frequently Asked Questions
Can I keep the HEVC codec in the HLS stream?
Yes, but only if your target audience uses devices that fully support HEVC over HLS, such as newer Apple TVs and high-end Android devices. Most web-based players still require H.264 fallbacks.
How do I reduce the file size of the HLS output?
Increase the CRF value (e.g., to 26 or 28) or lower the
-b:v bitrate. However, this may degrade visual quality significantly, especially in scenes with fast motion.
What is the ideal segment length for HLS?
Between 2 and 6 seconds is standard. Shorter segments allow faster startup times but increase overhead, while longer segments improve caching efficiency at the cost of latency.
Do I need a special server to host HLS files?
No, any standard HTTP server works as long as it serves the .m3u8 and .ts files with correct MIME types. Cloud storage services like AWS S3 also work well with proper configuration.
Why is my audio out of sync after conversion?
This usually happens due to timestamp inconsistencies in the source file. Using the
-fflags +genpts option during input processing can often resolve timestamp gaps.