arut / nginx-rtmp-module

NGINX-based Media Streaming Server
http://nginx-rtmp.blogspot.com
BSD 2-Clause "Simplified" License
13.33k stars 3.5k forks source link

Live Transcoding for Live events - Great, but heavy! Any tips? #455

Open pedrosimao opened 10 years ago

pedrosimao commented 10 years ago

Hello Guys,

I was searching for an alternative to Wowza Media server, and I found this module just great! Can't believe it's free. I spent the whole day setting up my new server. And I finally achieved something interesting. I am basically using FFMPEG to transcode 1 FullHD streaming into three different bitrates, and make them available to the players. My application also automatically record the source bit-rate to a folder in my server. So I will never loose any important video. If recording takes almost no processing power FFMPEG consumes a lot of processing power. I am here hoping to find someone who can share some tips and ideas on how to make FFMPEG less hungry. Maybe using Gstreamer would be a solution? Anyone here codes in Gstreamer?

So. I will share my complete configuration with you.

My workflow is the following: 1 - I send 1 Full HD RTMP streaming to a "src" app 2 - The "src" app send three bitrates instances (using FFMPEG) to the "live" app 3 - The live app pushes three instances do "hls" app

Here are my config. It took me dozens of hours to find this configuration. Which is stable and works perfectly with my server. But it consumes so much processing power that I am afraid it will make it impossible to have hundreds of persons watching my streaming. If I can't find a solution for the processing power, I may launch a second Nginx server, just to be the provider. As this server gets the "transcoding" role.

Anyway. I would also love to know if someone has experience distributing the streams over a CDN, or creating a network of servers.

So here it goes:

user www-data;

worker_processes 1; pid /var/run/nginx.pid;

error_log /var/log/nginx/error_debug.log debug;

events { worker_connections 768;

multi_accept on;

}

http {

##
# Basic Settings
##

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;

include /etc/nginx/mime.types;
default_type application/octet-stream;

##
# Logging Settings
##

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

##
# Gzip Settings
##

gzip on;
gzip_disable "msie6";

# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

##
# Virtual Host Configs
##

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

Streaming Server

server {

    listen      8080;

    location /hls {
        # Serve HLS fragments
        types {
            application/vnd.apple.mpegurl m3u8;
            video/mp2t ts;
        }
        root /tmp;
        add_header Cache-Control no-cache;
    }

    location /dash {
        # Serve DASH fragments
        root /tmp;
        add_header Cache-Control no-cache;
    }
}

}

rtmp {

server {

    listen 1935;
    chunk_size 4000;
    publish_time_fix off; # compatibility with GStreamer

    application src {
        live on;

     # This records the source streaming, (best quality)
  record all;
        record_path /var/www/liverec;
        record_suffix -%d-%b-%y-%T.flv;
        record_unique on;
        record_notify on;

        # Transcode source into three different bitrates: 720p, 480p and 360p

        exec ffmpeg -y -i rtmp://localhost/src/mystream -threads 8 -f mp4 -vcodec libx264 -preset faster -profile:v baseline -level 40 -refs 6 -deblockalpha 0 -deblockbeta 0 -subq 6 -s 1280x720 -r 30000/1001 -b 1400k -g 30 -coder vlc -acodec copy -ac 2 -ab 128k -f flv rtmp://localhost/live/720; # -bufsize 15000k -maxrate 2500k -bt 1400k

        exec ffmpeg -y -i rtmp://localhost/src/mystream -threads 8 -f mp4 -vcodec libx264 -preset faster -profile:v baseline -level 31 -refs 6 -deblockalpha 0 -deblockbeta 0 -subq 6 -s 854x480 -r 30000/1001 -b 800k -g 20  -coder vlc -acodec copy -ac 2 -ab 128k -f flv rtmp:/localhost/live/480; #-bt 800k -bufsize 15000k -maxrate 1500k -g 300

        exec ffmpeg -y -i rtmp://localhost/src/mystream -threads 8 -f mp4 -vcodec libx264 -preset veryfast -profile:v baseline -level 31 -refs 6 -deblockalpha 0 -deblockbeta 0 -subq 6 -s 426x240 -r 30000/1001 -b 250k -g 20 -coder vlc -acodec copy -ac 2 -ab 128k -f flv rtmp://localhost/live/240; # -bt 250k -bufsize 5000k -maxrate 400k

    }

    application hls {
        live on;

        hls on;
        hls_path /tmp/hls;
        hls_nested on;

    }

   # This application is the live streaming feeds. We will have rtmp://localhost/live/names here!

    application live {
        live on;

        # This pushes all the three streaming to the HLS. I fount that the right URLs or HLS are http://localhost/hls/streamName/index.m3u8

        push rtmp://178.62.6.105/hls;

    }

}

}

Now, anyone has a solution for the transcoding heavy load problem? Finally anyone has experience implementing a multiple servers with DNS failover technique?

Hope to hear from you guys!

theonewolf commented 10 years ago

Transcoding is pretty intense independent of the framework doing it. I would not expect to do more than a handful of live streams in real-time without fairly beefy hardware or multiple backend transcoding workers.

In this regard, nginx with this RTMP module is probably ideal for fanning out "transcoding jobs" to back-end workers, and also being the front-end for streaming them back out.

misiek08 commented 10 years ago

I used to buy cheap VPSes for 3-5$/month to transcode all the things :) They are great workers.

jalonsoa commented 10 years ago

Hi Pedro, you can try to merge the ffmpeg command to generate all streams in one command (this use less resources I think)

And you should change the ffmpeg command to use $name variable, because with you configuration, the ffmpeg command only publish mystream, isn't it ?

exec ffmpeg -y -i rtmp://localhost/src/$name -threads 8 -f mp4 -vcodec libx264 -preset faster -profile:v baseline -level 40 -refs 6 -deblockalpha 0 -deblockbeta 0 -subq 6 -s 1280x720 -r 30000/1001 -b 1400k -g 30 -coder vlc -acodec copy -ac 2 -ab 128k -f flv rtmp://localhost/live/$name-720; # -bufsize 15000k -maxrate 2500k -bt 1400k

j

On Wed, Aug 20, 2014 at 11:48 PM, pedrosimao notifications@github.com wrote:

Hello Guys,

I was searching for an alternative to Wowza Media server, and I found this module just great! Can't believe it's free. I spent the whole day setting up my new server. And I finally achieved something interesting. I am basically using FFMPEG to transcode 1 FullHD streaming into three different bitrates, and make them available to the players. My application also automatically record the source bit-rate to a folder in my server. So I will never loose any important video. If recording takes almost no processing power FFMPEG consumes a lot of processing power. I am here hoping to find someone who can share some tips and ideas on how to make FFMPEG less hungry. Maybe using Gstreamer would be a solution? Anyone here codes in Gstreamer?

So. I will share my complete configuration with you.

My workflow is the following: 1 - I send 1 Full HD RTMP streaming to a "src" app 2 - The "src" app send three bitrates instances (using FFMPEG) to the "live" app 3 - The live app pushes three instances do "hls" app

  • finally it's the "src" app that is in charge of recording

Here are my config. It took me dozens of hours to find this configuration. Which is stable and works perfectly with my server. But it consumes so much processing power that I am afraid it will make it impossible to have hundreds of persons watching my streaming. If I can't find a solution for the processing power, I may launch a second Nginx server, just to be the provider. As this server gets the "transcoding" role.

Anyway. I would also love to know if someone has experience distributing the streams over a CDN, or creating a network of servers.

So here it goes:

user www-data;

worker_processes 1; pid /var/run/nginx.pid;

error_log /var/log/nginx/error_debug.log debug;

events { worker_connections 768;

multi_accept on;

}

http {

Basic Settings

sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048;

include /etc/nginx/mime.types; default_type application/octet-stream;

Logging Settings

access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log;

Gzip Settings

gzip on; gzip_disable "msie6";

gzip_vary on;

gzip_proxied any;

gzip_comp_level 6;

gzip_buffers 16 8k;

gzip_http_version 1.1;

gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

Virtual Host Configs

include /etc/nginx/conf.d/.conf; include /etc/nginx/sites-enabled/;

Streaming Server

server {

listen      8080;

location /hls {
    # Serve HLS fragments
    types {
        application/vnd.apple.mpegurl m3u8;
        video/mp2t ts;
    }
    root /tmp;
    add_header Cache-Control no-cache;
}

location /dash {
    # Serve DASH fragments
    root /tmp;
    add_header Cache-Control no-cache;
}

}

}

rtmp {

server {

listen 1935;
chunk_size 4000;
publish_time_fix off; # compatibility with GStreamer

application src {
    live on;

 # This records the source streaming, (best quality)

record all; record_path /var/www/liverec; record_suffix -%d-%b-%y-%T.flv; record_unique on; record_notify on;

    # Transcode source into three different bitrates: 720p, 480p and 360p

    exec ffmpeg -y -i rtmp://localhost/src/mystream -threads 8 -f mp4 -vcodec libx264 -preset faster -profile:v baseline -level 40 -refs 6 -deblockalpha 0 -deblockbeta 0 -subq 6 -s 1280x720 -r 30000/1001 -b 1400k -g 30 -coder vlc -acodec copy -ac 2 -ab 128k -f flv rtmp://localhost/live/720; # -bufsize 15000k -maxrate 2500k -bt 1400k

    exec ffmpeg -y -i rtmp://localhost/src/mystream -threads 8 -f mp4 -vcodec libx264 -preset faster -profile:v baseline -level 31 -refs 6 -deblockalpha 0 -deblockbeta 0 -subq 6 -s 854x480 -r 30000/1001 -b 800k -g 20  -coder vlc -acodec copy -ac 2 -ab 128k -f flv rtmp:/localhost/live/480; #-bt 800k -bufsize 15000k -maxrate 1500k -g 300

    exec ffmpeg -y -i rtmp://localhost/src/mystream -threads 8 -f mp4 -vcodec libx264 -preset veryfast -profile:v baseline -level 31 -refs 6 -deblockalpha 0 -deblockbeta 0 -subq 6 -s 426x240 -r 30000/1001 -b 250k -g 20 -coder vlc -acodec copy -ac 2 -ab 128k -f flv rtmp://localhost/live/240; # -bt 250k -bufsize 5000k -maxrate 400k

}

application hls {
    live on;

    hls on;
    hls_path /tmp/hls;
    hls_nested on;

}

This application is the live streaming feeds. We will have rtmp://localhost/live/names here!

application live {
    live on;

    # This pushes all the three streaming to the HLS. I fount that the right URLs or HLS are http://localhost/hls/streamName/index.m3u8

    push rtmp://178.62.6.105/hls;

}

}

}

Now, anyone has a solution for the transcoding heavy load problem? Finally anyone has experience implementing a multiple servers with DNS failover technique?

Hope to hear from you guys!

— Reply to this email directly or view it on GitHub https://github.com/arut/nginx-rtmp-module/issues/455.

deedos commented 9 years ago

@misiek08 I 'm wondering how you share the cpu load across differente VPSes. Thanks in advance

misiek08 commented 9 years ago

At first I just made simple bash script to restart ffmpeg if it died, then I rewrote it to python to get data by simple API, so I had remote control over that.

I am from Poland and here arent many client for live streaming, so my plans to make all the things "smart" died.

I just ran 2-4 (depending on bitrate) ffmpeg's and watched how much resources they use and if there is some space for next one. If not I just took next small VPS and the process restarts :) 22 wrz 2014 23:06 "Daniel Roviriego" notifications@github.com napisał(a):

@misiek08 https://github.com/misiek08 I 'm wondering how you share the cpu load across differente VPSes. Thanks in advance

— Reply to this email directly or view it on GitHub https://github.com/arut/nginx-rtmp-module/issues/455#issuecomment-56443159 .

ebuildy commented 9 years ago

@deedos

You easily start ffmpeg on another server, using ssh for instance or a complex HTTP API (NodeJS: express + https://github.com/fluent-ffmpeg/node-fluent-ffmpeg).

Or, use some specialized tools like Docker or http://mesos.apache.org/.

lavvy commented 9 years ago

Please what is configuration to transcode live rtmp to .ogg . Can it be achieved ? On Sep 2, 2015 5:38 AM, "Thomas Decaux" notifications@github.com wrote:

@deedos https://github.com/deedos

You easily start ffmpeg on another server, using ssh for instance or a complex HTTP API (NodeJS: express + https://github.com/fluent-ffmpeg/node-fluent-ffmpeg).

Or, use some specialized tools like Docker or http://mesos.apache.org/.

— Reply to this email directly or view it on GitHub https://github.com/arut/nginx-rtmp-module/issues/455#issuecomment-136999752 .