[toc]
背景
当今社会,无论工作还是生活,大家都离不开互联网,近几年随着移动互联网的日趋成熟,直播的地点和场景越发的丰富,直播正在为越来越多的行业、应用、社会生活提供各种有价值的赋能。
概述
本文以一个非常简单的实际例子,搭建一个直播所需要的基础软件支撑平台,浅尝直播业务中核心业务概念及他们的交互流程。
对于一场直播,大致会拥有如下环节:
- 主播通过直播设备将画面推送到直播平台
- 平台接收主播推送的画面
- 观众通过平台找到主播的直播画面,具体来说就是要找到主播的房间号
- 观众从平台拉取房间号中的直播画面
对于上述环节,可以抽象出如下的业务对象:
- 流媒体服务器,即一个直播平台,连通主播和观众,主播往流媒体服务器推直播画面,观众从流媒体服务器拉取直播画面,这里面的直播画面就是直播流
- 推流设备,主播通过推流设备将摄像头、麦克风等设备收集的电子信息推送到流媒体服务器,这里的推流设备可以是手机、笔记本电脑、台式机等等
- 拉流设备,观众通过拉流设备获取主播的画面,常见的拉流设备有手机、浏览器等等
可以实现上述业务流程的软件基础设施非常的多,本文将基于OBS+NGINX+VLC这个技术栈来讨论。这里面,OBS充当了主播推送画面的推流设备;NGINX充当了直播平台的流媒体服务器,具体来说是使用 nginx-http-flv-module 模块;VLC充当了观众拉取画面的拉流设备。
理论来说一场直播至少涉及三台设备,即推流设备、流媒体服务器、拉流设备。本文将仅提供两台设备。其中一台是笔记本电脑,用于使用OBS推流,并同时使用VLC拉流;另外一台是CentOS的服务器,用作流媒体服务器。
步骤
搭建流媒体服务器
nginx中的模块虽然就是类似插件的概念,但是它无法像VsCode那样轻松的安装扩展。针对像 nginx-http-flv-module 这样的 nginx 模块,仅能通过重新编译 nginx 源码的方式完成“插件的安装”。
nginx-http-flv-module 基于 nginx-rtmp-module 二次开发,拥有 nginx-rtmp-module 全部的功能,同时具备HTTP-FLV播放,这个功能就很Nice,有了这个就可以实现在浏览器中观看直播,针对推送端无需额外的配置,一个直播流推送到流媒体服务器,直接可以输出多种流,包括:rtmp、hls、flv,rtmp用于在桌面应用程序中播放,hls和flv用于在浏览器中播放,当然hls也可以在桌面应用程序中播放,在浏览器播放方式中flv的画面延迟明显由于hls。
需要注意的是 nginx-http-flv-module 要求nginx的版本大于等于1.2.6。由于nginx-http-flv-module包含了 nginx-rtmp-module 模块,所以不可将 nginx-http-flv-module 和 nginx-rtmp-module 同时编译,当我们编译完 nginx-http-flv-module 之后,其实就已经拥有了 nginx-rtmp-module 的完整功能。
核心步骤为:
- 查看当前nginx 的版本(假设安装位置为:/usr/local/nginx)
- 下载当前版本nginx的源代码
- 下载 nginx-http-flv-module 模块源代码
- 重新编译nginx并追加nginx-http-flv-module
- 将新编译好的 nginx 可执行文件拷贝到当前nginx安装目录(/usr/local/nginx/sbin)
详细步骤如下:
使用如下命令查看当前已经安装的nginx的版本
[root@bogon sbin]# ./nginx -V
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-http_dav_module --with-http_stub_status_module --with-http_addition_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre --with-http_ssl_module --with-http_gzip_static_module
V:小v仅打印版本号,大V既打印版本号,也打印扩展信息,这里要使用大V
拿到版本号的目的是待会要下载该版本的源代码
注意保存打印内容中的 arguments 后面的内容,后面编译会用到
下载 nginx 源码和 nginx-http-flv-module 的源码,示例代码如下:
wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar -zxvf nginx-1.18.0.tar.gz
git clone https://github.com/winshining/nginx-http-flv-module.git
进入nginx源码目录,使用如下命令重新编译nginx:
./configure --prefix=/usr/local/nginx --with-http_dav_module --with-http_stub_status_module --with-http_addition_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre --with-http_ssl_module --with-http_gzip_static_module --add-module=/home/cml/nginx-http-flv-module
make
- 使用configure 配置编译环境
- 将上面 保存的“arguments 后面的内容”作为configure 的第一个参数
- 第二个参数为 --add-module=/home/cml/nginx-http-flv-module ,即添加一个模块,模块源代码位置是 /home/cml/nginx-http-flv-module
- 使用make命令执行编译编译
编译成功后,在 bjs 中会有一个 名为nginx的可执行文件,这个就是编译好的nginx了, 里面包含已经安装的功能和新增加的nginx-rtmp-module,将这个可执行文件拷贝到当前安装目录(/usr/local/nginx/sbin)中就可以了。
注意拷贝之前需要停止nginx,否则会报当前文件繁忙,无法覆盖的错误。
通过如下命令验证安装是否正常:
nginx -V
若打印的信息中包含nginx-http-flv-module,说明安装好了。
当安装好了 nginx-http-flv-module 之后,就可以创建流媒体应用了。所谓的创建流媒体应用其实就是编写 nginx 的配置文件,如果需要创建一个名为 live 的流媒体应用,那么可以在 nginx.conf 中做如下配置:
# 以下内容放可在 nginx.conf 的最后,rtmp 配置块为顶级配置块
rtmp_auto_push on ;
rtmp {
server {
listen 1935; #监听的端口
notify_method get;
chunk_size 4000;
application live { #rtmp推流请求路径
live on;
# 添加 hls 支持
hls on;
hls_path /usr/local/nginx/html/hls;
hls_fragment 3;
hls_playlist_length 60;
# 允许从任何源push 流
allow publish all ;
# 允许从任何地方来播放流
allow play all;
# 20s内没有push,就断开连接
drop_idle_publisher 20s ;
}
}
}
- listen 1935:指定流媒体服务器的运行端口
- live :为流媒体应用的应用的名称,也即流媒体应用的唯一标识
- live on : 添加直播的支持
- hls_path:指定生成的m3u8文件的位置
之后就是创建http-flv端点和hls端点了,目的是让直播流可以在http协议上面传输直播画面。
若不创建,将仅可以使用rtmp协议拉流,即rtmp://ip:1935/live/stream_no;若创建了就可以使用hls或者flvjs来拉流播放了。
创建http-flv端点和hls端点同样是编辑nginx.conf来实现,如下示例配置:
http {
......
server {
listen 82;
server_name rtmpserver;
# 创建hls端点
location /hls {
add_header 'Access-Control-Allow-Origin' '*' ;
add_header 'Access-Control-Allow-Credentials' 'true' ;
types {
application/vnd.apple.mpegurl m3u8 ;
video/mp2t ts;
}
alias /usr/local/nginx/html/hls;
expires -1 ;
add_header 'Cache-Control' 'no-cache';
}
# 创建 flv 端点
location /flv {
flv_live on ;
chunked_transfer_encoding on;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
}
}
......
}
- listen 82 :指定 hls端点和flv端点的监听端口,此端口可以自定义,针对hls端点和flv端点可以分开设置不同的监听端口
- hls端点的标识为 hls,此标识可以自定义,拉流的时候会用到
- alias:指定m3u8文件的访问路径,需要和 "创建流媒体应用"中的hls_path配置保持一致
- flv端点的标识为flv,此标识可以自定义,拉流的时候会用到
使用OBS推流
OBS 是非常成熟的软件了,安装参考官网:https://obsproject.com/
假设约定的推拉流地址为 rtmp://192.168.1.115:1935/live/room-1
设置直播流来源为 视频采集设备 和 浏览器,其中视频采集设备就是笔记本的摄像头,浏览器为OBS内置浏览器并打开 https://time.is/zh/ 这个网址。最终的直播画面就是两个采集终端的画面叠加在一起,底部是一个网址,网页中有一个时钟,顶部是摄像头。
设置直播服务器和推流码:
- 服务器:即流媒体应用的地址,即 rtmp://192.168.1.115:1935/live
- 推流码:即当前推流唯一标识,可以随意指定,保证推拉流地址一致即可,示例为: room-1
点击开始直播,OBS就开始向流媒体服务器推流了。
此时就可以使用拉流客户端拉取直播画面了,同时hls_path 下将生成m3u8文件,文件名称为 room-1.m3u8,如下:
[root@bogon hls]# pwd
/usr/local/nginx/html/hls
[root@bogon hls]# tree -L 1
.
├── room-1-0.ts
├── room-1-10.ts
├── room-1-11.ts
├── room-1-12.ts
├── room-1-13.ts
├── room-1-14.ts
├── room-1-15.ts
├── room-1-1.ts
├── room-1-2.ts
├── room-1-3.ts
├── room-1-4.ts
├── room-1-5.ts
├── room-1-6.ts
├── room-1-7.ts
├── room-1-8.ts
├── room-1-9.ts
└── room-1.m3u8
使用VLC拉流
VLC是非常成熟的软件了,安装参考官网。
VLC拉流使用rtmp进行,拉流地址为:
rtmp://192.168.1.115:1935/live/room-1
使用flv.js播放器拉流
基于flv.js编写一个视频播放器,新建一个html文件,示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FLV.js Example</title>
<script src="https://cdn.jsdelivr.net/npm/flv.js@1.5.0/dist/flv.min.js"></script>
</head>
<body>
<h1>FLV.js Player</h1>
<video id="videoElement" width="640" height="360" controls></video>
<script>
// Check if the browser supports FLV.js
if (flvjs.isSupported()) {
var videoElement = document.getElementById('videoElement');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url: 'http://192.168.1.115:82/flv?port=1935&app=live&stream=room-1' // Replace with your FLV video URL
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
} else {
console.error('FLV.js is not supported in this browser.');
}
</script>
</body>
</html>
总结
本文简述了直播业务基本流程和相关的业务对象,并基于OBS+NGINX-VLC来搭建了一个直播需要的基础软件设施。其中使用了 nginx-http-flv-module 模块来实现浏览器基于flv.js的拉流。
实测flv.js播放器的延迟在2s内。
这里面无论是OBS、nginx-http-flv-module 还是VLC,都用到了 ffmpeg 这个音视频领域BOSS级别的软件。然而本文并未对ffmpeg做过多的介绍,如果期望搭建自己的商业化直播平台,或者期望做在线教育或者娱乐直播相关产品的技术团队,免不了最终都会指向 ffmpeg,尽早投入对 ffmpeg 的研究将会节省很多的研发资源和时间。