本文介绍了如何用ffmpeg和nginx实现推流,服务器收到推流请求后,进行鉴权,之后用ffmpeg filter对视频做分析,并将结果编码推流到nginx服务器。手机或PC客户通过web预览hls.

主要流程:

  • ffmpeg推流到pingos搭建的rtmp服务器, rtmp服务器支持hls
  • rtmp服务器收到push请求后,通过http协议将流信息传入鉴权http服务器
  • 鉴权服务收到请求后,判断是否合法,如果不合法则返回404,则客户端推流失败
  • 如果鉴权成功,则创建ffmpeg进程,从上面的rtmp输入源拉流,通过ffmpeg filter对视频做进一步处理(这里以logo叠加为例),再推理到rtmp服务器
  • 最后通过html5的video功能播放hls

url参数说明:

  • app name:input。input为客户端推流 output为视频filter处理后推流

  • stream name: %token%%model_level%%detection_size%%detection_thresold%%encode_bitrate%_%uuid%
    如: Hi20240217_0_1280_20_2000000_uuid2

  • token: 固定为Hi20240217,防止非法用户推流

  • model_level: 算法等级别[0,1,2,3],级别越高精度越高

  • detection_size: 监测算法的输入分辨率,越大,精度越高,性能越低

  • detection_thresold: 检测结果置信度过滤的阈值

  • encode_bitrate: 编码的码流bps

  • uuid: 用户自定义不包括以下字符:_?&

版本信息

操作步骤

搭建rtmp服务

安装pingos

wget https://github.com/pingostack/pingos/archive/refs/tags/v1.0.tar.gz
tar -xf v1.0.tar.gz
cd pingos-1.0/
rm -rf /usr/local/pingos/
./release.sh -i

配置nginx(/usr/local/pingos/conf/nginx.conf) http端口为:8081

user  root;
daemon on;
master_process on;
worker_processes  1;
error_log  logs/error.log  info;
worker_rlimit_nofile 102400;
worker_rlimit_core   2G;
working_directory    /tmp;
pid        logs/nginx.pid;
events {
    use epoll;
    worker_connections  65535;
    multi_listen unix:/tmp/http 8081;
    multi_listen unix:/tmp/rtmp 1935;
    dynamic_refresh_interval 5s;
    dynamic_domain_buckets   1001;
    resolver 114.114.114.114  valid=1m;
    resolver_timeout 30s;
}

rtmp {
    log_format log_bandwidth '{"app":"$app","name":"$name","bitrate":$bitrate,"args":"$args","timestamp":$ntp,"ts":"$time_local","type":"$command","remote_addr":"$remote_addr","domain":"$domain"}';
    access_log logs/bandwidth.log log_bandwidth trunc=60s;
    server {
        listen 1935;
        serverid 000;
        out_queue 10240;
        server_name live.pingos.io;
        rtmp_auto_pull on;
        rtmp_auto_pull_port unix:/tmp/rtmp;

        application input {
            live on;
            hls on;
            hls_path /tmp/hls/input;
            hls_fragment 4000ms;
            hls_playlist_length 12000ms;
            hls_type live;
            mpegts_cache_time 20s;
            wait_key on;
            wait_video on;
            cache_time 1s;
            send_all on;
            low_latency on;
            hevc_codecid  12;
            oclp_publish    http://127.0.0.1:9990/video/notify/publish args=stream=$stream stage=start,done;
        }
        application output {
            live on;
            hls on;
            hls_path /tmp/hls/output;
            hls_fragment 4000ms;
            hls_playlist_length 12000ms;
            hls_type live;
            mpegts_cache_time 20s;
            wait_key on;
            wait_video on;
            cache_time 1s;
            send_all on;
            low_latency on;
            hevc_codecid  12;
        }
    }
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_X-Forwarded-For" "$http_X-Real-IP" "$host"';
    proxy_headers_hash_max_size 51200;
    proxy_headers_hash_bucket_size 6400;
    client_max_body_size 4096m;
    proxy_buffer_size 10240k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
    proxy_buffers 16 10240k; #proxy_buffers缓冲区,网页平均在32k以下的设置
    proxy_busy_buffers_size 20480k; #高负荷下缓冲大小(proxy_buffers*2)
    proxy_temp_file_write_size 20480k;#设定缓存文件夹大小,大于这个值,将从upstream服务器传
    access_log  logs/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen 8081;
        location /rtmp_stat {
            rtmp_stat all;
            rtmp_stat_stylesheet /stat.xsl;
        }
        location /xstat {
            rtmp_stat all;
        }
        location /sys_stat {
            sys_stat;
        }
        location /sys_stat_proxy/ {
                rewrite ^/proxy/(.*) /sys_stat break;
                proxy_pass http://$1:;
        }
        location ~ .mp4$ {
            root html;
        }
        location /control {
            rtmp_control all;
        }
         location /flv {
             flv_live 1935 app=live;
            chunked_transfer_encoding off;
         }
         location /ts {
             ts_live 1935 app=live;
             expires -1;
             add_header 'Access-Control-Allow-Origin' '*';
             add_header "Access-Control-Allow-Credentials" "true";
             add_header "Access-Control-Allow-Methods" "*";
             add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token";
             add_header "Access-Control-Expose-Headers" "*";
         }
         location /input {
             types {
                 application/vnd.apple.mpegurl m3u8;
                 video/mp2t ts;
             }
             root /tmp/hls;
             expires -1;
             add_header Cache-Control no-cache;
             add_header 'Access-Control-Allow-Origin' '*';
             add_header "Access-Control-Allow-Credentials" "true";
             add_header "Access-Control-Allow-Methods" "*";
             add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token";
             add_header "Access-Control-Expose-Headers" "*";
         }
         location /output {
             types {
                 application/vnd.apple.mpegurl m3u8;
                 video/mp2t ts;
             }
             root /tmp/hls;
             expires -1;
             add_header Cache-Control no-cache;
             add_header 'Access-Control-Allow-Origin' '*';
             add_header "Access-Control-Allow-Credentials" "true";
             add_header "Access-Control-Allow-Methods" "*";
             add_header "Access-Control-Allow-Headers" "Content-Type,Access-Token";
             add_header "Access-Control-Expose-Headers" "*";
         }
         location / {
             chunked_transfer_encoding on;
             root html/;
         }
    }
}

启动nginx服务

cd /usr/local/pingos/
killall -9 nginx
./sbin/nginx
cd -

搭建rtmp鉴权和启动视频处理的服务

下载ffmpeg用于拉流、视频处理、推流

wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
tar -xf ffmpeg-release-amd64-static.tar.xz

rtmp推流服务的鉴权服务代码(rtmp_auth_srv.py)

import os
from flask import Flask,redirect,Response,request,jsonify
import subprocess
from urllib import parse
from urllib.parse import urlparse
from flask import abort
import psutil
import time
import os
import os.path
from ctypes import *
import time
import psutil
import logging

app = Flask(__name__,static_folder="")

def judgeprocess(processname):
    try:
        pl = psutil.pids()
        for pid in pl:
            if psutil.Process(pid).name() == processname:
                return pid
        else:
            return None
    except:
        return None

02-27 21:17