ut0mt8 / nginx-rtmp-module

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

nginx-rtmp-module without dash_variant #7

Closed almoghzn closed 6 years ago

almoghzn commented 6 years ago

I'm using nginx-rtmp-module from https://github.com/ut0mt8/nginx-rtmp-module/ with the dash_variant ability.

My question is: Can I use this fork of nginx-rtmp-module but without dash_variant configuration (as it should work with the original nginx-rtmp-module)?

I tried to remove the dash_variant property but the the directory /tmp/dash/{name} was empty (the directory was created but the mpd and the segments did not created).

ut0mt8 commented 6 years ago

Unless I broke something, yes it should work as the original. However the dash_variant is the main feature of this fork, unless you want to try very specific feature, rmtp scte35 to inband emsg .

Can you post your config ? what are in the log ? did the rtmp sucessfully connect ? (it is very helpfull to enable debug on nginx to see something)

almoghzn commented 6 years ago

Ok few insights.

I think I succeed to use your fork without the "dash_variant" property. I wanted to do so because the quality of the video was pretty bad. and I wanted to identify where is the issue.

First, my nginx config is: `user root;

pid /var/run/nginx.pid;

error_log logs/error.log info;

worker_processes 1;

events { worker_connections 1024; }

http { include mime.types; sendfile on;
keepalive_timeout 65;

server {
    listen 80;
    server_name localhost;

    client_max_body_size 128M;

    add_header Access-Control-Allow-Origin * always;
    add_header Cache-Control no-cache always;

    # Redirect this domain to a different URL
    location / {
        root   html;
        return 301 muvix.co.il;
    }

    # Return an empty response, used by dash.js to sync with server time
    location /time {
        return 200;
    }

    # DASH files
    location /dash {
        root /tmp;
    add_header Cache-Control no-cache;
        add_header 'Access-Control-Allow-Origin' '*';
    }

    # HLS files
    location /hls {
        root /tmp;
    }
}

}

rtmp { server { listen 1935; chunk_size 4096;

    publish_time_fix off;

    application kan {
        exec_static ffmpeg -i rtmp://ipbc-s.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3 -ar 44100 -f flv rtmp://localhost/ingest/kan;
    }

    application ingest {
        live on;
        exec ffmpeg -i rtmp://localhost/$app/$name
            -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 500k -minrate 500k -maxrate 500k -bufsize 1000k -g 60 -s 640x360
                -f flv rtmp://localhost/dash/$name_low 
            -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 1500k -minrate 1500k -maxrate 1500k -bufsize 3000k -g 60 -s 1280x720
                -f flv rtmp://localhost/dash/$name_med 
            -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 10000k -g 60 -s 1920x1080
                -f flv rtmp://localhost/dash/$name_high;
    }

    application dash {
        live on;
        allow publish all;

        dash on;
        dash_nested on;
        dash_path /tmp/dash;
        dash_fragment 3;
        dash_playlist_length 120;

        dash_variant _low   bandwidth="500000"  width="640"  height="360";
        dash_variant _med  bandwidth="1500000" width="1280"  height="720";
        dash_variant _high bandwidth="5000000" width="1920" height="1080" max;
    }
}

} `

Couple of things:

  1. I want to stream linear channel (live channel) to my nginx and dash it. I can use either exec_static internally from the nginx or from my computer. Am I using the exec_static right? (I want to stream this channel always. therefore I'm using the exec_static)
  2. The ffmpeg command which push the media to the dash application must contains the following presets: -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 500k -minrate 500k -maxrate 500k -bufsize 1000k -g 60 -s 640x360 (either if I use the ffmpeg from the ingest application as you can see in the config or if I use the ffmpeg from local computer directly to the dash application) My question is, Why I must use this parameters within the ffmpeg command? I don't want to reencode/transcode the media. I only need to copy it and dash it. (If I remove this ffmepg parameters the dash isn't created).
almoghzn commented 6 years ago

One more thing I just found, When I stream the linear channel using the following (either from my computer or internally from nginx like it is at the config file under kan applicaion) ffmpeg -i rtmp://ipbc-s.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3 -ar 44100 -f flv rtmp://{nginx_ip}/ingest/kan Then the quality reduce and I get pixel-ed media.

But, when I run this following ffmpeg command: ffmpeg -i rtmp://ipbc-s.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3 -ar 44100 -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 10000k -g 60 -s 1920x1080 -f flv rtmp://{nginx_ip}/ingest/kan (I just added the "high quality" ffmpeg paramse: _-c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 10000k -g 60 -s 1920x1080_) Then the quality is good as expected (as the origin in that case).

Why should I add the ffmpeg params when I just want to stream the media to my nginx server? Shouldn't it stream as the origin quality without any transcoding?

ut0mt8 commented 6 years ago

If understand correctly you only want to restream an rtmp stream to nginx-rtmp . Theoretically ffmpeg doesn't have to transcode anything and just forward the rtmp stream as is. Have you try something simpler like https://datarhei.github.io/restreamer/ ? Anyway what you could be sure is that nginx-rtmp only transmux rtmp leaving h264 / aac untouched.

almoghzn commented 6 years ago

Yes, you got me right.

I'm trying to restream a live media.

The live media is streamed by HLS and RTMP. I'm using the rtmp option of the live media. The url of the live media is: rtmp://ipbc-s.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3

Then I sending this RTMP live stream to my nginx server with the nginx-rtmp module. Then my nginx server "dash" this rtmp stream.

Summary:

  1. Get the live media RTMP to my nginx server: application kan { exec_static ffmpeg -i rtmp://ipbc-s.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3 -ar 44100 -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 10000k -g 60 -s 1920x1080 -f flv rtmp://localhost/ingest/kan; }

  2. Ingest the RTMP stream into 3 variant bitrates: application ingest { live on; exec ffmpeg -i rtmp://localhost/$app/$name -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 500k -minrate 500k -maxrate 500k -bufsize 1000k -g 60 -s 640x360 -f flv rtmp://localhost/dash/$name_low -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 1500k -minrate 1500k -maxrate 1500k -bufsize 3000k -g 60 -s 1280x720 -f flv rtmp://localhost/dash/$name_med -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 10000k -g 60 -s 1920x1080 -f flv rtmp://localhost/dash/$name_high; }

  3. Dash the rtmp stream using your fork of rtmp module: `application dash { live on; allow publish all;

    dash on;
    dash_nested on;
    dash_path /tmp/dash;
    dash_fragment 3;
    dash_playlist_length 120;
    
    dash_variant _low   bandwidth="500000"  width="640"  height="360";
    dash_variant _med  bandwidth="1500000" width="1280"  height="720";
    dash_variant _high bandwidth="5000000" width="1920" height="1080" max;

    }`

Questions:

  1. Can I simplify this? as I see it, I running transcoding/encoding (I don't know what is the right terminology) multiple times (~4) for nothing. The stream I get from the rtmp live source is an HD 720p as I want to produce, Therefore I believe I don't need to re-encode it at all. Just need to "convert" rtmp to dash. Where I'm doing wrong?

  2. Here, when I just getting the live rtmp source and getting it to my nginx server: application kan { exec_static ffmpeg -i rtmp://ipbc-s.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3 -ar 44100 -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 10000k -g 60 -s 1920x1080 -f flv rtmp://localhost/ingest/kan; } I can do it without all the ffmpeg params: -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 10000k -g 60 -s 1920x1080 BUT, when I do so the output quality is very poor. Why? BTW, if I execute: ffmpeg -i rtmp://ipbc-s.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3 output.mp4 on my PC, the output.mp4 is in good quality (720p h264).

  3. Question about your addition of adaptive DASH: Why should we need to add the following properties to the "dash_variant": bandwidth, width, height? Can it infer this values from the stream/dash itself, we already configure it at the ingest command here: exec ffmpeg -i rtmp://localhost/$app/$name -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 500k -minrate 500k -maxrate 500k -bufsize 1000k -g 60 -s 640x360 -f flv rtmp://localhost/dash/$name_low -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 1500k -minrate 1500k -maxrate 1500k -bufsize 3000k -g 60 -s 1280x720 -f flv rtmp://localhost/dash/$name_med -c:a aac -strict -2 -ac 2 -b:a 128k -c:v libx264 -pix_fmt yuv420p -profile:v baseline -preset ultrafast -tune zerolatency -vsync cfr -x264-params "nal-hrd=cbr" -b:v 5000k -minrate 5000k -maxrate 5000k -bufsize 10000k -g 60 -s 1920x1080 -f flv rtmp://localhost/dash/$name_high;

ut0mt8 commented 6 years ago

If your original stream is already in the output format you want, yes you didn't need transcoding at all. Transmuxing : we only act on the container level and didn't alter alter the video and audio data. Transcoding : we alter / compress /resize the video and audio. In your case you want to restream the original rtmp flow to nginx rmtp without adding any variant. The configuration should be much more simple than that.

ut0mt8 commented 6 years ago

something like :

/usr/local/bin/ffmpeg -re -i rtmp://ipbcs.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3 -vcodec flv -acodec copy -f flv rtmp://nginx:1935/dash/flow;

should be sufficient. You should try to launch ffmepg command outside nginx for better visibility / debug.

almoghzn commented 6 years ago

So I tired your suggestion to restream this media using: /usr/local/bin/ffmpeg -re -i rtmp://ipbc-s.vidnt.com/ipbc_IPBCchannel11LVMRepeat/IPBCchannel11LVM_3 -vcodec flv -acodec copy -f flv rtmp://nginx:1935/dash/flow;

But then, when I'm trying to play this media using the DASH-IF player I get only audio, there is no media playing, just black screen.

ut0mt8 commented 6 years ago

Hum I'm not an expert of ffmepg and I don't think this is related to nginx-rtmp (rtfm the ffmepg manual) but I think I made a mistake so :

ffmpeg -i rmtp://input/stream -c copy -f flv rtmp://output/stream

should work

almoghzn commented 6 years ago

Hi ut0mt8,

Thank you for your kind help.

ffmpeg -i rmtp://input/stream -c copy -f flv rtmp://output/stream It's worked just fine!

I have another question for you: Why do I need to use nginx-rtmp at all if ffmpeg can make dash? I'll explain, nginx-rtmp take rtmp stream and create dash from it, right? (BTW, another question, nginx-rtmp can take only rtmp streams right? If I have HLS stream what do I need to do in order to create dash from it?) So I can just run ffmpeg command with -f dash out.mpd and it will create dash from the stream.

Where I goes wrong?

Thanks again.

ut0mt8 commented 6 years ago

I don't know very well ffmepg but if It can output dash you are good. Nginx rtmp as its name implies only take rtmp input. If you have HLS ingest I think ffmepg can take it but I don't know if it can output dash directly.

ut0mt8 commented 6 years ago

Close as there no activity. Feel free to open a new one if you have question.