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 3) – Multiple Bitrates
This is the full command until now:
./ffmpeg -listen 1 -i rtmp://martin-riedl.de/stream01 \ -preset veryfast -g 25 -sc_threshold 0 \ -map v:0 -c:v:0 libx264 -b:v:0 2000k \ -map v:0 -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
It produces an HLS livestream with two different video qualities (video bitrates).
Two different bitrates are well, but more helpful would it be to have the lesser bitrate version in a lower resolution.
Video Resolutions using Complex Filter
To achieve this, we need to duplicate the video input signal. Then we can apply different filter to each stream.
-filter_complex "[v:0]split=2[vtemp001][vout002]"
The command above splits the first video input source [v:0] and splits it into two. The first video feed with the name vtemp001 is the one that we want to scale own. The second vout002 is the full HD version. This one is already finished, so we just passt them out (FFmpeg Documentation).
[vtemp001]scale=w=960:h=540[vout001]
Then we add the text above to the filter separated by a semi-colon. Here the vtemp001 video stream is scaled down to a lesser resolution (FFmpeg Documentation).
Now both new video feeds must be replaced with the original input in our command. The first -map v:0 will be replaced with -map [vout001], the second will be replaced with -map [vout002].
Finally
Easy, right? The new command is now:
./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
Great tips, just what i was looking for. thanks for this.
Thanks 🙂
-filter_complex “[v:0]split=2[vtemp001][vout002];[vtemp001]scale=w=960:h=540[vout001]”
What does the entry [vout001] mean on this line?
vout001 is just a placeholder name to be used later with the -map command (v = virual; out = output; 001 = just a counter). You can also use a different name here.
Hello,
Thanks for this lovely tutorial and it helps me a lot for what u want to do. Please I got some questions;
First it seems tutorial 4 is not linked at the bottom of 3’s page, making it difficult to find.
Second you make no mention (pls forgive if you did), if how you then served the files to your client. Isn’t there like a separate server running? Can you write on this aspect too?
Kind regards
Thanks for the feedback.
First: I have now made a new overview article that contains links for all posts. So it should now be easier to go through this series of articles.
Second: The files are just served using a simple webserver. I personally use nginx for this but you can also use apache or IIS for this.
Thanks, but how to do it on windows10 saving the m3u8 files to desktop ?
I´m trying to convert an mkv file to be streamed in hls (packets), but didn´t understood how to do it.
I have a mkv containing
a) Video in mp4 format (encoded with h264) to be used/transcoded in several different resolutions 640×480, 960×720 etc (in .ts format)
b) 2 or more audio tracks (encoded as mp3 format) (The output can be in aac or mp3 work as well on streamings ?)
c) 2 or more subtitles (built with srt or WebVTT format) The desired output format is webvtt
I would like to create a playlist in m3u8 containing several small pieces (something around 256 kb each or 6 seconds per chunck) of .ts file that can allow me to stream the video and all it´s multiple audio and multiple subtitles each one on their own subdirectories.
I tried to follow the commands here : https://kipalog.com/posts/FFMPEG-HLS-STREAM-MULTIPLE-AUDIO-SUBTITLES and here at yours https://www.martin-riedl.de/2018/08/
But i didn´t succeed to make it work.
I tried this command:
ffmpeg -i teste.mkv -profile:v baseline -level 3.0 -s 640×360 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls index.m3u8
It did created the ts and vtt files, but, it did not putted the generated files on their own subdirectories, and neither exported the different audio channels (in case, the test.mkv file contains 2 audio tracks and 2 subtitles) as it shows in the zip file as an example on the 1st link.
How can this be done ?
Best Regards,
guga
I never did anything with subtitles.
But my now article explains how to use multiple audio languages.
https://www.martin-riedl.de/2020/05/31/using-ffmpeg-as-a-hls-streaming-server-part-9-multiple-audio-languages/
Hi Martin. Awesome blog. Thanks for sharing your knowledge as well. Would it be possible to restream an hls source to an rtmp endpoint, using the above technique – i.e take an hls video source, split it into two streams and then deliver both streams to rtmp endpoints.
Thanks.
Basically you just need to switch the input and output:
./ffmpeg -i http://some.published.com/stream.hls rtmp://server/stream
If you want to send the same stream to two RTMP servers you can just execute the command two times at the same time.
Thanks for this useful tip.
if i had more than 2 resolutions and each had to be of a separate resolution how would i structure the command?
HI,
i have a problem 😉
I run the bash file:
if [ ! -d /mnt/mp4s/$dir ]
then
mkdir -p /mnt/mp4s/$dir
fi
ffmpeg -i rtmp://localhost:1935/$1/$2 \
-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 mp4s/$dir/stream_%v/data%06d.ts \
-use_localtime_mkdir 1 \
-var_stream_map “v:0,name:480,a:0 v:1,name:720,a:1” mp4s/$dir/stream_%v.m3u8
when you go to call it from the player it gives me the absolute address and therefore does not track the ts file well.
in m3u8 i have this
#EXTINF:4.166667,
mp4s/9965C46D-21C2-4CDE-A310-4061FA9A291B/stream_720/data000000.ts
and the result call from player is:
http://domain.com/mp4s/9965C46D-21C2-4CDE-A310-4061FA9A291B/mp4s/mp4s/9965C46D-21C2-4CDE-A310-4061FA9A291B/stream_720/data00000.ts
but I should have this:
/mp4s/9965C46D-21C2-4CDE-A310-4061FA9A291B/stream_720/data000000.ts
thk you in advance
regards
Alessandro
i tried this script but not created 2 subtitles for one video, i want 2 subtitles and one video in master player, please reply me
RStreamer_engine_VOD -i Doctor_strange.mkv \
-max_muxing_queue_size 1024 -preset ultrafast -c:v copy \
-map a:0 -map s:0 -map v:0 -map s:1 \
-f hls -hls_time 2 -hls_list_size 4 \
-hls_delete_threshold 1 \
-hls_flags delete_segments \
-hls_start_number_source datetime \
-start_number 10 \
-hls_playlist_type event -master_pl_name master.m3u8 \
-hls_segment_filename stream_%v/data%06d.ts \
-use_localtime_mkdir 1 \
-var_stream_map “a:0,agroup:audio,s:0,sgroup:subtitles v:0,agroup:audio,s:1,sgroup:subtitles