Part5 - HLS Streaming with Nginx Rtmp Module
RTMP is not supported by most of the devices and most of the browsers anymore. At the time of this writing I found out the best streaming choice would be HLS to support most of the devices and browser. HLS not only added video support for iOS devices, but its stateless HTTP delivery method enables us to leverage caching and have the full benefits of load balancing, with a huge impact on performance and scalability.
Incoming stream must be in H264/AAC for HLS streaming, we will set this on OBS and FFMpeg.
Before streaming HLS make sure FFMpeg is installed. Just run the command below to check if it is installed
ffmpeg -v
If it is not installed you can check my article named Installing FFMPEG with Extra Encoding and Decoding Libraries.
This is my IP camera settings:
I will be recording while I do the streaming. Recording must be high quality (1280x720) and stream will be 640x480.
While I was testing HLS stream, I had problems with Windows version of OBS. The hls index file and ts fragments were not updated and hls files were deleted automatically and hls stream was stuck. I tested Mac and Linux version of OBS with the same Nginx config and hls stream worked just fine. The OBS version I am using is OBS for MAC 0.16.2.
The OBS Settings:
On General section, check "Automatically record when streaming" (if you need to record the stream)
On Stream section, enter stream server info in the following format
rtmp://ipaddressofthestreamserver/applicationname
Streamkey: this can be anything that you wanna specify, for test purpose just type: test
Because I am using IP Camera as source, I need to select channels as "Mono." When channels field is selected as stereo, I experienced problems with audio. So, selecting it as "Mono" solved the problem with audio.
I also changed file name formatting as below.
Nginx Configuration for HLS:
First create the folder for hls files under /tmp. Then change nginx.conf file according to your info. I removed the comments from nginx.conf in this article for readability's sake. You need to modify YourNginxIPAddress field with your own server.
mkdir /tmp/hls
sudo nano /usr/local/nginx/conf/nginx.conf
#user nobody;
user nginxadminusername;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
server {
listen 80;
server_name YourNginxIPAddress;
location /hls {
# Serve HLS fragments
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
root /tmp/;
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Origin' '*';
}
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
rtmp {
server {
listen 1935;
application live {
live on;
#What's happening here is we're telling ffmpeg that we want the keyframe interval to be every 40 frames (which is
#two seconds based on OBS's output frame rate of 20fps), and then we're telling nginx to split every 3 keyframes
#(6 seconds). This means that everything fits within the correct second boundaries
exec ffmpeg -i rtmp://YourNginxIPAddress/$app/$name -vcodec libx264 -vprofile
baseline -x264opts keyint=40 -acodec aac -strict -2 -f flv rtmp://YourNginxIPAddress/hls/$name;
}
application hls {
live on;
hls on;
hls_path /tmp/hls/;
hls_fragment 6s;
hls_playlist_length 60s;
}
}
}
Restart Nginx Service
sudo service nginx restart
Test your HLS on VLC:
http://nginxIPAddress/hls/test.m3u8
It works fine.
The above ffmpeg line encodes the video and audio one more time which you may find unnecessary. You can just copy video and audio from the input to output like this:
exec ffmpeg -i rtmp://YourNginxIPAddress/$app/$name -vcodec copy -map 0:a -map 0:v -acodec copy -f flv rtmp://YourNginxIPAddress/hls/$name;
-vcodec copy
: tells ffmpeg that we don't want to change the video codec and can copy what's already in the file
-map 0:a
: tells ffmpeg that we want to include all audio streams
-map 0:a
: tells ffmpeg that we want to include all video streams
-acodec copy
: tells ffmpeg that we don't want to change the audio codec and can copy what's already in the file
Securing your Streaming Server:
At the beginning I disabled the firewall and now I want to enable it and open the required ports. 5900 and 5500 are required if you use VNC for remote connection.
sudo ufw allow 80
sudo ufw allow 1935
sudo ufw allow 5900
sudo ufw allow 5500
sudo ufw enable
I also want to limit the access to my streaming server. Edit nginx.conf.
allow play all;
allow publish 127.0.0.1;
allow publish nginxserveripaddress;
allow publish obsencoderipaddress;
deny publish all;
Restart nginx service
sudo service nginx restart
I noticed that If I reboot the server, the ownership of /tmp/hls changes and nginx can not write to that folder and hls file can not be created. I added the line below at the top of nginx.conf file.
user mynginxadminusername;
Then run the command below to change the ownership of hls folder to modify the permissions.
sudo chown mynginxadminusername /tmp/hls
Finally change the permission like below.
- Hits: 30938