FreeBSD nGinx FFmpeg camera recording and live streaming

NGINX FFMPEG Camera recording and live streaming

We will install and configure FFMpeg on FreeBSD 10.1 x64 server and will learn how to convert video/audio files.

FFmpeg — this is set of libraries which, helps to write digital audio and video files and convert them to different formats. It includes libavcodec  library for audio/video code/decode works and libavformat to mediacontainer for multiplexing/demultiplexing. Its name is based from MPEG and FF.

ffmpeg consists of the following components:
ffmpeg — CLI utilit for convertiong one video file to another. With the help of utilit you can also capture video in real time from TV-card.
ffserverHTTP(RTSP is being used now) radio broadcasting and video streaming server.
ffplay — Simple media player based on SDL and FFmpeg libraries.
libavcodec — Library with all audio/video codecs. Most of codecs are prepared for the best productivity prepared from scratch.
libavformat — Multiplexer and demultipexer Library for different audio,video formats.
libavutil — Assistant library with standart sub programs for different components of ffmpeg. Adler-32, CRC, MD5, SHA1, LZO-decompressor, Base64 – coder/decoder, DES – crypter/decrypter, RC4 – crypter/decrypter and AES – crypter/decrypter is included.
libpostproc — It is a library of standart sub programs of video processing.
libswscale — It is library for scaling.
libavfilter — is the substitute for vhook which allows the video/audio to be modified or examined between the decoder and the encoder.

RTSP – Real Time Streaming Protocol streaming protocol, it was prepared in 1998 by IETF and was described in RFC 2326. Applied protocol, it was aimed to use controlling streaming information in multimedia worked systems. By RTSP you can use “Start” “Stop” commands and also entry by the time for files that are placed in server.

RTMP – Real Time Messaging Protocol it is a major protocol to send stream informations. Basically it is used for sending video and audio streams from web cameras over the internet.

# portsnap fetch extract update           => Update ports
# cd /usr/ports/multimedia/ffmpeg         => Go to the Ffmpeg port
# make config                             => Chooshe modules
ffmpeg-port
# make install clean –DBATCH        => install from the ports
# rehash                            => Reupdate binary files

We can see the list of video and audio codecs are supported bye FFMPEG:
# ffmpeg –codecs

We can see the list of video and audio formats are supported bye FFMPEG:
# ffmpeg –formats

We can change a video format(for example .mp4) to another one(.avi) as follows:
# ffmpeg -i test.mp4 test.avi

Lets take the sound from the video in the format .mp3:
# ffmpeg -i test.avi -vn -ar 44100 -ac 2 -f mp3 test_ses.mp3
-i  – the name of input file
-vn –  stop the video recording
-ar – set the frequency audio copy
-ac – set the number of audio channel
-f  – set the format of output file

Convert the .WAV file to .mp3 format
# ffmpeg -i test.wav -vn -ar 44100 -ac 2  -f mp3 test.mp3

Setting certain size and converting .avi format to .flv format
# ffmpeg -i test.avi -ab 56 -ar 44100 -b 200 -r 15 -s 320×240 -f flv test.flv
-r – It sets the number of frames of input/output files per second
-s – Set the screen size of output file

Saving live video stream from the IP camera by openRTSP and FFMpeg
To watch the view of any IP cameras in VLC player by RTSP protocol we install the VLC player to our Windows desktop and look documentation of IP camera for using RTSP URL syntax. For example we watch the live stream by RTSP of HikVision camera from our network with IP:10.50.6.101, Login:admin and Password:12345. The documentation of HikVision said RTSP syntax must be as follows:
rtsp://admin:12345@10.50.6.101:554/Streaming/Channels/101?transportmode=unicast

Open the VLC meda player Media->Open Network Stream enter the URL and push the Play.
VLC-media-player
Open-Media

And after seing the result we can be sure that RTSP URL works.
RTSP-VLC

Then come back to the FreeBSD server.
# cd /usr/ports/net/liveMedia       => Go to the port folder
# make install clean          => Install OpenRTSP(LiveMedia) from the ports
# rehash                      => Rehash the binaary files

Then write a minutes view with the format .avi from our camera to our server by the following command:
# openRTSP -v -t -d 60s “rtsp://admin:12345@10.50.6.101:554/Streaming/Channels/101?transportmode=unicast” | ffmpeg -i – -y -r 20 -b 1000k -vcodec h264 -f avi test.avi

openRTSP
-v – Play only video stream
-t – Play RTP/RSTP stream via TCP(by default is UDP)
-d – Set playbaack time

ffmpeg
-y – Write output file without asking
-vcodec – Set the video codec of output file

After finishing of recording we can download “test.avi” file from our server by the “winscp.exe” program and play this file in Windows player.

You can see the result of this example.
test.avi

Sending live broadcast and video files from cameras to web server by FFserver

Send video file with voice to web server as flv format

FFserver is the component of FFMPEG distro and when installing FFmpeg this comes with working FFserver.
# cd /usr/local/etc/    => Go to the FFserver configuration folder
# ee ffserver.conf     => Open the configuration file and change as follow

Port 8090               # Set listen port of FFserver
BindAddress 0.0.0.0     # Listen on all IPs
MaxHTTPConnections 2000 # Maximum number of HTTP connections
MaxClients 1000         # Maximum number of clients
MaxBandwidth 20480      # Maximum bandwidth per user (kbit/s)
CustomLog /var/log/ffserver.log     # Path for log file
<Feed feed1.ffm>        # Main translation for each source translation
File /tmp/feed1.ffm     # Path for main translation
FileMaxSize 500M        # The limit of main translation
</Feed>                 # Close the main translation

<Stream video.flv>      # The latest broadcast which is published to users
    Format flv          # The format of the latest broadcast
    Feed feed1.ffm      # To ühich main broadcast belongs(define the source)
    VideoCodec libx264  # Set the last video stream codec
    VideoFrameRate 30   # Frame count per second of last video stream
    VideoBitRate 800    # Set the bit rate of last video broadcast(kb/s)
    VideoSize 720×576   # Set the screen size of last video broadcast

    # The following “AVoption” variables directly communicated with
    # libavformat, libavdevice and libavcodec libraries and they have 2 types
    # Generic (can be used for each codec) and Private (Can only be used for
    # specified codec).
    AVOptionVideo crf 23
    AVOptionVideo preset medium
    AVOptionVideo me_range 16
    AVOptionVideo qdiff 4
    AVOptionVideo qmin 10
    AVOptionVideo qmax 51
    AVOptionVideo flags +global_header

    AudioCodec aac            # Set the voice codec
    Strict -2           # It is used to force start experimental codecs
    AudioBitRate 128    # Set the bit rate of voice codec(kb/s)
    AudioChannels 2   # Set the amount of voice channels during the broadcast
    AVOptionAudio flags +global_header

</Stream>                     # It is used to finish the broadcasting

<Stream index.html>           # Set the index page
Format status     # Give information about the broadcasting on index page
</Stream>               # It is used to stop the broadcast

Add the daemon to startup and start it:
# echo ‘ffserver_enable=”YES”‘ >> /etc/rc.conf
# service ffserver start

To analyze the Ffserver logs you can look at the /var/log/ffserver.log file which we have already configured:
root@live:~ # tail -f /var/log/ffserver.log
Mon Jun 29 15:22:39 2015 FFserver started.

And now lets send a video file to FFServer
# ffmpeg -i /root/test.video/team.mp4 http://localhost:8090/feed1.ffm

Then if we have suitable codec we can open in WEB browser or we can write http://ffserver.ip.add.ress:8090/video.flv link in our VLC player and watch it.
video-flv
video-flv-via-web

So, everything is working. Added lines to our ffserver.conf configuration file create index page for broadcasting.
<Stream index.html>
Format status
</Stream>

If you will open web page as http://ffserver.ip.add.ress:8090/ , you can see the following page.
10.50.3.200-8090

And now lets send camera broadcast to ffserver server. Create the second “Feed” and send the video and the camera broadcast to our server.

For it add the following lines to the same configuration file. The old configurations will remain the same.

# ee /usr/local/etc/ffserver.conf         => Enter the configuration file and add the following red lines
Port 8090
BindAddress 0.0.0.0
MaxHTTPConnections 2000
MaxClients 1000
MaxBandwidth 20480
CustomLog /var/log/ffserver.log

<Feed feed1.ffm>
File /tmp/feed1.ffm
FileMaxSize 500M
</Feed>

<Stream video.flv>
    Format flv
    Feed feed1.ffm
    VideoCodec libx264
    VideoFrameRate 30
    VideoBitRate 800
    VideoSize 720×576
    AVOptionVideo crf 23
    AVOptionVideo preset medium
    AVOptionVideo me_range 16
    AVOptionVideo qdiff 4
    AVOptionVideo qmin 10
    AVOptionVideo qmax 51
    AVOptionVideo flags +global_header
    AudioCodec aac
    Strict -2
    AudioBitRate 128
    AudioChannels 2
    AudioSampleRate 44100
    AVOptionAudio flags +global_header
</Stream>

# Create the second main broadcast
<Feed feed2.ffm>       
File /tmp/feed2.ffm
FileMaxSize 500M
</Feed>

# Create new broadcast and define it to the second main broadcast
<Stream camera.flv>
    Format flv
    Feed feed2.ffm
    VideoCodec libx264
    VideoFrameRate 25
    VideoBitRate 800
    VideoSize 1280×720
    AVOptionVideo crf 23
    AVOptionVideo preset medium
    AVOptionVideo me_range 16
    AVOptionVideo qdiff 4
    AVOptionVideo qmin 10
    AVOptionVideo qmax 51
    AVOptionVideo flags +global_header
    NoAudio
</Stream>

<Stream index.html>
Format status
</Stream>

# service ffserver restart          => restart Ffserver again

Then to send video file to our machine enter the following command:
# ffmpeg -i /root/test.video/team.mp4 http://localhost:8090/feed1.ffm -loglevel debug

And the same time to send the camera broadcast add the following command:
# ffmpeg -i “rtsp://admin:12345@10.50.6.101:554/Streaming/Channels/101?transportmode=unicast” http://localhost:8090/feed2.ffm -loglevel debug

Go to the WEB browser and see the status page
second-status-page

If we enter again the video.flv vodeo broadcast we can see the video with voice. We can get this entering to VLC player too. We noted about it in our previous example.
second-video-flv

If we go to the Camera.flv we can see the live broadcasting. If your web browsers supports FLV codec you will get the following result.
warehouse

But in VLC player you will get the following result.
warehouse2

If you want to download camera broadcast automatically to your FFserver after starting, we do changes the following red changes in our  /usr/local/etc/ffserver.conf configuration file:
Port 8090
BindAddress 0.0.0.0
MaxHTTPConnections 2000
MaxClients 1000
MaxBandwidth 20480
CustomLog /var/log/ffserver.log

<Feed feed1.ffm>
    File /tmp/feed1.ffm
    FileMaxSize 500M
</Feed>

<Stream video.flv>
    Format flv
    Feed feed1.ffm
    VideoCodec libx264
    VideoFrameRate 30
    VideoBitRate 800
    VideoSize 720×576
    AVOptionVideo crf 23
    AVOptionVideo preset medium
    AVOptionVideo me_range 16
    AVOptionVideo qdiff 4
    AVOptionVideo qmin 10
    AVOptionVideo qmax 51
    AVOptionVideo flags +global_header
    AudioCodec aac
    Strict -2
    AudioBitRate 128
    AudioChannels 2
    AudioSampleRate 44100
    AVOptionAudio flags +global_header
</Stream>

<Feed feed2.ffm>
    File /tmp/feed2.ffm
    FileMaxSize 500M

# When FFserver will start it will execute the following command automatically and get source for “feed2” main broadcast from RTSP broadcast
    Launch ffmpeg –i “rtsp://admin:12345@10.50.6.101:554/Streaming/Channels/101?transportmode=unicast”
</Feed>

<Stream camera.flv>
    Format flv
    Feed feed2.ffm
    VideoCodec libx264
    VideoFrameRate 25
    VideoBitRate 800
    VideoSize 1280×720
    AVOptionVideo crf 23
    AVOptionVideo preset medium
    AVOptionVideo me_range 16
    AVOptionVideo qdiff 4
    AVOptionVideo qmin 10
    AVOptionVideo qmax 51
    AVOptionVideo flags +global_header
    NoAudio
</Stream>

<Stream index.html>
    Format status
</Stream>

# service ffserver restart          => Restart Ffserver again

In the log file you will see the ffserver executing command:
# tail –f /var/log/ffserver.log   
Tue Jun 30 00:31:02 2015 FFserver started.
Tue Jun 30 00:31:02 2015 Launch command line: /usr/local/bin/ffmpeg –i rtsp://admin:12345@10.50.6.101:554/Streaming/Channels/101?transportmode=unicast http://127.0.0.1:8090 feed2.ffm

If we again enter http://ffserver.ip.add.ress:8090/camera.flv broadcast we will see the everything is working.
vlc-video-3

On nGinx web server by RTMP protocol and Ffmpeg to watch 2 camera’s broadcast by JWPlayer web player, recording broadcast and watch recorded files.

# cd /usr/ports/www/nginx     => Go to the port
# make config                 => Choose modules below, except standarts
nginx-port
# make install clean –DBATCH        => install (veersion 1.8.0_2,2)
# rehash                            => Update binary path’s
# cd /usr/local/etc/nginx/          => Go to the nGinx configuration folder
# ee nginx.conf                    => Open default nginx configuration file and add the red marked lines
#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

# Set the path of error log file
error_log /var/log/nginx/nginx-error.log debug;

#pid        logs/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

#log_format  main  ‘$remote_addr – $remote_user [$time_local] “$request” ‘
#                  ‘$status $body_bytes_sent “$http_referer” ‘
#                  ‘”$http_user_agent” “$http_x_forwarded_for”‘;

#access_log  logs/access.log  main;

sendfile        on;
#tcp_nopush     on;
#keepalive_timeout  0;
keepalive_timeout  65;
#gzip  on;
# Include the virtual host configuration path’s
    include sites-enabled/*;
    include sites-available/*;
    server {
        listen       80;
        server_name  localhost;
#charset koi8-r;
#access_log  logs/host.access.log  main;
location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;
        }
#error_page  404              /404.html;
# redirect server error pages to the static page /50x.html
error_page   500 502 503 504  /50x.html;
location = /50x.html {
            root   /usr/local/www/nginx-dist;
        }
    }
}

# Add the configuration for RTMP protocol
rtmp {
        # Set the full path for access logs
        access_log /var/log/nginx/rtmp_access.log;
        server {
                listen 1935;              # Set the listen port
                application live {       
                live on;                  # Turn on ‘Live’ mode

# When nGinx will start it will create “live” streaming for “camera1”
# and “camera2” 2 different channel with exec_static command
                exec_static /usr/local/bin/ffmpeg -i rtsp://10.41.10.25:554/ -c copy -f flv rtmp://localhost/live/camera1;
                exec_static /usr/local/bin/ffmpeg -i rtsp://10.41.10.4:554/ -c copy -f flv rtmp://localhost/live/camera2;
                record all;   # Recording videos
                record_path /var/videos;        # recorded video path
                record_suffix _%d-%b-%y-%T.flv;      # timestamp for recorded # .flv video files
                record_interval 60m;      # record file interval is 60 minutes
                }
        }
}

# mkdir /var/log/nginx/       => Create folder for log file
# mkdir /usr/local/etc/nginx/sites-enabled      => Create folder
# mkdir /usr/local/etc/nginx/sites-available    => Create folder
# mkdir /var/videos           => Create folder to save videos
# chown www:www /var/videos/  => Add access for web server for recording     
# nginx –t                    => check the configuration file

If output will be as follows then everything is OK:
nginx-output

# cd /usr/local/etc/nginx/sites-enabled/        => Go to the folder
# ee camera1.conf       => Create configuration file for “camera1.lan” virtual host and add the following lines
server {
    listen 80;
server_name camera1.lan;    # Set the virtualhost name

# Set the PUBLIC_HTML folder and index extension
location / {
        root /usr/local/www/camera1.lan;
        index index.php index.html index.htm;
    }
}

# mkdir /usr/local/www/camera1.lan        => Create the folder for camera1.lan virtual host
# cd /usr/local/www/camera1.lan           => Go to the folder

Download JWPLAYER from http://www.adrive.com/public/pN4j4w/jwplayer.zip link to our FreeBSD server to folder /usr/local/www/camera1.lan.

# ee index.html         => Create index file and edit as follows
# Enter JWPLAYER to index page
<script type=”text/javascript” src=”jwplayer.js“></script>
<div id=”jwplayer.flash.swf“>Loading the player …</div>
<script type=”text/javascript”>
jwplayer(‘jwplayer.flash.swf’).setup({
# Set the file that will be read for Jwplayer. Here will be camera1 Live
# broadcast which, we did this in nginx global configuration file with
# exec_static command. It will be RTSP broadcast for 10.41.10.25 camera
# You can see this in nginx global configuration file
# In line below write the web server IP address
file: ‘rtmp://10.50.3.200/live/camera1’,
# Set the size for JWplayer
width: ‘1280‘,
height: ‘720‘,
aspectratio: ’16:9’
});
</script>

# cd /usr/local/etc/nginx/sites-enabled/  => Go to the folder
# cp camera1.conf camera2.conf            => Copy camera1.conf virtualhost configuration file to “camera2.lan” virtualhost file

# ee camera2.conf             => Change red marked lines
server {
    listen 80;
    server_name camera2.lan;    # Set the name of VirtualHost

# Show the address where all files of virtualhost are settled and set
# the index files
location / {
        root /usr/local/www/camera2.lan;
        index index.php index.html index.htm;
    }
}

# cd /usr/local/www/          => Go to the folder
# cp -r camera1.lan/ camera2.lan/         => Copy camera1.lan full folder to the camera2.lan folder
# cd  camera2.lan/            => Go to the copied folder
# ee index.html               => Open the index page and change the red lines
# Enter JWPLAYER to index page
<script type=”text/javascript” src=”jwplayer.js“></script>
<div id=”jwplayer.flash.swf“>Loading the player …</div>
<script type=”text/javascript”>
jwplayer(‘jwplayer.flash.swf’).setup({
# Set the file that will be read for Jwplayer. Here will be camera2 Live
# broadcast which, we did this in nginx global configuration file with
# exec_static command. It will be RTSP broadcast for 10.41.10.4 camera
# You can see this in nginx global configuration file
# In line below write the web server IP address
file: ‘rtmp://10.50.3.200/live/camera2’,
# Change size for Jwplayer index page
width: ‘1280‘,
height: ‘720‘,
aspectratio: ’16:9’
});
</script>

# cd /usr/local/etc/nginx/sites-enabled/  => Go to the folder
# cp camera1.conf play.conf         => To see old recorded files we create “play.lan” virtualhost. For that we copy camera1.conf file to play.conf file
# ee play.conf                =>  Change red marked lines
server {
    listen 80;
    server_name play.lan; # Set the VirtualHost name

# Show the address where all files of virtualhost are settled and
# delete index files and set the differen folder for auto indexing
    location / {
        root /var/videos;
        autoindex     on;
        #index index.php index.html index.htm;
    }
}

Add nGinx daemon to StartUP and start
# echo ‘nginx_enable=”YES”‘ >> /etc/rc.conf
# service nginx start

Open the log file on different page:
# tail -f /var/log/nginx/nginx-error.log
nginx-error-log

We can see starting “Exec” commands and creating 2 broadcasts(camera1 and camera2) automatically.

To watch the broadcasts first add the following lines to C:\Windows\System32\drivers\etc\hosts wile in our Windows machine:
10.50.3.200 camera1.lan
10.50.3.200 camera2.lan
10.50.3.200 play.lan

After saving changes open the web browser and push PLAY in JWplayer.
http://camera1.lan/
camera1.lan

http://camera2.lan/
camera2-lan

As you see we can see different live stream on different virtual names.

And now let’s see old recorded files of our camera broadcast

Open http://play.lan/ page in web browser. You will see the page as follows and there will be recroded .flv files for one hour.
index-of

If we click one of them and if you web browser supports video codecs the page will be opened. If doesn’t the video file will be downloaded to your machine.
last-photo

As you see everything is working