这篇文章上次修改于 240 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

最近下了个 OBS 想拿来直播推流用, 但是发现还需要一个服务器. 而我平时根本就不碰直播平台, 于是干脆在内网搭建一台服务器, 不然我的软路由该着凉了.

编译 Nginx

没错, 还是它.

在原来的基础上再加一个参数重新编译就好了

模块地址: https://github.com/arut/nginx-rtmp-module

参数: --add-module=/www/compile/nginx-rtmp-module

服务器配置

需要新增一个上下文, 和之前的 http{} 是同级的.

# 选择自己需要的一个就行了
rtmp {
    server {
        listen 1935;
        chunk_size 4000;

        application small {
            live on;
        }

        application tv {
            live on;
            record all;
            record_path /www/live/tmp/tv;
            record_max_size 1K;
            record_unique on;
            allow publish 127.0.0.1;
            deny publish all;
        }

        application live {
            live on;
            exec ffmpeg -re -i rtmp://localhost:1935/$app/$name -vcodec flv -acodec copy -s 32x32 -f flv rtmp://localhost:1935/small/${name};
        }

        # 摄像头推流
        application webcam {
            live on;
            exec_static ffmpeg -f video4linux2 -i /dev/video0 -c:v libx264 -an -f flv rtmp://localhost:1935/webcam/mystream;
        }

        application hls {
            live on;
            hls on;
            hls_path /www/live/tmp/hls;
            hls_fragment 2s; # 设置HLS片段的时长
            hls_playlist_length 30s; # 设置HLS播放列表的时长
            hls_nested on; # 允许嵌套HLS播放列表
        }

        application dash {
            live on;
            dash on;
            dash_path /www/live/tmp/dash;
        }
    }
}

如果选择 hls 或者 dash 这种方式还需要添加两条 location 到 http.server 中让客户端访问.

        location /live {
            index index.m3u8;
            alias /www/live/tmp/hls;
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            add_header Cache-Control no-cache;
        }

推流设置

有两种方案, 一种是通过 OBS 给人用的, 还一种是通过 FFmpeg 配合一些操作实现某些特殊设备的开机静默启动(嘿嘿嘿

OBS 这里很简单, 串流服务器形如 rtmp://10.0.0.1:1935/hls, 但是我有点迷惑 rtmp://hls:// 居然都可用.

FFmpeg 我在之前的博客中也更新了, 但是发现有缓冲区溢出的问题, 还没完全解决. 测试设备是教学用一体机, 出现的问题主要有网络不稳定以及高频休眠, 尝试调参数依然不能避免. (笔记本测试的时候一切正常, 相同的命令放到另一台设备就会出问题

ffmpeg -f dshow -i video="Smart_Camera" -c:v h264_qsv -b:v 2500k -an -r 30 -f flv -fflags nobuffer -flags low_delay -strict experimental -reconnect 1 -reconnect_at_eof 1 -reconnect_streamed 1 -reconnect_delay_max 2 rtmp://10.247.241.5:1935/hls/class8

播放

rtmp 和推流设备的服务器信息保持一致就好了, hls 这种是通过 location 来发布 .m3u8 文件的.

随便找个支持 rtmp 协议的播放器就好了, hls 还能在网页播放但是可能存在跨域问题.

这里推荐 potplayer, mpv 这种本地播放器.

延迟

经过一番排插, 最后发现让延迟高达近十秒的是播放器本身原因, 通过 ffplay 添加 -fflags nobuffer 参数可以把延迟降到一秒以内, 进一步降低感觉有些难度了, 因为可能还要经过 ffmpeg 的两次编码.

题外话

我真的去看了一下 POE 的摄像头和交换机, 还发现有人拿相机直通给 Linux 当摄像头用. 当然最后还是不买了, 想到交换机还得占用排插直接劝退.

至于普通的家用摄像头, 不仅偏贵而且看上去不能接到 Linux 上玩, 最主要的还是我其实没这个需求, 我还挺好奇 /dev/video0 这个设备的.