(Ubuntu)自己搭建直播平台,使用 Nginx RTMP HTTP-FLV,DPlayer播放,支持弹幕Danmaku
系统只因酱 Lv114514

前言

最近捣鼓了一下直播,花了差不多半个月的时间吧(开学了搞技术的时间就少),差不多实现了直播推流+拉流和弹幕发送功能,使用Frp内网穿透之后延迟极限可以达到2秒。

想了解各种直播相关协议推荐观看这个视频:

最终效果

也可以到本站直播页观看使用本教程方法搭建的直播平台,不定时开播

视频教程

哔哩哔哩

准备工作(前提条件)

1.一个Linux系统环境,这里推荐Ubuntu

可以使用物理机安装、VMWare虚拟机安装、购买安装Ubuntu系统的VPS、WSL2、手机Termux跑proot/chroot容器等方式运行Ubuntu,具体过程这里就不赘述了

2.国际互联网环境

由于众所周知的原因,可能会遇到无法连接到github或nginx官网的情况,这时候有国际互联网环境就可以完美解决这个问题,工具自找

3.一个公网IP地址(可选,如果你不局限于内网观看直播的话)

要满足这个条件,最简单的,可以使用VPS搭建直播服务器;如果家中有公网IP,可以使用家中设备搭建直播服务器;再不行,可以使用Frp这类型的内网穿透工具来映射至公网(我就使用这种方法)

 

正式部分

编译Nginx

Nginx是目前主流的高性能开源Web服务器,但是原生Nginx并不支持RTMP协议,需要将RTMP模块编译进Nginx

如果之前有安装Nginx最好卸载掉

1
apt autopurge nginx*

1. 安装软件包依赖

复制运行以下命令:

1
2
apt update
apt install wget git tar gcc vim ffmpeg openssl libpcre3-dev zlib1g-dev make libgd-dev libpcre3 libssl-dev

2.下载Nginx源代码

Nginx下载页面下载源码的tar.gz压缩文件,推荐nginx-1.22.0.tar.gz,目前Ubuntu官方软件源中的Nginx就是这个版本,当然你也可以选择更新的

使用命令下载并解压nginx-1.22.0.tar.gz:

1
2
3
4
wget https://nginx.org/download/nginx-1.22.0.tar.gz
tar zxvf nginx-1.22.0.tar.gz
rm nginx-1.22.0.tar.gz
cd nginx-1.22.0

3.下载nginx-http-flv-module

nginx-http-flv-module是一个基于nginx-rtmp-module的第三方模块,包含所有nginx-rtmp-module的功能。项目中文文档

克隆模块仓库

1
git clone https://github.com/winshining/nginx-http-flv-module.git

4.编译并安装

配置编译器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
./configure --prefix=/usr/local/nginx \
--user=$USER \
--with-pcre \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_image_filter_module \
--with-http_slice_module \
--with-mail \
--with-threads \
--with-file-aio \
--with-stream \
--with-mail_ssl_module \
--with-stream_ssl_module \
--add-module=./nginx-http-flv-module

编译并安装

1
2
make
make install

将编译出来的nginx二进制文件链接到/usr/local/sbin/目录中

1
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/

查看Nginx版本

1
nginx -v

正常情况下会输出你编译的Nginx版本

nginx version: nginx/1.22.0

配置RTMP推流服务器

使用你喜爱的文本编辑器打开nginx配置文件,我使用vim

1
vim /usr/local/nginx/conf/nginx.conf

在event块和http之间添加rtmp块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
rtmp {
server {
listen 1935; #监听端口
chunk_size 4096;
application live { #live是直播流应用名,可以改成其它
live on;
meta off; #为了兼容flv.js
hls on;
hls_path /tmp/hls; #hls拉流缓存存放地址
hls_fragment 4;
hls_playlist_length 30; #指定hls_path文件夹中的切片(ts格式)数量
record off;
allow play all; #任何人均可拉流
}
}
}

配置HTTP-FLV和HLS拉流服务器

在配置文件中的http块中添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
listen 8080; #监听端口
server_name localhost;

location / {
flv_live on; #打开http-flv服务
chunked_transfer_encoding on;
add_header 'Access-Control-Allow-Origin' '*'; #允许跨域
add_header 'Access-Control-Allow-Credentials' 'true';
}
location /hls { #打开hls服务
add_header 'Access-Control-Allow-Origin' '*'; #允许跨域
add_header 'Access-Control-Allow-Credentials' 'true';
types {
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias /tmp/hls;
expires -1;
}
}

保存退出配置文件,启动Nginx服务器:

1
nginx

测试推流

这里示例使用ffmpeg进行简单推流

1
ffmpeg -re -i /root/Videos/test.mp4 -c copy -f flv rtmp://127.0.0.1:1935/live/1

命令解释(ChatGPT生成):

  1. ffmpeg: 这是FFmpeg工具的命令行启动命令,它用于处理多媒体文件。

  2. -re: 这是一个选项,表示以实时模式(real-time)播放输入文件。在实时模式下,FFmpeg会以与视频的帧速率相匹配的速度处理视频,而不是尽可能快地处理它。这通常用于模拟直播流,以防止过快处理视频。

  3. -i /root/Videos/test.mp4: 这是输入文件的路径和名称。在这个例子中,输入文件是位于/root/Videos/目录下的test.mp4文件。

  4. -c copy: 这是一个选项,指定了视频和音频的编解码方式。copy表示将输入文件中的视频和音频以原样复制到输出文件,而不进行任何重新编码。这可以加快处理速度,尤其是当输入文件已经包含所需的编解码格式时。

  5. -f flv: 这是一个选项,指定了输出文件的格式。在这个例子中,输出文件将以Flash视频(FLV)格式保存。

  6. rtmp://127.0.0.1:1935/live/1: 这是输出文件的目标地址。它使用RTMP(Real-Time Messaging Protocol)协议,将处理后的视频数据流推送到本地主机上的RTMP服务器。具体来说,它将数据推送到127.0.0.1(本地主机)的1935端口上的live应用程序,而1是流的名称。这个地址通常用于流媒体服务器,以便将视频流发送到网络上的观众。

命令后边rtmp://127.0.0.1:1935/live/1的“1”叫推流密钥,自建服务器可以随便填写,作用类似于直播房间号,可以使一个应用处理多个直播流

FFmpeg出现比特率、视频速度等信息即为测试推流成功

测试拉流

推荐使用开源的VLC media player

以Windows端的VLC为例,点击左上角的媒体(M),点击打开网络串流(N),然后点击网络(N),在URL栏中输入http://[服务器IP]:8080/?port=1935&app=live&stream=1

这里的port就是服务器中RTMP推流端口,app就是推流应用程序,stream就是房间号(或者叫推流密钥)

点击播放(P),稍等片刻后看到FFmpeg推的视频即为测试拉流成功

image

使用DPlayer在支持HTML5的浏览器中拉流

为了保证直播观看的方便性,最优解就是在支持HTML5的浏览器播放直播流(除非是古董浏览器都支持HTML5)

DPlayer是一个开源的,基于css和JavaScript的HTML5网页视频播放器,在GitHub开源 开源地址

1.创建一个页面

打开Nginx配置文件,在http块中添加以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {

listen 8000; #监听端口
server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

location / {
root live; #网站文件根目录
index index.html index.htm;
types {
application/javascript js;
text/css css;
text/html html;
}
}
}

保存退出,创建网站根目录文件夹

1
mkdir /usr/local/nginx/live

重启Nginx服务器

1
nginx -s reload

2.下载Dplayer、flv.js、hls.js

进入到网站根目录文件夹中,创建一个子文件夹以存放这些文件,然后下载并解压

1
2
3
4
5
6
7
8
9
10
11
12
cd /usr/local/nginx/live
mkdir dplayer
cd dplayer
wget https://jsmirror.xtzyj.top/npm/dplayer/dist/DPlayer.min.css
wget https://jsmirror.xtzyj.top/npm/dplayer/dist/DPlayer.min.js
wget https://github.com/bilibili/flv.js/releases/download/v1.6.2/flv.min.js
wget https://github.com/video-dev/hls.js/releases/download/v1.4.12/release.zip
apt install p7zip-full -y
7z x ./release.zip
mv dist/* .
rm -rf dist
rm release.zip

3.配置DPlayer(使用flv.js)

在网站根目录创建index.html

1
vim /usr/local/nginx/live/index.html

这是一个示例HTML代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>系统只因家直播Demo</title>
<link class="dplayer-css" rel="stylesheet" href="http://192.168.0.21:8000/dplayer/DPlayer.min.css">
</head>
<body>
<font color="red">直播</font>
<div id="player" style="width: 100%"></div>

<script src="http://192.168.0.21:8000/dplayer/flv.min.js"></script>
<script src="http://192.168.0.21:8000/dplayer/DPlayer.min.js"></script>

<script type="application/javascript">
function createApiBackend (url, onMessage) {
var ws;
var connect = function () {
ws = new WebSocket(url);
ws.onmessage = function (event) {
onMessage(JSON.parse(event.data));
};
ws.onclose = function () {
// Try to reconnect in 5 seconds
setTimeout(connect, 5000);
};
};
var connected = false;
window.addEventListener('beforeunload', function () {
ws.onclose = null;
ws.close();
});
return {
read: function (options) {
if (connected) {
return;
}
connected = true;
connect();
options.success();
},
send: function (options) {
ws.send(JSON.stringify(options.data));
options.success();
}
};
}

var dp = new DPlayer({
container: document.getElementById('player'),
live: true,
autoplay: true,
danmaku: false,
lang: "zh-cn",
apiBackend: createApiBackend('ws://192.168.0.21:1207', function (dan) {
dp.danmaku.draw(dan);
}),
video: {
url: 'http://192.168.0.21:8080/?port=1935&app=live&stream=1',
type: 'flv'
}
});
</script>
</body>
</html>

记得将IP改成你自己的,stream=1的1要和推流源保持一致

保存退出后,浏览器访问http://[服务器IP]:8000,正常情况下,将出现一个DPlayer播放器,如果访问是下载文件,在地址栏添加/index.html;如果不显示,检查HTML语法是否正确,或者查看Nginx的日志文件

1
2
cat /usr/local/nginx/logs/access.log
cat /usr/local/nginx/logs/error.log

*配置DPlayer(使用hls.js)

由于iOS不支持Media Source Extensions,故无法播放flv.js直播流

解决方案是使用hls.js替代hls.js,缺点是延迟有30秒左右,这比起flv.js 2秒的延迟显得延迟非常大,尤其是如果要直播弹幕的话会导致别人看到是实时画面,iOS用户看的是30秒前的画面,导致iOS端弹幕画面不同步

要解决这个缺点只能去苹果公司应聘然后给iOS开发出MSE要不然就是众生平等给全端使用hls.js(

我使用子页面的方式将HTTP-FLV拉流方式和HLS拉流方式共存

在DPlayer网站根目录创建一个文件夹来存放hls.js DPlayer页面文件

1
2
cd /usr/local/nginx/live
mkdir hls

将根目录的index.html复制到hls文件夹中并编辑

1
2
cp ./index.html hls
vim hls/index.html

将HTML文件中的

1
<script src="http://192.168.0.21:8000/dplayer/flv.min.js"></script>

改为

1
<script src="http://192.168.0.21:8000/dplayer/hls.min.js"></script>

注意这里的IP仅为示例,以你为准

将HTML文件中的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var dp = new DPlayer({
container: document.getElementById('player'),
live: true,
autoplay: true,
danmaku: false,
lang: "zh-cn",
apiBackend: createApiBackend('ws://192.168.0.21:1207', function (dan) {
dp.danmaku.draw(dan);
}),
video: {
url: 'http://192.168.0.21:8080/?port=1935&app=live&stream=1',
type: 'flv' <-------------------
}
});

改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var dp = new DPlayer({
container: document.getElementById('player'),
live: true,
autoplay: true,
danmaku: false,
lang: "zh-cn",
apiBackend: createApiBackend('ws://192.168.0.21:1207', function (dan) {
dp.danmaku.draw(dan);
}),
video: {
url: 'http://192.168.0.21:8080/?port=1935&app=live&stream=1',
type: 'hls' <-------------------
}
});

将HTML文件中的

1
url: 'http://192.168.0.21:8080/?port=1935&app=live&stream=1',

改为

1
url: 'http://192.168.0.21:8080/hls/1.m3u8',

这个1是推流密钥,确保和推流时填写的推流密钥一致

保存退出后,在之前的网址中添加/hls即可访问使用HLS拉流的直播页面

使用Websocket+DPlayer搭建直播弹幕服务

DPlayer作为一个播放器有另一个优点:支持渲染弹幕。但是在官方文档中,只有简单的示例,在直播弹幕的版块也只是一笔略过,好在GitHub中有大佬开发出了专用于DPlayer的Websocket弹幕服务器:dplayer-live-backend

1.安装Node.js

运行以下命令安装Node.js

1
apt install nodejs npm -y

2.安装dplayer-live-backend

在网站目录外克隆这个仓库

1
2
git clone https://github.com/Izumi-kun/dplayer-live-backend.git
cd dplayer-live-backend

安装所需的依赖

1
npm i

如果出现类似于这个的输出

1 critical serverity vulnerability


To address all issues, run:
  npm audit fix


Run `npm audit` for details.

就运行这个命令修复一下:

1
npm audit fix

3.修改server.js

此代码来自项目Issues#2

1
vim ./server.js

将这两个变量

1
2
var hexColorRegExp = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
var typeRegExp =/^(top|bottom|right)$/;

更改为以下形式,因为dplayer的消息格式发生了变化。

1
2
var hexColorRegExp = /^\d{8}$/
var typeRegExp = /^(0|1|2)$/;

4.运行弹幕服务器

运行

1
node ./server.js

成功运行时的输出:

WebSocket server started on port: 1207

你可以通过传递--port参数来自定义服务器端口,如

1
node ./server.js --port=1207

后台运行

1
node ./server.js &

5.DPlayer开启弹幕

编辑DPlayer网站HTML文件

1
vim /usr/local/nginx/live/index.html

将其中的

1
danmaku: false,

改为

1
danmaku: true,

然后在下面把ws地址改为服务器的IP和端口

如果有hls页面的话,也要一起改一遍

1
vim /usr/local/nginx/live/hls/index.html

这时DPlayer就出现了发送弹幕的按钮了,左边可以调节发送设置

image

正常来说到此为止就成功搭建一个直播平台了。

使用OBS Studio推流

1.下载OBS Studio

进入OBS官网,然后下载适用于你操作系统的版本

2.布局界面

OBS Studio可以制作各种各样不同的布局,可以点击下方菜单栏的+号添加元素

3.进行推流

点击左上角文件(F),选择设置(S),点击左侧的直播 ,将服务器改为自定义,然后填写RTMP服务器地址,推流密钥自建服务器随便写,拉流是填写一致的推流密钥就行,保存后点击右下角开始直播即可开启推流

使用Frp进行内网穿透

本着能白嫖就白嫖的原则,推荐 乐青映射 完全免费, 高自由度,流量大,稳定(非广告)

需要穿透DPlayer网页服务端口、HTTPFLV-HLS服务端口、弹幕服务端口

Frp使用方法这里就不赘述了,教程一抓一大把,这里只说一下坑点:Nginx的那个DPlayer页面的内网端口要和穿透的远程端口一致,否则有可能给你重定向端口,造成无法访问

注意事项(自助纠错)

1.如果要套tls,那么套tls的http要改为https,ws要改为wss,注意如果网页套了tls那么网页内的所有资源都要套tls不然无法加载

2.OBS Studio长期运行会让电脑一直发烫容易缩短电脑寿命,Windows11以上可以在任务管理器中给进程开启效能模式来缓解,或者改用FFmpeg推流

3.如果你开启了HLS协议拉流,那么Nginx会循环往硬盘中写入直播流TS文件,长期使用会加速缩短硬盘寿命,解决方法是挂载一段内存地址然后更改缓存来存取这些TS文件(未经测试):

1
mount -t tmpfs -o size=4g tmpfs /data

4.OBS Studio的RTMP服务器地址填完后面一定要确保后面有斜杠/,不然会推流失败

5.服务器配置里不要填写127.0.0.1或者localhost等本地回环地址,要填写内网/公网IP,不然其它设备无法访问

 评论
评论插件加载失败
正在加载评论插件