Search code examples
nginxffmpegyoutubeoverlayrtmp

NGinx RTMP live stream text overlay and push to multiple


I have been banging my head against this wall for a long time. Hoping you all can get me over.

I have a live stream coming from an IP Camera to my computer.

Nginx publishes to YouTube and to an FFmpeg stream that takes a frame every minute to use for a static webcam image.

Here is the code with the exec_push that I've tried to use with no success. The YouTube stream and frame capture work fine. I have FFmpeg installed with freetype. This is all on MacOS X 10.15.4 Catalina with home-brew FFmpeg --HEAD installed.

Update: I should also say I have tried outputting the overlay using command line FFmpeg and it works great with this command:

/usr/local/bin/ffmpeg -i rtmp://localhost:1935/live/68.1. -vf drawtext="fontfile=/System/Library/Fonts/Supplemental/Arial.ttf:text='Stack Overflow': fontcolor=white: fontsize=24: box=1: [email protected]: boxborderw=5: x=(w-text_w)/2: y=(h-text_h)/2" /Users/user/Desktop/test.mp4

So it seems that the output portion is the part FFmpeg doesn't like in Nginx.conf

My thought is I should be passing the overlayed FFmpeg stream to the "overlay" app and have the stream published to Youtube and the frame capture from there. (And also potentially recorded).

Update: When I have tried point to a sh file to run the command rather than the direct FFmpeg exec_push I get:

[alert] 56849#0: kevent() error on 15 filter:-1 flags:4002 (2: No such file or directory)

Thanks so much!

rtmp {
server {
       listen 1935;
       chunk_size 4096;

       application live {
                live on;
                record off;
                exec_push /usr/local/bin/ffmpeg -i rtmp://localhost:1935/live/68.1. -vf drawtext="fontfile=/System/Library/Fonts/Supplemental/Arial.ttf:textfile=/Users/Shared/overlayescaped.txt: reload=1: fontcolor=white: fontsize=20: box=1: boxcolor=black@1: boxborderw=75: x=70: y=925" -c:v libx264 -maxrate 6000k -bufsize 4000k -c:a aac -b:a 160k -ar 44100 -b:a 128k -f mp4 rtmp://localhost:1935/overlay/test;
                #push rtmp://localhost:1935/overlay;

                }

        application overlay {
                live on;
                record off;
                push rtmp://a.rtmp.youtube.com app=live2 playpath=yourstreamkey;
                exec_push /usr/local/bin/ffmpeg -i rtmp://localhost:1935/overlay/$name -vf fps=1/60 /Users/Shared/stream/netcam.jpg;
                }

        }

}

Solution

  • The answer was:

    a) I must invoke the Ffmpeg command through a file for this to work. I'm not entirely sure why, but that is just the way it is.

    b) I wasn't able before to get logging info from Ffmpeg. It was because I was logging to the wrong spot. I needed to log to /tmp/ because of the unprivileged (nobody) user used by Nginx. Makes sense.

    c) At that point once the command was working from a file, I could see the actual errors that Ffmpeg was throwing and could troubleshoot them. Which had a lot to do with option placement, spacing, and ensuring it is a flv container, not an mp4 container.

    Here is the Nginx rtmp configuration I ended up with:

    rtmp {
            server {
                    listen 1935;
                    chunk_size 4096;
    
                    application live {
                                        live on;
                                        record off;
                                        meta copy;
                                        exec /Users/Shared/ffmpegcommand.sh $name;
                    }
    
                    application overlay {
                                        live on;
                                        record off;
                                        meta copy;
                                        push rtmp://a.rtmp.youtube.com app=live2 playpath=stream-key;
                                        exec_push /usr/local/bin/ffmpeg -i rtmp://localhost:1935/overlay/$name -vf fps=1/60 /Users/Shared/stream/netcam.jpg;
                    }
    
            }
    
    }
    

    And here is the Ffmpeg command I am using in the command file for the text overlay (now using -filter_complex, as -vf wasn't the proper option in this case).

    /usr/local/bin/ffmpeg -i rtmp://localhost:1935/live/68.1. -filter_complex drawtext="fontfile=/System/Library/Fonts/Supplemental/Verdana.ttf: textfile=/Users/Shared/overlayescaped.txt: reload=1: fontcolor=white: fontsize=17: box=1: boxcolor=black@1: boxborderw=80: x=80: y=935" -c:v libx264 -level 4.1 -maxrate 6000k -bufsize 4000k -c:a copy -f flv rtmp://localhost:1935/overlay/newlive 2>>/tmp/ffmpeg.error
    

    I also modified the audio options so that they copy straight from source as no encoding is needed.

    Finally, I created the overlay text file from a text file I already had. The existing overlay had a % symbol for humidity so I had to escape that character using sed in a bash script.

    escovlfiletmp='/Users/Shared/overlayescapedtmp.txt'
    escovlfile='/Users/Shared/overlayescaped.txt'
    overlaysearch="% B:"
    overlayreplace="\\\\\\% B:"
    
    sed -e "s/${overlaysearch}/${overlayreplace}/g" ${overlayfile} > ${escovlfile}
    

    I've attached a screen cap of the final video stream result. The entire black area is the overlay.

    Very happy.

    Thank you for all the resources on this website and elsewhere. It took me 4 days and many hours of constant searching but managed to piece it all together.

    enter image description here