ScaleScaleScaleScale

Tips / Nginx


Optimizing Nginx for Video sites

Today one of my customers was trying to work with an application to convert and play videos using nginx and php, like any other “tube” website.  One of his requirements was to enable pseudostreaming for FLV and MP4 videos. So I had to install ffmpeg system and php libraries and then figure out a way to enable pseudostreaming.

The way I found was using the ngx_http_flv and ngx_http_mp4 modules. ngx_http_flv module is used for pseudo-streaming server-side support for Flash Video (FLV) file, and the ngx_http_mp4_module module provides pseudo-streaming server-side support for H.264/AAC files (often used as .mp4, .m4v, or .m4a files).

First, you must check if this modules are already compiled in your nginx installation:

[root@server.myserver.com:~]nginx -V
nginx version: nginx/1.4.1
built by gcc 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) 
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx/ --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log  --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
 --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module
 --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module 
--with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_random_index_module 
--with-http_secure_link_module --with-http_stub_status_module --with-mail --with-mail_ssl_module 
--with-file-aio --with-ipv6 --with-cc-opt='-O2 -g' --add-module=/usr/src/headers-more-nginx-module-0.20

As you see, my nginx installation using Nginx’s offical repo already have this modules compiled. If you are building nginx from source, just make sure to add –with-http_flv_module –with-http_mp4_module while running configure command:

./configure --with-http_flv_module --with-http_mp4_module --with-other-modules

Then, just add these directives to enabled flv and mp4 pseudostreaming:

location /video/ {
# activate flv/mp4 parsing for pseudostreaming
flv;
        mp4;
mp4_buffer_size     4M;
    mp4_max_buffer_size 10M;
}

You can also configure it to serve flv or mp4 individually, examples:

location ~ .flv$ {
flv;
}
location ~ .mp4$ {
mp4;
mp4_buffer_size 4M;
mp4_max_buffer_size 10M;
}

Reload nginx to apply the changes:

service nginx reload

Directives explained:

flv; enables flv pseudostreaming.
mp4; enables mp4 pseudostreaming
mp4_buffer_size: the initial size of a memory buffer used for processing mp4 files.
mp4_max_buffer_size: needed to avoid error 500 while metadata file processing.

Important notes:

1) if mp4_max_buffer_size is set to a small size, you may get Internal Server error and a message like this:
“/myfile.mp4” mp4 moov atom is too large: 4758338, you may want to increase mp4_max_buffer_size

2) You may need to tweak client_max_body_size (and also php/nginx timeouts for very large files) option inside nginx.conf file to allow large file uploads, in my case I got it in this way:

client_max_body_size    80m;

 

Popular search terms:

  • nginx mp4
  • nginx mp4 autoplay
  • https://www scalescale com/tips/nginx/optimizing-nginx-for-video-sites/
  • nginx mp4 streaming
profile

Esteban Borges

Linux Geek, Webperf Addict, Nginx Fan. CTO @Infranetworking

  • laur

    Recommanded to be disable gzip to avoid compression when in streaming is not needed.

    location ~ .mp4$ {
    gzip off;
    gzip_static off;
    mp4;
    limit_rate_after 10m;
    limit_rate 1m;
    }

    Using rate will speed up to max server speed first 10MB than will be limited to 1Mbps, you can configure it as you wish…

  • ura

    i haven’t been able to get this to function here.
    i am using the projekktor media player, which has a config option for pseudo streaming, yet the coders, via their forum, said that pseudostreaming will activate if supported automatically.

    i am using the advised nginx config, to no avail.
    any tips welcomed.

  • what does client_max_body_size have got to do with video streaming? isn’t it for file upload requests? according to the docs on nginx.org it limits the content length in the request header by the client.
    But when a client streams a video, he does not send 80mb request, he gets a big response but the request size is usually less than 1mb

    • nginxadmin

      You are right, it’s for file upload, which are VERY common on streaming servers if the users don’t use FTP. That’s the reason you see that variable there.

  • Will Dashwood

    Is there a way to test the module is working, client side or server side?

  • Ivan

    Thanks ! I have tested so many other tutorials with no success…. this one made my day.

  • crex code

    hi dear thanks for your website it’s so good
    i want ask you about ngx_http_flv_moduleit’s work but not skip minute in vide

    it’s skipping small mp4 video but not flv large video

    nginx.conf
    server {
    location ~ {
    # activate flv/mp4 parsing for pseudostreaming
    flv;
    mp4;
    mp4_buffer_size 4M;
    mp4_max_buffer_size 10M;
    root /usr/share/nginx/html/;
    }

    location / {
    root /usr/share/nginx/html/;
    index index.html index.htm index.txt;
    }

    }
    erro.log empty
    access.log
    41.142.148.140 – – [16/Apr/2015:18:10:20 +0200] “GET /85867.flv HTTP/1.1” 200 741713 “http://mp3zik.com/project/upload/jwplayer/jwplayer.flash.swf” “Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0”
    41.142.148.140 – – [16/Apr/2015:18:10:23 +0200] “GET /85867.flv?start=213152401 HTTP/1.1” 200 1621625 “http://mp3zik.com/project/upload/jwplayer/jwplayer.flash.swf” “Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0”
    41.142.148.140 – – [16/Apr/2015:18:10:24 +0200] “GET /85867.flv?start=336600608 HTTP/1.1” 200 519557 “http://mp3zik.com/project/upload/jwplayer/jwplayer.flash.swf” “Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0”
    41.142.148.140 – – [16/Apr/2015:18:10:25 +0200] “GET /85867.flv?start=64116057 HTTP/1.1” 200 560213 “http://mp3zik.com/project/upload/jwplayer/jwplayer.flash.swf” “Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0”
    41.142.148.140 – – [16/Apr/2015:18:10:26 +0200] “GET /85867.flv?start=400916890 HTTP/1.1” 200 378713 “http://mp3zik.com/project/upload/jwplayer/jwplayer.flash.swf” “Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0”
    41.142.148.140 – – [16/Apr/2015:18:10:30 +0200] “GET /85867.flv?start=442961847 HTTP/1.1” 200 1875725 “http://mp3zik.com/project/upload/jwplayer/jwplayer.flash.swf” “Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0”

    thanks

  • jitender

    I tested this and is working fine for me, but video take so much time start is there any way to reduce the start-up time for video.
    Thanks in advance!!

    • Hey @jitender

      How many simultaneous connections are you having right now? And what’s your current disk setup? (SSD, SATA, raid, no raid?)
      Also, paste your Nginx.conf configuration here and the virtual host one for this site from where you are serving the videos, let me take a look.

  • FRESH ASS NY RAT

    Can’t get this to work to save my life 🙁