799967501@qq.com

添加实时直播接口(目前步步高用)

... ... @@ -5,6 +5,7 @@ var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var bbgRecordingRouter = require('./routes/bbgRecording');
var app = express();
... ... @@ -18,7 +19,18 @@ app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.all("*",function(req,res,next){
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin","*");
//允许的header类型
res.header("Access-Control-Allow-Headers","content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods","POST,OPTIONS");
next();
});
app.use('/', indexRouter);
app.use('/mp4record',bbgRecordingRouter)
// catch 404 and forward to error handler
app.use(function(req, res, next) {
... ... @@ -28,12 +40,13 @@ app.use(function(req, res, next) {
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// res.locals.message = err.message;
// res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
// res.status(err.status || 500);
// res.render('error');
res.send({ code: err.status || 500 });
});
module.exports = app;
... ...
{
"PROJECTWINCATALOG": "F:/project/web_capture_release/win-x64",
"PROJECTCATALOG": "/Users/zhangaichen/Desktop/学点云/webScreen",
"BACKMEDIACONFIG": {
"url": "https://pclive.xuedianyun.com/pcBase/pclive2/dev/index.html",
"recordMp4": true,
"classId": "",
"userId": 0,
"userName": "",
"userRole": "invisible",
"portalIP": "saas.xuedianyun.com",
"portalPort": 80,
"channels": 0,
"playRecord": 1,
"d": 21600000,
"s": 3000,
"fa": 15,
"k": 0,
"w": 1280,
"h": 720
}
}
... ...
var express = require('express');
var router = express.Router();
const { exec } = require('child_process');
const fs = require("fs");
const axios = require('axios');
const method = require("../config/method")
const { dayTimeYMD } = method
let classids = []
/**
*
* @param {*} id 课堂id
*/
class MediaCreat {
constructor() {
}
wrieLog(text) {
// 写入log
let logFile = `./log/${dayTimeYMD().ymd}.txt`
fs.appendFileSync(logFile, new Date().toLocaleString() + " " + text + '\r\n');
}
recordingCreat(id,siteId,classUrl,duration,width,height,frameRate,bitrate) {
this.wrieLog(" 课堂录制开始:------>" + id)
let fileConfig = this.getConfigFileJson()
if (!fileConfig) return false
const { BACKMEDIACONFIG, PROJECTWINCATALOG, PROJECTCATALOG } = JSON.parse(fileConfig)
let mediaDir = PROJECTCATALOG + "/media/"
let classDir = PROJECTCATALOG + "/media/" + siteId
let ymdDir = null
let timeDir = dayTimeYMD().ymd
ymdDir = PROJECTCATALOG + "/media/" + siteId + "/" + timeDir
if (!fs.existsSync(mediaDir)) {
fs.mkdirSync(mediaDir);
}
if (!fs.existsSync(classDir)) {
fs.mkdirSync(classDir);
}
if (!fs.existsSync(ymdDir)) {
fs.mkdirSync(ymdDir);
}
// let files = fs.readdirSync(ymdDir);
// let interValGetFile = setInterval(()=>{
// this.wrieLog("files:" + files)
// if (files.indexOf(id + ".mp4") != -1) {
// this.wrieLog("已存在:" + id + "课堂号,停止继续录制")
// return
// }
// if(!classUrl){
// classUrl = `${BACKMEDIACONFIG.url}?classId=${id}&recordMp4=${BACKMEDIACONFIG.recordMp4}&userId=${BACKMEDIACONFIG.userId}&userName=${BACKMEDIACONFIG.userName}&userRole=${BACKMEDIACONFIG.userRole}&portalIP=${BACKMEDIACONFIG.portalIP}&portalPort=${BACKMEDIACONFIG.portalPort}&channels=${BACKMEDIACONFIG.channels}"`
// }
// if(!duration){
// duration = BACKMEDIACONFIG.d
// }
let url = `${PROJECTWINCATALOG}/web_capture_c -o=${ymdDir}/${id}.mp4 -u="${classUrl}" -d=${duration} -s=${BACKMEDIACONFIG.s} -k=${BACKMEDIACONFIG.k} -w=${width} -h=${height} -fa=${frameRate} -vb=${bitrate}`
this.wrieLog("全地址"+url)
exec(url, { maxBuffer: 1073741824 }, (err, stdout, stderr) => {
if (err != null) {
this.wrieLog(" 错误" + id + ":" + err)
this.wrieLog(" 错误 stdout" + id + ":" + stdout)
this.wrieLog(" 错误 stderr" + id + ":" + stderr)
// 删除已存元素
classids.splice(classids.findIndex(item => item === id),1)
return
}
// let files = fs.readdirSync(ymdDir);
// if (files.indexOf(id + ".mp4") != -1) {
// 删除已存元素
classids.splice(classids.findIndex(item => item === id),1)
this.sendMediaInfo(siteId,id,timeDir)
// }
})
}
// 上报地址
async sendMediaInfo(siteId,id,timeDir){
// https://testmp4.obs.cn-north-4.myhuaweicloud.com/oss/media/eebbktest/20210326/1657547103.mp4
let MediaUrl = `https://testmp4.obs.cn-north-4.myhuaweicloud.com/oss/media/${siteId}/${timeDir}/${id}.mp4`
let urlSizeId = {
"eebbktest": "gdbbkwxyace",
"gdbbk":"gdbbkwx",
"gdbbkdev":"gdbbkwxtest"
}
let requestUrl = `https://${urlSizeId[siteId]}.xuedianyun.com/bbgserver/app/course/updateRecordUrl`
let result = await axios.post(
requestUrl,
{meetingNumber:id,url:MediaUrl},
{headers: {'orgId':siteId }}
)
if(result.data){
this.wrieLog("更新视频地址结果:"+JSON.stringify(result.data))
}
}
getConfigFileJson() {
const buffer = fs.readFileSync(process.cwd() + "/config/realTimeConfig.json")
return String(buffer)
}
}
/**
* {
* "classId":[{ classId: '389675110', siteId: 'kuaikuenglish' }]
* }
*/
router.post('/recording/:id', function (req, res, next) {
new MediaCreat().wrieLog("录制启动:------>")
let fileConfig = new MediaCreat().getConfigFileJson()
if (!fileConfig) return false
/**
* classId:课堂号
* siteId:机构编码
* url:课堂地址
* duration:录制时长
* width height 录制视频宽高
* frameRate 帧率
* bitrate 码率
*/
let { classId,siteId,url:classUrl,duration,width,height,frameRate,bitrate } = req.body
if (classId && siteId && classUrl && duration && width && height && frameRate && bitrate) {
if(!Number.isInteger(classId) || !Number.isInteger(duration) || !Number.isInteger(width) || !Number.isInteger(height) || !Number.isInteger(frameRate) || !Number.isInteger(bitrate)){
res.send({ code: "3", message: "参数类型错误" });
return
}
let maxTime = 10*60*60*1000
if(duration < 0 || duration > maxTime){
res.send({ code: "4", message: "参数范围错误" });
return
}
// 避免多次重复课堂号请求
if(!classids.includes(classId)){
// 没有正在录制的该课堂
classids.push(classId)
bitrate = bitrate * 1024 // 转换 * 1024
new MediaCreat().recordingCreat(classId, siteId,classUrl,duration,width,height,frameRate,bitrate)
res.send({ code: "0" });
}else{
res.send({ code: "2", message: "重复请求课堂号" });
}
} else {
res.send({ code: "1", message: "缺少参数" });
}
})
module.exports = router;
... ...