近期在家里闲着没事干,然后和群员聊着聊着,突然想起了之前想要搭建的流式媒体服务器,但是没有搭建成功。然而在这个超长的寒假中,我成功实现了(后来发现很简单)
结构
在搭建后不久,我做了很多修改,大概是这个样子
前端:完全静态,因为是自己的流式媒体服务器,自己播着玩玩也用不到动态。
流式媒体服务器:Nginx 的rtmp模块。
后端:Nodejs,做实时评论用,关于为啥不用php等。。我觉得nodejs来的更快。当然代码都是Ctrl+C,Ctrl+V来的
前端
这里我推荐使用hls.js,因为hls流的话很方便,就是有点延时。。。代码可以自由发挥了。
搭建
我这里建议使用Debian系的Linux系统,当然Windows也不是不可以,我都会在后面放出。
为什么建议使用Debian系的Linux系统呢?因为apt一下很方便。其他可以可以自行搜索了,编译安装。
请额外放行端口:1935,3000(可能),80,443
PS:树莓派也可以
安装必要的软件包
首先准备一个纯净的系统(不是纯净的自己看着改代码)
# 更新系统
sudu apt update
# 安装nginx和rtmp模块及wget(万一没有)
sudo apt install nginx-full libnginx-mod-rtmp wget -y
设置nginx.conf
sudo vim /etc/nginx/nginx.conf
你需要在第一个server 前加一段
rtmp {
server {
listen 1935;
application live {
live on;
}
application hls {
live on;
hls on;
hls_path /var/www/html/hls;
hls_fragment 2s;
}
}
}
他看上去应该像这样:
hls_path你可以修改,但是建议放在和前端文件同级的一个目录下。
然后重启nginx
sudo systemctl restart nginx
此时rtmp服务器你就搭建完成了
就这么简单
现在你可以推个流试试了,串流密钥随便写。
使用OBS推流,服务器地址为:rtmp://IP:1935/live/,密钥随便
拉流:rtmp://IP:1935/live/你的密钥
HLS流:使用OBS推流,服务器地址为:rtmp://IP:1935/hls/,密钥随便
拉流:rtmp://IP:1935/hls/你的密钥
或者用浏览器播放hls的m3u8
http(s)://IP/hls/密钥.m3u8
实时评论
这里就直接用nodejs实现了
参考:https://www.jianshu.com/p/5539ccd8d9c4
首先安装nodejs和npm以及创建目录,安装依赖
sudo apt install nodejs npm -y
cd ~
mkdir livechat
cd livechat
npm install express socket.io
apt里的nodejs的版本是足够了的
创建一个目录,然后开始安装软件,代码在上面的URL里。
全部弄完后启动就行,然后试试能不能访问。能访问的话就可以配置nginx的反向代理了。
配置反向代理
为何要反向代理?因为支持https并且利用nginx的rtmp模块。
那为什么不直接用nodejs搭建rtmp服务器呢?因为我没尝试过,既然nginx都跑起来了,那顺便用nginx搭建其他网站也不是问题。
接下来你需要在现有的http{}中添加一个sever,你可以新建配置文件,或者直接在nginx.conf中写,如果你还要架设多个网站的话,我还是推荐新建配置文件,这里我就直接在nginx.conf中写了。
vim /etc/nginx/nginx.conf
server {
listen 8081;
server_name live.nwl.im;
location / {
proxy_pass http://127.0.0.1:3000/;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
# 为什么需要下面这段呢?因为我的教程里是设置的反代,如果不加这段是直接从nodejs那里读取,但是nodejs那里是没有ts和m3u8文件的。
location /hls {
#server hls fragments
types{
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
# 把下面的alias后面的目录改成和hls_path相同的目录。
alias temp/hls;
expires -1;
# 设置CORS,如果不需要将下面那一段删除
add_header 'Access-Control-Allow-Origin' '*';
}
}
他看起来应该像这样(可能会和我的不一样,我的配置文件也许和你的环境不符合,请按照你的实际环境修改),当然我这里是加了ssl的。如果你更改了nodejs的端口,你也需要在上方配置文件中修改一下proxy_pass部分。
然后检查nginx的配置文件是否有误
sudo nginx -t
如果返回类似如下消息,你的流式媒体服务器搭建完成了,接下来就是前端。
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重启nginx
sudo systemctl nginx restart
前端
这里我推荐前端使用nodejs,因为。。需要依靠socket.io
打开你按照上方URL中创建的index.html,你可以在里面加入如下视频标签和hls.js
<video muted="muted" preload="auto" id="video" controls></video>
<script src="https://cdn.bootcss.com/hls.js/0.13.2/hls.min.js"></script>
<script>
var video = document.getElementById('video');
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource('http(s)://你的IP或者域名/密钥.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'http(s)://你的IP或者域名/hls/密钥.m3u8';
video.addEventListener('loadedmetadata', function() {
video.play();
});
}
</script>
然后做些适当的修改,就完成了,接下来你可以把评论区整合进去。
我这放一下我的index.html,如果你喜欢的话,可以拿去用。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="renderer" content="webkit">
<link rel="stylesheet" href="//cdnjs.loli.net/ajax/libs/mdui/0.4.3/css/mdui.min.css" />
<link rel="icon" href="https://ivampiresp.com/wp-content/uploads/2020/02/cropped-illust_78879291_20200207_181713-1-32x32.jpg" sizes="32x32" />
<link rel="icon" href="https://ivampiresp.com/wp-content/uploads/2020/02/cropped-illust_78879291_20200207_181713-1-192x192.jpg" sizes="192x192" />
<link rel="apple-touch-icon" href="https://ivampiresp.com/wp-content/uploads/2020/02/cropped-illust_78879291_20200207_181713-1-180x180.jpg" />
<script src="//cdnjs.loli.net/ajax/libs/mdui/0.4.3/js/mdui.min.js"></script>
<title>iVampireSPのLive</title>
</head>
<body class="mdui-drawer-body-left mdui-appbar-with-toolbar mdui-theme-primary-indigo mdui-theme-accent-pink">
<header class="mdui-appbar mdui-appbar-fixed">
<div class="mdui-toolbar mdui-color-theme">
<span class="mdui-btn mdui-btn-icon mdui-ripple mdui-ripple-white" mdui-drawer="{target: '#main-drawer', swipe: true}"><i class="mdui-icon material-icons">menu</i></span>
<a href="#" class="mdui-typo-headline mdui-typo-title">iVampireSPのLive</a>
<div class="mdui-toolbar-spacer"></div>
</div>
</header>
<div class="mdui-drawer" id="main-drawer">
<div class="mdui-list" mdui-collapse="{accordion: true}" style="margin-bottom: 76px;">
<div class="mdui-collapse-item ">
<div class="mdui-collapse-item-header mdui-list-item mdui-ripple">
<i class="mdui-list-item-icon mdui-icon material-icons mdui-text-color-blue">near_me</i>
<div class="mdui-list-item-content">菜单</div>
<i class="mdui-collapse-item-arrow mdui-icon material-icons">keyboard_arrow_down</i>
</div>
<div class="mdui-collapse-item-body mdui-list">
<a href="./" class="mdui-list-item mdui-ripple ">刷新</a>
<a href="https://ivampiresp.com" class="mdui-list-item mdui-ripple ">博客</a>
</div>
</div>
</div>
</div>
<div class="mdui-container" style="float: left;">
<br />
<video muted="muted" preload="auto" class="mdui-video-fluid" poster="https://i.loli.net/2020/04/01/ylL1nsNXDdBxwMT.jpg" id="video" controls></video>
<script src="https://cdn.bootcss.com/hls.js/0.13.2/hls.min.js"></script>
<script>
var video = document.getElementById('video');
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource('http(s)://你的IP或者域名/hls/iVampireSP.com.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function() {
video.play();
});
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'http(s)://你的IP或者域名/hls/iVampireSP.com.m3u8';
video.addEventListener('loadedmetadata', function() {
video.play();
});
}
</script>
<h1 class="mdui-text-color-theme">实时评论区</h1>
<ul id="messages"></ul>
<form name="chat" action="">
<div class="mdui-textfield">
<label class="mdui-textfield-label">昵称</label>
<input class="mdui-textfield-input" id="username" type="text" placeholder="昵称" oninput="getUser()" autocomplete="on" required />
</div>
<div class="mdui-textfield">
<label class="mdui-textfield-label">实时评论</label>
<input class="mdui-textfield-input" id="comment" type="text" onclick="echoUser()" placeholder="请遵守格式,谢谢! 格式为:“昵称:内容”(不包括引号)" autocomplete="off" maxlength="35" required />
<br />
<button class="mdui-btn mdui-btn-raised mdui-ripple mdui-color-theme-accent">发送</button>
</div>
</form>
<script src="/socket.io/socket.io.js"></script>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript">
function getUser() {
userName = ($("#username").val());
}
function echoUser() {
$("#comment").attr("value", userName + ':');
}
var socket = io();
$('form').submit(function() {
//点击发送按钮,提交输入的信息
socket.emit('chat message', $('#comment').val());
$('#comment').val(userName + ':');
return false;
});
//接收到chat message时
socket.on('chat message', function(msg) {
//将chat message显示在页面
$('#messages').append($('<li>').text(msg));
});
</script>
<p>本直播页面是使用Nginx RTMP模块实现的,并且使用了hls.js和socket.io做到的接收流和实时评论,缺点是不能查看以前的评论。后端:nodejs。搭建教程:<a href="https://ivampiresp.com/2020/04/05/%e4%bd%bf%e7%94%a8nginx%e7%9a%84rtmp%e6%a8%a1%e5%9d%97%e6%90%ad%e5%bb%ba%e4%b8%80%e4%b8%aa%e6%b5%81%e5%bc%8f%e5%aa%92%e4%bd%93%ef%bc%88%e7%9b%b4%e6%92%ad%ef%bc%89%e6%9c%8d%e5%8a%a1%e5%99%a8%e5%b9%b6.html">点我查看</a></p>
</div>
</body>
</html>
接下来就是Windows端,Windows端nodejs部分和上面是一样的,nginx.conf少做修改也可以。
带rtmp的nginx Windows端:https://github.com/illuspas/nginx-rtmp-win32
接下来你可以随心所欲的修改了,比如添加一些功能。
希望你使用愉快~
tql,马克一下,之后想折腾
加油!(ง •_•)ง
路过吃瓜
大佬