This is a series of articles. Follow the link here to get an overview over all articles.
Previously
on Using FFmpeg as a HLS streaming server (Part 4) – Multiple Video Resolutions.
The command until now looks like the following:
./ffmpeg -listen 1 -i rtmp://martin-riedl.de/stream01 \ -filter_complex "[v:0]split=2[vtemp001][vout002];[vtemp001]scale=w=960:h=540[vout001]" \ -preset veryfast -g 25 -sc_threshold 0 \ -map [vout001] -c:v:0 libx264 -b:v:0 2000k \ -map [vout002] -c:v:1 libx264 -b:v:1 6000k \ -map a:0 -map a:0 -c:a aac -b:a 128k -ac 2 \ -f hls -hls_time 4 -hls_playlist_type event \ -master_pl_name master.m3u8 \ -var_stream_map "v:0,a:0 v:1,a:1" stream_%v.m3u8
But all stream variants are placed in one folder. We want to do here a custom folder structure.
Data Folder per Stream Variant
-hls_segment_filename stream_%v/data%06d.ts
This parameters sets the name of the segment file. In my case a folder name is added named “stream_%v”. %v is the stream variant. The %06d in the file name “data%6d.ts” is a formatted number. 06 means fill the number up with 0 up to 6 digits.
And the result looks great:
But when we try to watch the stream, no video is playing. Hmm, why? A look in the stream_0.m3u8 explains it:
The path for the data.ts files is missing. So the files are not found by the player.
Segment Folder Declaration
For this a base-url must be added to each line of data.ts.
-use_localtime_mkdir 1
This can be done by easily adding the line above. The documentation tells us following:
Used […] it will create all subdirectories which is expanded in filename.
Now the folder path is added correctly in the segment playlist.
Finally
Now the full command looks like this:
./ffmpeg -listen 1 -i rtmp://martin-riedl.de/stream01 \ -filter_complex "[v:0]split=2[vtemp001][vout002];[vtemp001]scale=w=960:h=540[vout001]" \ -preset veryfast -g 25 -sc_threshold 0 \ -map [vout001] -c:v:0 libx264 -b:v:0 2000k \ -map [vout002] -c:v:1 libx264 -b:v:1 6000k \ -map a:0 -map a:0 -c:a aac -b:a 128k -ac 2 \ -f hls -hls_time 4 -hls_playlist_type event \ -master_pl_name master.m3u8 \ -hls_segment_filename stream_%v/data%06d.ts \ -use_localtime_mkdir 1 \ -var_stream_map "v:0,a:0 v:1,a:1" stream_%v.m3u8
hi,
the command is working and is creating files but when i try to play the master file with vlc it does not start.
are you use url for m3u file?
Make sure that the files are available over HTTP(s). Then use the URL to the m3u8 file for the VLC and choose “Open Network”.
Hello. What is the way to add a logo to HLS Stream?
Have made a short article about how to add a logo to the input video. This can be easily combined with the command in this article.
https://www.martin-riedl.de/2020/01/03/add-a-logo-to-a-video-using-ffmpeg/
Your whole tutorial looks very interesting, thanks for putting this together! Will test it as sokn as possible.
Thanks. 🙂
Hi Martin, awesome tutorial man…loved it…working great… but just want to know how to put this entire thing in a folder….I mean, like, master.m3u8, stream folders and stream m3u8 files…all these in a folder
You mean like it is in the first command of this article? Just make sure that you don’t use a folder in the parameter hls_segment_filename.
Thank you for sharing !
Really usefull .
instead of adding options in the ffmpeg command line for creating subfolder,
and you are using nginx for streaming, you could add this option in your nginx.conf (in the application block) =>
hls_nested on;
# on|off. In this mode a subdirectory of hls_path is created for each stream. Default=off.
my 2 cents.
Best regards,
Fred
The free / open source version of NGINX doesn’t support HLS. You are talking about a additional module for that must be installed / compiled.
If you use the RTMP module of arut (https://github.com/arut/nginx-rtmp-module) then you need also FFmpeg for additional features like multiple bitrates or resolutions.
Dear Martin,
about “If you use the RTMP module of arut (https://github.com/arut/nginx-rtmp-module) then you need also FFmpeg for additional features like multiple bitrates or resolutions.”
Sorry my message wasn’t clear, yes I’m using this module, and of course I need ffmpeg.
we all need ffmpeg 😉
Merci.
What if we have multiple audio how can we make it work
Check out part 9: https://www.martin-riedl.de/2020/05/31/using-ffmpeg-as-a-hls-streaming-server-part-9-multiple-audio-languages/
Hi Martin
Thanks for this suburb list of tutorials!
In my ffmpeg (5.0.1 on MacOS with brew) the use_localtime_mkdir option is not recognized.
However, with [-var_stream_map “v:0,a:0 v:1,a:1” stream_%v/index.m3u8] the same folder structure can be realized
thanks and keep up the good work!
Willem
use_localtime_mkdir was renamed to strftime_mkdir
How do I add base url to every entry in master playlist? I tried the hls_base_url and segment_list_entry_prefix options but it only adds the value to the playlist of the different variants and not that of the master playlist. Is there an option or way to do? Or do I have to temper with the master playlist after it has been generated?
hi
When I run below command in windows shell then every things is Ok. But command through batch file by subprocess.call([‘C:/Users/mehdi/video/hls/myscript.bat’] ) in Django I have below error.
More than 1 variant streams are present, %v is expected either in the filename or in the sub-directory name of file stream_v.m3u8
My coomand:
ffmpeg -i brooklynsfinest_clip_1080p.mp4 \
-filter_complex \
“[0:v]split=3[v1][v2][v3]; \
[v1]copy[v1out]; [v2]scale=w=1280:h=720[v2out]; [v3]scale=w=640:h=360[v3out]” \
-map “[v1out]” -c:v:0 libx264 -x264-params “nal-hrd=cbr:force-cfr=1” -b:v:0 5M -maxrate:v:0 5M -minrate:v:0 5M -bufsize:v:0 10M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 \
-map “[v2out]” -c:v:1 libx264 -x264-params “nal-hrd=cbr:force-cfr=1” -b:v:1 3M -maxrate:v:1 3M -minrate:v:1 3M -bufsize:v:1 3M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 \
-map “[v3out]” -c:v:2 libx264 -x264-params “nal-hrd=cbr:force-cfr=1” -b:v:2 1M -maxrate:v:2 1M -minrate:v:2 1M -bufsize:v:2 1M -preset slow -g 48 -sc_threshold 0 -keyint_min 48 \
-map a:0 -c:a:0 aac -b:a:0 96k -ac 2 \
-map a:0 -c:a:1 aac -b:a:1 96k -ac 2 \
-map a:0 -c:a:2 aac -b:a:2 48k -ac 2 \
-f hls \
-hls_time 2 \
-hls_playlist_type vod \
-hls_flags independent_segments \
-hls_segment_type mpegts \
-hls_segment_filename stream_%v/data%02d.ts \
-master_pl_name master.m3u8 \
-var_stream_map “v:0,a:0 v:1,a:1 v:2,a:2” stream_%v.m3u8
It shows that error.
Error: ffmpeg exited with code 1: Unrecognized option ‘var_stream_map “v:0,a:0 v:1,a:1″‘.
Error splitting the argument list: Option not found
How to solve it?
HLS muxer’s ‘user_localtime’/’use_localtime_mkdir’ options removed, users should use ‘strftime’/’strftime_mkdir’ instead
https://trac.ffmpeg.org/wiki/Bump59