[mirotalksfu] - add RTMP server and multi-source streaming!, update dep

هذا الالتزام موجود في:
Miroslav Pejic
2024-06-29 18:49:10 +02:00
الأصل aaf5fe44ed
التزام 3929212631
52 ملفات معدلة مع 3986 إضافات و132 حذوفات

عرض الملف

@@ -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
// ####################################################