系统是CentOS 7.9
整体逻辑是先搭建好Nginx服务器,前端发送用户手机号给node处理,node使用手机号生成独特的流密钥,将密钥返回给前端进行推流使用,用户拿到推流密钥之后使用OBS进行推流。nginx将RTMP流转换为HLS流,前端接收流并使用video.js进行直播。
服务器
安装依赖项
sudo yum update
sudo yum install epel-release
sudo yum install gcc gcc-c++ make zlib-devel pcre-devel openssl-devel git
下载Nginx和rtmp模块
cd /usr/local/src
sudo git clone https://github.com/arut/nginx-rtmp-module.git
sudo wget http://nginx.org/download/nginx-1.20.1.tar.gz
sudo tar -zxvf nginx-1.20.1.tar.gz
编译安装Nginx(如果报错查找rtmp文件路径是否正确)
cd nginx-1.20.1
sudo ./configure --with-http_ssl_module --add-module=../nginx-rtmp-module
sudo make
sudo make install
修改配置文件
vim /usr/local/nginx/conf/nginx.conf
添加如下代码
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
}
}
}
启动nginx
sudo /usr/local/nginx/sbin/nginx
查看是否启动成功
sudo /usr/local/nginx/sbin/nginx -t
重启nginx
sudo /usr/local/nginx/sbin/nginx -s reload
node后台
安装依赖项
npm install express mysql
链接数据库
// 导入 mysql 模块
const mysql = require('mysql')
// 创建数据库连接对象
const db = mysql.createPool({
host: "13.13.13.13",
port: "3333",
user: "api_ranni_cc",
password: "wrYi5YWXy3xT3yej",
database: "api_ranni_cc"
});
// 向外共享 db 数据库连接对象
module.exports = db
创建数据表
CREATE TABLE user_stream_info (
id INT AUTO_INCREMENT PRIMARY KEY,
phone VARCHAR(255) NOT NULL,
stream_key VARCHAR(255) NOT NULL,
stream_url VARCHAR(255) NOT NULL,
UNIQUE (phone)
);
创建js主文件
const express = require("express");
const crypto = require("crypto");
const app = express();
// 导入数据库
const db = require("./db/index");
// 解析 JSON 请求体
app.use(express.json());
// 解析 x-www-form-urlencoded 请求体
app.use(express.urlencoded({ extended: true }));
// 基础 RTMP 服务器地址
const rtmpServerUrl = 'rtmp://12.12.12.12:1935';
// 生成独特的流密钥
function generateStreamKey(phone) {
return crypto.createHash('sha256').update(phone + new Date().getTime()).digest('hex');
}
// 保存或更新用户的推流信息
function saveOrUpdateStreamInfo(phone, callback) {
const streamKey = generateStreamKey(phone);
const streamUrl = `${rtmpServerUrl}/${streamKey}`;
const query = `INSERT INTO user_stream_info (phone, stream_key, stream_url) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE stream_key = VALUES(stream_key), stream_url = VALUES(stream_url)`;
db.query(query, [phone, streamKey, streamUrl], (error, results) => {
if (error) {
return callback(error, null);
}
callback(null, { phone, streamUrl });
});
}
// 路由: 处理获取推流地址的请求
app.post("/getStreamUrl", (req, res) => {
// console.log(req.body);
const phone = req.body.phone;
if (!phone) {
return res.status(400).send("Phone number is required");
}
saveOrUpdateStreamInfo(phone, (error, streamInfo) => {
if (error) {
return res.status(500).send("Internal Server Error");
}
res.json({ streamUrl: streamInfo.streamUrl });
});
});
// 启动服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
前端Vue
安装video.js
npm install video.js
前端主文件(这里只演示了如何播放获取到的流,其余逻辑不做演示)
<template>
<div>
<video ref="videoPlayer" class="video-js vjs-default-skin" controls preload="auto" width="640" height="360">
<source :src="videoSrc" type="application/x-mpegURL" />
</video>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import videojs from 'video.js'
import 'video.js/dist/video-js.css'
const videoPlayer = ref(null)
const videoSrc = 'http://12.12.12.12/hls/027963e2ddd3ae1fda1816a7c4f5a31d41de745891148afee5208481c8946a39.m3u8'
onMounted(() => {
videoPlayer.value = videojs(videoPlayer.value)
})
onBeforeUnmount(() => {
if (videoPlayer.value) {
videoPlayer.value.dispose()
}
})
</script>