mlbserver 2023.4.4 → 2023.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/index.js +25 -9
- package/package.json +1 -1
package/README.md
CHANGED
package/index.js
CHANGED
|
@@ -1238,10 +1238,12 @@ app.get('/', async function(req, res) {
|
|
|
1238
1238
|
} else if ( level_ids == '1' ) {
|
|
1239
1239
|
team_ids = session.getTeamIds()
|
|
1240
1240
|
for (let i=0; i<session.credentials.fav_teams.length; i++) {
|
|
1241
|
-
if (
|
|
1242
|
-
level_ids
|
|
1241
|
+
if ( session.credentials.fav_teams[i] != '' ) {
|
|
1242
|
+
if ( level_ids == '1' ) {
|
|
1243
|
+
level_ids = levels['All']
|
|
1244
|
+
}
|
|
1245
|
+
team_ids += ',' + AFFILIATE_TEAM_IDS[session.credentials.fav_teams[i]]
|
|
1243
1246
|
}
|
|
1244
|
-
team_ids += ',' + AFFILIATE_TEAM_IDS[session.credentials.fav_teams[i]]
|
|
1245
1247
|
}
|
|
1246
1248
|
}
|
|
1247
1249
|
let cache_name = gameDate
|
|
@@ -1340,7 +1342,7 @@ app.get('/', async function(req, res) {
|
|
|
1340
1342
|
body += 'function makeGETRequest(url, callback){var request=new XMLHttpRequest();request.onreadystatechange=function(){if (request.readyState==4 && request.status==200){callback(request.responseText)}};request.open("GET", url);request.send();}' + "\n"
|
|
1341
1343
|
|
|
1342
1344
|
// Multiview functions
|
|
1343
|
-
body += 'var excludeTeams=[];function parsemultiviewresponse(responsetext){if (responsetext == "started"){setTimeout(function(){document.getElementById("startmultiview").innerHTML="Restart";document.getElementById("stopmultiview").innerHTML="Stop"},15000)}else if (responsetext == "stopped"){setTimeout(function(){document.getElementById("stopmultiview").innerHTML="Stopped";document.getElementById("startmultiview").innerHTML="Start"},3000)}else{alert(responsetext)}}function addmultiview(e, teams=[], excludes=[]){var newvalue=e.value;for(var i=1;i<=4;i++){var valuefound = false;var oldvalue="";if(!e.checked){oldvalue=e.value;newvalue=""}if ((document.getElementById("multiview" + i).value == oldvalue) || ((oldvalue != "") && (document.getElementById("multiview" + i).value.startsWith(oldvalue)))){if ((newvalue != "") && (excludes.length > 0)){newvalue+="&excludeTeams="+excludeTeams.toString()}document.getElementById("multiview" + i).value=newvalue;valuefound=true;break}}if(e.checked && !valuefound){e.checked=false}for(var i=0;i<teams.length;i++){if(e.checked){excludeTeams.push(teams[i])}else{var index=excludeTeams.indexOf(teams[i]);if (index !== -1){excludeTeams.splice(index,1)}}}}function startmultiview(e){var count=0;var getstr="";for(var i=1;i<=4;i++){if (document.getElementById("multiview"+i).value != ""){count++;getstr+="streams="+encodeURIComponent(document.getElementById("multiview"+i).value)+"&sync="+encodeURIComponent(document.getElementById("sync"+i).value)+"&"}}if((count >= 1) && (count <= 4)){if (document.getElementById("faster").checked){getstr+="faster=true&dvr=true&"}else if (document.getElementById("dvr").checked){getstr+="dvr=true&"}if (document.getElementById("reencode").checked){getstr+="reencode=true&"}if (document.getElementById("audio_url").value != ""){getstr+="audio_url="+encodeURIComponent(document.getElementById("audio_url").value)+"&";if (document.getElementById("audio_url_seek").value != "0"){getstr+="audio_url_seek="+encodeURIComponent(document.getElementById("audio_url_seek").value)}}e.innerHTML="starting...";makeGETRequest("/multiview?"+getstr, parsemultiviewresponse)}else{alert("Multiview requires between 1-4 streams to be selected")}return false}function stopmultiview(e){e.innerHTML="stopping...";makeGETRequest("/multiview", parsemultiviewresponse);return false}' + "\n"
|
|
1345
|
+
body += 'var excludeTeams=[];function parsemultiviewresponse(responsetext){if (responsetext == "started"){setTimeout(function(){document.getElementById("startmultiview").innerHTML="Restart";document.getElementById("stopmultiview").innerHTML="Stop"},15000)}else if (responsetext == "stopped"){setTimeout(function(){document.getElementById("stopmultiview").innerHTML="Stopped";document.getElementById("startmultiview").innerHTML="Start"},3000)}else{alert(responsetext)}}function addmultiview(e, teams=[], excludes=[]){var newvalue=e.value;for(var i=1;i<=4;i++){var valuefound = false;var oldvalue="";if(!e.checked){oldvalue=e.value;newvalue=""}if ((document.getElementById("multiview" + i).value == oldvalue) || ((oldvalue != "") && (document.getElementById("multiview" + i).value.startsWith(oldvalue)))){if ((newvalue != "") && (excludes.length > 0)){newvalue+="&excludeTeams="+excludeTeams.toString()}document.getElementById("multiview" + i).value=newvalue;valuefound=true;break}}if(e.checked && !valuefound){e.checked=false}for(var i=0;i<teams.length;i++){if(e.checked){excludeTeams.push(teams[i])}else{var index=excludeTeams.indexOf(teams[i]);if (index !== -1){excludeTeams.splice(index,1)}}}}function startmultiview(e){var count=0;var getstr="";for(var i=1;i<=4;i++){if (document.getElementById("multiview"+i).value != ""){count++;getstr+="streams="+encodeURIComponent(document.getElementById("multiview"+i).value)+"&sync="+encodeURIComponent(document.getElementById("sync"+i).value)+"&"}}if((count >= 1) && (count <= 4)){if (document.getElementById("faster").checked){getstr+="faster=true&dvr=true&"}else if (document.getElementById("dvr").checked){getstr+="dvr=true&"}if (document.getElementById("reencode").checked){getstr+="reencode=true&"}if (document.getElementById("park_audio").checked){getstr+="park_audio=true&"}if (document.getElementById("audio_url").value != ""){getstr+="audio_url="+encodeURIComponent(document.getElementById("audio_url").value)+"&";if (document.getElementById("audio_url_seek").value != "0"){getstr+="audio_url_seek="+encodeURIComponent(document.getElementById("audio_url_seek").value)}}e.innerHTML="starting...";makeGETRequest("/multiview?"+getstr, parsemultiviewresponse)}else{alert("Multiview requires between 1-4 streams to be selected")}return false}function stopmultiview(e){e.innerHTML="stopping...";makeGETRequest("/multiview", parsemultiviewresponse);return false}' + "\n"
|
|
1344
1346
|
|
|
1345
1347
|
// Function to switch URLs to stream URLs, where necessary
|
|
1346
1348
|
body += 'function stream_substitution(url){return url.replace(/\\/([a-zA-Z]+\.html)/,"/stream.m3u8")}' + "\n"
|
|
@@ -1470,7 +1472,7 @@ app.get('/', async function(req, res) {
|
|
|
1470
1472
|
|
|
1471
1473
|
let blackouts = {}
|
|
1472
1474
|
|
|
1473
|
-
if ( (mediaType == 'MLBTV') && level_ids.startsWith('1,') ) {
|
|
1475
|
+
if ( (mediaType == 'MLBTV') && ((level_ids == '1') || level_ids.startsWith('1,')) ) {
|
|
1474
1476
|
if ( (gameDate >= today) && cache_data.dates && cache_data.dates[0] && cache_data.dates[0].games && (cache_data.dates[0].games.length > 0) ) {
|
|
1475
1477
|
blackouts = await session.get_blackout_games(cache_data.dates[0].games, true)
|
|
1476
1478
|
}
|
|
@@ -1527,8 +1529,8 @@ app.get('/', async function(req, res) {
|
|
|
1527
1529
|
body += '<tr><td><span class="tooltip">' + compareStart.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + ' - ' + compareEnd.toLocaleString('en-US', { hour: 'numeric', minute: 'numeric', hour12: true }) + '<span class="tooltiptext">The game changer stream will automatically switch between the highest leverage active live non-blackout games, and should be available whenever there are such games available. Does not support adaptive bitrate switching, will default to best resolution if not specified.</span></span></td><td>'
|
|
1528
1530
|
if ( (currentDate >= compareStart) && (currentDate < compareEnd) ) {
|
|
1529
1531
|
let streamURL = server + '/gamechanger.m3u8'
|
|
1532
|
+
let multiviewquerystring = streamURL + '?resolution=' + DEFAULT_MULTIVIEW_RESOLUTION + content_protect_b
|
|
1530
1533
|
streamURL += content_protect_a
|
|
1531
|
-
let multiviewquerystring = streamURL + '&resolution=' + DEFAULT_MULTIVIEW_RESOLUTION
|
|
1532
1534
|
if ( resolution != VALID_RESOLUTIONS[0] ) streamURL += '&resolution=' + resolution
|
|
1533
1535
|
if ( linkType != VALID_LINK_TYPES[1] ) {
|
|
1534
1536
|
streamURL = thislink + '?src=' + encodeURIComponent(streamURL) + '&startFrom=' + VALID_START_FROM[1] + content_protect_b
|
|
@@ -1993,6 +1995,7 @@ app.get('/', async function(req, res) {
|
|
|
1993
1995
|
body += '<input type="checkbox" id="dvr"/> <span class="tooltip">DVR: allow pausing/seeking multiview<span class="tooltiptext">If this is enabled, it will use more disk space but you will be able to pause and seek in the multiview stream. Not necessary if you are strictly watching live.</span></span><br/>' + "\n"
|
|
1994
1996
|
body += '<input type="checkbox" id="faster" onchange="if (this.checked){document.getElementById(\'dvr\').checked=true}"/> <span class="tooltip">Encode faster than real-time<span class="tooltiptext">Implies DVR. Not necessary for live streams (which are only delivered in real-time), but if you want to seek ahead in archive streams using multiview, you may want to enable this. WARNING: ffmpeg may approach 100% CPU usage if you use this while combining multiple archive video streams in multiview.</span></span><br/>' + "\n"
|
|
1995
1997
|
body += '<input type="checkbox" id="reencode"/> <span class="tooltip">Re-encode all audio<span class="tooltiptext">Uses more CPU. Generally only necessary if you need the multiview stream to continue after one of the individual streams has ended. (Any streams with sync adjustments above will automatically be re-encoded, regardless of this setting.)</span></span><br/>' + "\n"
|
|
1998
|
+
body += '<input type="checkbox" id="park_audio"/> <span class="tooltip">Park audio: filter out announcers<span class="tooltiptext">Implies re-encoding all audio. If this is enabled, an extra audio filter is applied to remove the announcer voices.</span></span><br/>' + "\n"
|
|
1996
1999
|
body += '<hr><span class="tooltip">Alternate audio URL and sync<span class="tooltiptext">Optional: you can also include a separate audio-only URL as an additional alternate audio track. Archive games will likely require a very large negative sync value, as the radio broadcasts may not be trimmed like the video archives.</span></span>:<br/><textarea id="audio_url" rows=2 cols=60 oninput="this.value=stream_substitution(this.value)"></textarea><input id="audio_url_seek" type="number" value="0" style="vertical-align:top;font-size:.8em;width:4em"/>'
|
|
1997
2000
|
body += '<hr>Watch: <a href="/embed.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + '">Embed</a> | <a href="' + multiview_server + multiview_url_path + '">Stream</a> | <a href="/chromecast.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + '">Chromecast</a> | <a href="/advanced.html?src=' + encodeURIComponent(multiview_server + multiview_url_path) + '">Advanced</a><br/><span class="tinytext">Download: <a href="/kodi.strm?src=' + encodeURIComponent(multiview_server + multiview_url_path) + '">Kodi STRM file</a> (<a href="/kodi.strm?version=18&src=' + encodeURIComponent(multiview_server + multiview_url_path) + '">Leia/18</a>)</span>'
|
|
1998
2001
|
body += '</td></tr></table><br/>' + "\n"
|
|
@@ -2472,6 +2475,11 @@ app.get('/multiview', async function(req, res) {
|
|
|
2472
2475
|
if ( req.query.reencode ) {
|
|
2473
2476
|
reencode = req.query.reencode
|
|
2474
2477
|
}
|
|
2478
|
+
let park_audio = false
|
|
2479
|
+
if ( req.query.park_audio ) {
|
|
2480
|
+
reencode = true
|
|
2481
|
+
park_audio = req.query.park_audio
|
|
2482
|
+
}
|
|
2475
2483
|
let audio_url = false
|
|
2476
2484
|
if ( req.query.audio_url && (req.query.audio_url != '') ) {
|
|
2477
2485
|
audio_url = req.query.audio_url
|
|
@@ -2482,7 +2490,7 @@ app.get('/multiview', async function(req, res) {
|
|
|
2482
2490
|
}
|
|
2483
2491
|
// Wait to restart it
|
|
2484
2492
|
setTimeout(function() {
|
|
2485
|
-
res.end(start_multiview_stream(req.query.streams, sync, dvr, faster, reencode, audio_url, audio_url_seek))
|
|
2493
|
+
res.end(start_multiview_stream(req.query.streams, sync, dvr, faster, reencode, park_audio, audio_url, audio_url_seek))
|
|
2486
2494
|
}, 5000)
|
|
2487
2495
|
} else {
|
|
2488
2496
|
res.end('stopped')
|
|
@@ -2493,7 +2501,7 @@ app.get('/multiview', async function(req, res) {
|
|
|
2493
2501
|
}
|
|
2494
2502
|
})
|
|
2495
2503
|
|
|
2496
|
-
function start_multiview_stream(streams, sync, dvr, faster, reencode, audio_url, audio_url_seek) {
|
|
2504
|
+
function start_multiview_stream(streams, sync, dvr, faster, reencode, park_audio, audio_url, audio_url_seek) {
|
|
2497
2505
|
try {
|
|
2498
2506
|
ffmpeg_command = ffmpeg({ timeout: 432000 })
|
|
2499
2507
|
|
|
@@ -2580,7 +2588,8 @@ function start_multiview_stream(streams, sync, dvr, faster, reencode, audio_url,
|
|
|
2580
2588
|
// Filters: resampling preserve timestamps and padding allows the multiview stream to continue if one stream ends
|
|
2581
2589
|
audio_reencoded = []
|
|
2582
2590
|
for (var i=0; i<audio_present.length; i++) {
|
|
2583
|
-
let audio_input = audio_present[i] + ':a:m:language:en?'
|
|
2591
|
+
//let audio_input = audio_present[i] + ':a:m:language:en?'
|
|
2592
|
+
let audio_input = audio_present[i] + ':a:0'
|
|
2584
2593
|
let filter = ''
|
|
2585
2594
|
// Optionally apply sync adjustments
|
|
2586
2595
|
if ( sync[audio_present[i]] ) {
|
|
@@ -2592,6 +2601,10 @@ function start_multiview_stream(streams, sync, dvr, faster, reencode, audio_url,
|
|
|
2592
2601
|
filter = 'atrim=start=' + (sync[audio_present[i]] * -1) + 's,'
|
|
2593
2602
|
}
|
|
2594
2603
|
}
|
|
2604
|
+
// Optionally filter to park audio
|
|
2605
|
+
if ( park_audio ) {
|
|
2606
|
+
filter = 'pan=stereo|c0=c0|c1=-1*c1,'
|
|
2607
|
+
}
|
|
2595
2608
|
if ( reencode || (filter != '') ) {
|
|
2596
2609
|
audio_reencoded.push(audio_present[i])
|
|
2597
2610
|
complexFilter.push({
|
|
@@ -2659,6 +2672,9 @@ function start_multiview_stream(streams, sync, dvr, faster, reencode, audio_url,
|
|
|
2659
2672
|
audio_encoder = 'copy'
|
|
2660
2673
|
}
|
|
2661
2674
|
ffmpeg_command.addOutputOption('-c:a:' + i, audio_encoder)
|
|
2675
|
+
if ( park_audio ) {
|
|
2676
|
+
ffmpeg_command.addOutputOption('-ac:a:' + i, '1')
|
|
2677
|
+
}
|
|
2662
2678
|
}
|
|
2663
2679
|
// Drop subtitles/captions
|
|
2664
2680
|
// End after 6 hours in case we forget to stop it manually
|