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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/index.js +25 -9
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mlbserver
2
2
 
3
- Current version 2023.04.04
3
+ Current version 2023.04.10
4
4
 
5
5
  Credit to https://github.com/tonycpsu/streamglob and https://github.com/mafintosh/hls-decryptor
6
6
 
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 ( level_ids == '1' ) {
1242
- level_ids = levels['All']
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mlbserver",
3
- "version": "2023.04.04",
3
+ "version": "2023.04.10",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",