Optimizing Nginx for Video sites

Nginx is commonly used for static content, and in many cases, it is used for video streaming. This article metions how to optimize nginx for video sites.

Weeks ago I 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 ngix_http_flv and ngix_http_mp4 modules. ngix_http_flv module is used for pseudo-streaming server-side support for Flash Video (FLV) file, and the ngix_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:

[bash][[email protected] conf.d]# nginx -V
nginx version: nginx/1.4.7
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (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_gunzip_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 -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector –param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables'[/bash]

As you see, the 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:

[bash]./configure –with-http_flv_module –with-http_mp4_module –with-other-modules[/bash]

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

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

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

[bash]location ~ .flv$ {
location ~ .mp4$ {
mp4_buffer_size 4M;
mp4_max_buffer_size 10M;

Reload nginx to apply the changes:

[bash]service nginx reload[/bash]

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.

Some 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. For example, if you allow users to upload files up to 80MB:[bash]client_max_body_size 80m;[/bash]
  3. Since streaming sites are normally high traffic, remember to configure at least the worker_process (= 2xCPU cores. However, try to see if there is any problem if this value > 4) and worker_connections variables properly.
  4. You can use the following ffmpeg command line to extract a thumbnail from a video for a specific time-frame: [bash]ffmpeg -ss 0:03:1 -i FILENAME.mp4 -s 150×100 -vframes 1 FILENAME-thumb.png[/bash]


Leave a Reply