[mirotalksfu] - add RTMP server and multi-source streaming!, update dep
هذا الالتزام موجود في:
175
app/src/Room.js
175
app/src/Room.js
@@ -1,6 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const config = require('./config');
|
||||
const crypto = require('crypto-js');
|
||||
const RtmpFile = require('./RtmpFile');
|
||||
const RtmpUrl = require('./RtmpUrl');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const Logger = require('./Logger');
|
||||
const log = new Logger('Room');
|
||||
|
||||
@@ -50,6 +56,11 @@ module.exports = class Room {
|
||||
this.router = null;
|
||||
this.routerSettings = config.mediasoup.router;
|
||||
this.createTheRouter();
|
||||
|
||||
// RTMP configuration
|
||||
this.rtmpFileStreamer = null;
|
||||
this.rtmpUrlStreamer = null;
|
||||
this.rtmp = config.server.rtmp || false;
|
||||
}
|
||||
|
||||
// ####################################################
|
||||
@@ -66,6 +77,12 @@ module.exports = class Room {
|
||||
isLobbyEnabled: this._isLobbyEnabled,
|
||||
hostOnlyRecording: this._hostOnlyRecording,
|
||||
},
|
||||
rtmp: {
|
||||
enabled: this.rtmp && this.rtmp.enabled,
|
||||
fromFile: this.rtmp && this.rtmp.fromFile,
|
||||
fromUrl: this.rtmp && this.rtmp.fromUrl,
|
||||
fromStream: this.rtmp && this.rtmp.fromStream,
|
||||
},
|
||||
moderator: this._moderator,
|
||||
survey: this.survey,
|
||||
redirect: this.redirect,
|
||||
@@ -74,6 +91,164 @@ module.exports = class Room {
|
||||
};
|
||||
}
|
||||
|
||||
// ##############################################
|
||||
// RTMP from FILE
|
||||
// ##############################################
|
||||
|
||||
isRtmpFileStreamerActive() {
|
||||
return this.rtmpFileStreamer;
|
||||
}
|
||||
|
||||
async getRTMP(dir = 'rtmp') {
|
||||
const folderPath = path.join(__dirname, '..', dir);
|
||||
|
||||
// Create dir if not exists
|
||||
if (!fs.existsSync(folderPath)) {
|
||||
fs.mkdirSync(folderPath, { recursive: true });
|
||||
}
|
||||
|
||||
try {
|
||||
const files = fs.readdirSync(folderPath);
|
||||
log.info('RTMP files', files);
|
||||
return files;
|
||||
} catch (error) {
|
||||
log.error(`[getRTMP] Error reading directory: ${error.message}`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async startRTMP(socket_id, room, host = 'localhost', port = 1935, file = '../rtmp/BigBuckBunny.mp4') {
|
||||
if (!this.rtmp || !this.rtmp.enabled) {
|
||||
log.debug('RTMP server is not enabled or missing the config');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.rtmpFileStreamer) {
|
||||
log.debug('RtmpFile is already in progress');
|
||||
return false;
|
||||
}
|
||||
|
||||
const inputFilePath = path.join(__dirname, file);
|
||||
|
||||
if (!fs.existsSync(inputFilePath)) {
|
||||
log.error(`File not found: ${inputFilePath}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.rtmpFileStreamer = new RtmpFile(socket_id, room);
|
||||
|
||||
const inputStream = fs.createReadStream(inputFilePath);
|
||||
|
||||
const rtmpUrl = this.getRTMPUrl(host, port);
|
||||
|
||||
const rtmpRun = await this.rtmpFileStreamer.start(inputStream, rtmpUrl);
|
||||
|
||||
if (!rtmpRun) {
|
||||
this.rtmpFileStreamer = false;
|
||||
return this.rtmpFileStreamer;
|
||||
}
|
||||
return rtmpUrl;
|
||||
}
|
||||
|
||||
stopRTMP() {
|
||||
if (!this.rtmp || !this.rtmp.enabled) {
|
||||
log.debug('RTMP server is not enabled or missing the config');
|
||||
return false;
|
||||
}
|
||||
if (this.rtmpFileStreamer) {
|
||||
this.rtmpFileStreamer.stop();
|
||||
this.rtmpFileStreamer = null;
|
||||
log.debug('RTMP File Streamer Stopped successfully!');
|
||||
return true;
|
||||
} else {
|
||||
log.debug('No RtmpFile process to stop');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ####################################################
|
||||
// RTMP from URL
|
||||
// ####################################################
|
||||
|
||||
isRtmpUrlStreamerActive() {
|
||||
return this.rtmpUrlStreamer;
|
||||
}
|
||||
|
||||
async startRTMPfromURL(
|
||||
socket_id,
|
||||
room,
|
||||
host = 'localhost',
|
||||
port = 1935,
|
||||
inputVideoURL = 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
|
||||
) {
|
||||
if (!this.rtmp || !this.rtmp.enabled) {
|
||||
log.debug('RTMP server is not enabled or missing the config');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.rtmpUrlStreamer) {
|
||||
log.debug('RtmpFile is already in progress');
|
||||
return false;
|
||||
}
|
||||
|
||||
this.rtmpUrlStreamer = new RtmpUrl(socket_id, room);
|
||||
|
||||
const rtmpUrl = this.getRTMPUrl(host, port);
|
||||
|
||||
const rtmpRun = await this.rtmpUrlStreamer.start(inputVideoURL, rtmpUrl);
|
||||
|
||||
if (!rtmpRun) {
|
||||
this.rtmpUrlStreamer = false;
|
||||
return this.rtmpUrlStreamer;
|
||||
}
|
||||
return rtmpUrl;
|
||||
}
|
||||
|
||||
stopRTMPfromURL() {
|
||||
if (!this.rtmp || !this.rtmp.enabled) {
|
||||
log.debug('RTMP server is not enabled or missing the config');
|
||||
return false;
|
||||
}
|
||||
if (this.rtmpUrlStreamer) {
|
||||
this.rtmpUrlStreamer.stop();
|
||||
this.rtmpUrlStreamer = null;
|
||||
log.debug('RTMP Url Streamer Stopped successfully!');
|
||||
return true;
|
||||
} else {
|
||||
log.debug('No RtmpUrl process to stop');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ####################################################
|
||||
// RTMP COMMON
|
||||
// ####################################################
|
||||
|
||||
getRTMPUrl(host, port) {
|
||||
const rtmpServer = this.rtmp.server != '' ? this.rtmp.server : false;
|
||||
const rtmpAppName = this.rtmp.appName != '' ? this.rtmp.appName : 'live';
|
||||
const rtmpStreamKey = this.rtmp.streamKey != '' ? this.rtmp.streamKey : uuidv4();
|
||||
const rtmpServerSecret = this.rtmp.secret != '' ? this.rtmp.secret : false;
|
||||
const expirationHours = this.rtmp.expirationHours || 4;
|
||||
const rtmpServerURL = rtmpServer ? rtmpServer : `rtmp://${host}:${port}`;
|
||||
const rtmpServerPath = '/' + rtmpAppName + '/' + rtmpStreamKey;
|
||||
|
||||
const rtmpUrl = rtmpServerSecret
|
||||
? this.generateRTMPUrl(rtmpServerURL, rtmpServerPath, rtmpServerSecret, expirationHours)
|
||||
: rtmpServerURL + rtmpServerPath;
|
||||
|
||||
log.info('RTMP Url generated', rtmpUrl);
|
||||
return rtmpUrl;
|
||||
}
|
||||
|
||||
generateRTMPUrl(baseURL, streamPath, secretKey, expirationHours = 8) {
|
||||
const currentTime = Math.floor(Date.now() / 1000);
|
||||
const expirationTime = currentTime + expirationHours * 3600;
|
||||
const hashValue = crypto.MD5(`${streamPath}-${expirationTime}-${secretKey}`).toString();
|
||||
const rtmpUrl = `${baseURL}${streamPath}?sign=${expirationTime}-${hashValue}`;
|
||||
return rtmpUrl;
|
||||
}
|
||||
|
||||
// ####################################################
|
||||
// ROUTER
|
||||
// ####################################################
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم