Started work on HLS Livestreaming. Created basic HLS Livestream Media Handler.
This commit is contained in:
parent
c6de68b474
commit
dd00a11b92
6 changed files with 208 additions and 72 deletions
|
|
@ -235,67 +235,76 @@ module.exports = class{
|
|||
}
|
||||
|
||||
async goLive(socket, data){
|
||||
//Grab the channel from DB
|
||||
const chanDB = await channelModel.findOne({name:this.channel.name});
|
||||
try{
|
||||
//Grab the channel from DB
|
||||
const chanDB = await channelModel.findOne({name:this.channel.name});
|
||||
|
||||
let title = "Livestream";
|
||||
let title = "Livestream";
|
||||
|
||||
if(data != null && data.title != null){
|
||||
//If the title is too long
|
||||
if(!validator.isLength(data.title, {max:30})){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Title too long!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
if(data != null && data.title != null){
|
||||
//If the title is too long
|
||||
if(!validator.isLength(data.title, {max:30})){
|
||||
//Bitch, moan, complain...
|
||||
loggerUtils.socketErrorHandler(socket, "Title too long!", "validation");
|
||||
//and ignore it!
|
||||
return;
|
||||
}
|
||||
|
||||
//Set title
|
||||
title = validator.escape(validator.trim(data.title));
|
||||
|
||||
//If we've got no title
|
||||
if(title == null || title == ''){
|
||||
title = "Livestream";
|
||||
}
|
||||
}
|
||||
|
||||
//Set title
|
||||
title = validator.escape(validator.trim(data.title));
|
||||
|
||||
//If we've got no title
|
||||
if(title == null || title == ''){
|
||||
title = "Livestream";
|
||||
//If we couldn't find the channel
|
||||
if(chanDB == null){
|
||||
//FUCK
|
||||
throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while queue item!`, "queue");
|
||||
}
|
||||
|
||||
//Kill schedule timers to prevent items from starting during the stream
|
||||
await this.stopScheduleTimers();
|
||||
|
||||
//Syntatic sugar because I'm lazy :P
|
||||
const streamURL = chanDB.settings.streamURL;
|
||||
|
||||
if(streamURL == ''){
|
||||
throw loggerUtils.exceptionSmith('This channel\'s HLS Livestream Source has not been set!', 'queue');
|
||||
}
|
||||
|
||||
|
||||
//Pull filename from streamURL
|
||||
let filename = streamURL.match(/^.+\..+\/(.+)$/);
|
||||
|
||||
//If we're streaming from the root of the domain
|
||||
if(filename == null){
|
||||
//Set filename to root
|
||||
filename = '/';
|
||||
}else{
|
||||
//Otherwise, hand over the filename
|
||||
filename = filename[1];
|
||||
}
|
||||
|
||||
//Create queued media object from stream URL and set it to nowPlaying
|
||||
this.nowPlaying = new queuedMedia(
|
||||
title,
|
||||
filename,
|
||||
streamURL,
|
||||
streamURL,
|
||||
"livehls",
|
||||
0,
|
||||
streamURL,
|
||||
new Date().getTime()
|
||||
);
|
||||
|
||||
//Broadcast new media object to users
|
||||
this.sendMedia();
|
||||
}catch(err){
|
||||
return loggerUtils.socketExceptionHandler(socket, err);
|
||||
}
|
||||
|
||||
//If we couldn't find the channel
|
||||
if(chanDB == null){
|
||||
//FUCK
|
||||
throw loggerUtils.exceptionSmith(`Unable to find channel document ${this.channel.name} while queue item!`, "queue");
|
||||
}
|
||||
|
||||
//Kill schedule timers to prevent items from starting during the stream
|
||||
await this.stopScheduleTimers();
|
||||
|
||||
//Syntatic sugar because I'm lazy :P
|
||||
const streamURL = chanDB.settings.streamURL;
|
||||
|
||||
//Pull filename from streamURL
|
||||
let filename = streamURL.match(/^.+\..+\/(.+)$/);
|
||||
|
||||
//If we're streaming from the root of the domain
|
||||
if(filename == null){
|
||||
//Set filename to root
|
||||
filename = '/';
|
||||
}else{
|
||||
//Otherwise, hand over the filename
|
||||
filename = filename[1];
|
||||
}
|
||||
|
||||
//Create queued media object from stream URL and set it to nowPlaying
|
||||
this.nowPlaying = new queuedMedia(
|
||||
title,
|
||||
filename,
|
||||
streamURL,
|
||||
streamURL,
|
||||
"livehls",
|
||||
0,
|
||||
streamURL,
|
||||
new Date().getTime()
|
||||
);
|
||||
|
||||
//Broadcast new media object to users
|
||||
this.sendMedia();
|
||||
}
|
||||
|
||||
//--- INTERNAL USE ONLY QUEUEING FUNCTIONS ---
|
||||
|
|
@ -553,8 +562,11 @@ module.exports = class{
|
|||
//otherwise
|
||||
}else{
|
||||
try{
|
||||
//DO everything ourselves since we don't have a fance end() function to do it
|
||||
chanDB = await channelModel.findOne({name:this.channel.name});
|
||||
//If we wheren't handed a channel
|
||||
if(chanDB == null){
|
||||
//DO everything ourselves since we don't have a fance end() function to do it
|
||||
chanDB = await channelModel.findOne({name:this.channel.name});
|
||||
}
|
||||
|
||||
//If we couldn't find the channel
|
||||
if(chanDB == null){
|
||||
|
|
@ -814,6 +826,9 @@ module.exports = class{
|
|||
//Send play signal out to the channel
|
||||
this.sendMedia();
|
||||
|
||||
//Kill existing sync timers to prevent kicking-off ghost timer loops
|
||||
clearTimeout(this.syncTimer);
|
||||
|
||||
//Kick off the sync timer
|
||||
this.syncTimer = setTimeout(this.sync.bind(this), this.syncDelta);
|
||||
|
||||
|
|
@ -879,9 +894,19 @@ module.exports = class{
|
|||
this.server.io.in(this.channel.name).emit('end', {});
|
||||
}
|
||||
|
||||
//If we're ending an HLS Livestream
|
||||
if(wasPlaying.type == "livehls"){
|
||||
//Redirect to the endLivestream function
|
||||
return this.endLivestream(chanDB);
|
||||
}
|
||||
|
||||
//If we're not in volatile mode and we're not ending a livestream
|
||||
if(!volatile){
|
||||
//Now that everything is clean, we can take our time with the DB :P
|
||||
chanDB = await channelModel.findOne({name:this.channel.name});
|
||||
//If we wheren't handed a channel
|
||||
if(chanDB == null){
|
||||
//Now that everything is clean, we can take our time with the DB :P
|
||||
chanDB = await channelModel.findOne({name:this.channel.name});
|
||||
}
|
||||
|
||||
//If we couldn't find the channel
|
||||
if(chanDB == null){
|
||||
|
|
@ -898,12 +923,13 @@ module.exports = class{
|
|||
//Take it out of the active schedule
|
||||
this.schedule.delete(wasPlaying.startTime);
|
||||
|
||||
//If archiving is enabled
|
||||
if(!noArchive){
|
||||
//Add the item to the channel archive
|
||||
chanDB.media.archived.push(wasPlaying);
|
||||
}
|
||||
|
||||
//broadcast queue using unsaved archive
|
||||
//broadcast queue using unsaved archive, run this before chanDB.save() for better responsiveness
|
||||
this.broadcastQueue(chanDB);
|
||||
|
||||
//Save our changes to the DB
|
||||
|
|
@ -918,6 +944,22 @@ module.exports = class{
|
|||
}
|
||||
}
|
||||
|
||||
async endLivestream(chanDB){
|
||||
try{
|
||||
//Refresh next timer
|
||||
this.refreshNextTimer();
|
||||
|
||||
//Broadcast Queue
|
||||
this.broadcastQueue();
|
||||
//ACK
|
||||
}catch(err){
|
||||
//Broadcast queue
|
||||
this.broadcastQueue();
|
||||
//Handle the error
|
||||
loggerUtils.localExceptionHandler(err);
|
||||
}
|
||||
}
|
||||
|
||||
async stop(chanDB){
|
||||
//If we wheren't handed a channel
|
||||
if(chanDB == null){
|
||||
|
|
|
|||
|
|
@ -160,8 +160,6 @@ app.use('/passwordReset', passwordResetRouter);
|
|||
app.use('/emailChange', emailChangeRouter);
|
||||
//Panel
|
||||
app.use('/panel', panelRouter);
|
||||
//Popup
|
||||
//app.use('/popup', popupRouter);
|
||||
//tooltip
|
||||
app.use('/tooltip', tooltipRouter);
|
||||
//Bot-Ready
|
||||
|
|
@ -169,9 +167,9 @@ app.use('/api', apiRouter);
|
|||
|
||||
//Static File Server
|
||||
//Serve client-side libraries
|
||||
app.use('/lib/bootstrap-icons',express.static(path.join(__dirname, '../node_modules/bootstrap-icons')));
|
||||
app.use('/lib/altcha',express.static(path.join(__dirname, '../node_modules/altcha/dist_external')));
|
||||
app.use('/lib/hls.js',express.static(path.join(__dirname, '../node_modules/hls.js/dist')));
|
||||
app.use('/lib/bootstrap-icons',express.static(path.join(__dirname, '../node_modules/bootstrap-icons'))); //Icon set
|
||||
app.use('/lib/altcha',express.static(path.join(__dirname, '../node_modules/altcha/dist_external'))); //Self-Hosted PoW-based Captcha
|
||||
app.use('/lib/hls.js',express.static(path.join(__dirname, '../node_modules/hls.js/dist'))); //HLS Media Handler
|
||||
//Server public 'www' folder
|
||||
app.use(express.static(path.join(__dirname, '../www')));
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. %>
|
|||
<%- include('partial/scripts', {user}); %>
|
||||
<%# 3rd party code %>
|
||||
<script src="/socket.io/socket.io.min.js"></script>
|
||||
<script src="/lib/hls.js/hls.js"></script>
|
||||
<script src="/lib/hls.js/hls.min.js"></script>
|
||||
<%# 1st party code %>
|
||||
<%# admin gunk %>
|
||||
<script src="/js/adminUtils.js"></script>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue