mlbserver 2024.10.7 → 2024.10.8

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 (2) hide show
  1. package/index.js +61 -29
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -29,12 +29,12 @@ const VALID_CONTROLS = [ 'Show', 'Hide' ]
29
29
  const VALID_INNING_HALF = [ '', 'top', 'bottom' ]
30
30
  const VALID_INNING_NUMBER = [ '', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' ]
31
31
  const VALID_SCORES = [ 'Hide', 'Show' ]
32
- const VALID_RESOLUTIONS = [ 'adaptive', '720p60', '720p', '540p', '504p', '360p', 'none' ]
32
+ const VALID_RESOLUTIONS = [ 'adaptive', '720p60', '720p', '540p', '504p', '360p', 'none' ]
33
33
  const DEFAULT_MULTIVIEW_RESOLUTION = '504p'
34
34
  // Corresponding andwidths to display for above resolutions
35
35
  const DISPLAY_BANDWIDTHS = [ '', '6600k', '4160k', '2950k', '2120k', '1400k', '' ]
36
- const VALID_AUDIO_TRACKS = [ 'all', 'English', 'Home Radio', 'Casa Radio', 'Away Radio', 'Visita Radio', 'none' ]
37
- const DISPLAY_AUDIO_TRACKS = [ 'all', 'TV', 'Radio', 'Spanish', 'Away Radio', 'Away Sp.', 'none' ]
36
+ const VALID_AUDIO_TRACKS = [ 'all', 'English', 'Home Radio', 'Casa Radio', 'Away Radio', 'Visita Radio', 'Park', 'none' ]
37
+ const DISPLAY_AUDIO_TRACKS = [ 'all', 'TV', 'Radio', 'Spa.', 'Away Rad.', 'Away Sp.', 'Park', 'none' ]
38
38
  const DEFAULT_MULTIVIEW_AUDIO_TRACK = 'English'
39
39
  const VALID_SKIP = [ 'off', 'breaks', 'idle time', 'pitches', 'commercials' ]
40
40
  const DEFAULT_SKIP_ADJUST = 0
@@ -536,9 +536,9 @@ function getMasterPlaylist(streamURL, req, res, options = {}) {
536
536
  // we'll append to this and output track(s) at the end of this code block
537
537
  let audio_output = ''
538
538
 
539
- // default TV audio
539
+ // default TV audio, or park sounds
540
540
  if ( !line.includes(',URI=') ) {
541
- if ( audio_track == VALID_AUDIO_TRACKS[1] ) {
541
+ if ( (audio_track == VALID_AUDIO_TRACKS[1]) || (audio_track == VALID_AUDIO_TRACKS[6]) ) {
542
542
  return line
543
543
  } else if ( audio_track == VALID_AUDIO_TRACKS[0] ) {
544
544
  audio_output += line
@@ -637,6 +637,7 @@ function getMasterPlaylist(streamURL, req, res, options = {}) {
637
637
  if ( skip_adjust != DEFAULT_SKIP_ADJUST ) newurl += '&skip_adjust=' + skip_adjust
638
638
  if ( pad != VALID_PAD[0] ) newurl += '&pad=' + pad
639
639
  if ( gamePk ) newurl += '&gamePk=' + gamePk
640
+ if ( audio_track == VALID_AUDIO_TRACKS[6] ) newurl += '&park_audio=true'
640
641
  newurl += content_protect + referer_parameter + token_parameter
641
642
  return '/playlist?url='+newurl
642
643
  }
@@ -693,6 +694,7 @@ app.get('/playlist', async function(req, res) {
693
694
  var skip_adjust = req.query.skip_adjust || DEFAULT_SKIP_ADJUST
694
695
  var pad = req.query.pad || VALID_PAD[0]
695
696
  var gamePk = req.query.gamePk || false
697
+ var park_audio = req.query.park_audio || false
696
698
 
697
699
  var req = function () {
698
700
  var headers = {}
@@ -817,6 +819,11 @@ app.get('/playlist', async function(req, res) {
817
819
  newline += '?url='+encodeURIComponent(url.resolve(u, line.trim())) + content_protect + referer_parameter + token_parameter
818
820
  if ( key ) newline += '&key='+encodeURIComponent(key) + '&iv='+encodeURIComponent(iv)
819
821
 
822
+ // park audio
823
+ if ( park_audio ) {
824
+ newline = 'download.html?park_audio=true&src=' + encodeURIComponent('http://127.0.0.1:' + session.data.port + newline) + content_protect
825
+ }
826
+
820
827
  return newline
821
828
  })
822
829
  .filter(function(line) {
@@ -1532,13 +1539,13 @@ app.get('/', async function(req, res) {
1532
1539
  if ( resolution != VALID_RESOLUTIONS[0] ) querystring += '&resolution=' + resolution
1533
1540
  if ( linkType == VALID_LINK_TYPES[1] ) {
1534
1541
  if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
1535
- } else if ( linkType == VALID_LINK_TYPES[VALID_LINK_TYPES.length-1] ) {
1542
+ } else if ( linkType == VALID_LINK_TYPES[4] ) {
1536
1543
  querystring += '&filename=' + gameDate + ' MLB Network'
1537
1544
  }
1538
1545
  querystring += content_protect_b
1539
1546
  multiviewquerystring += content_protect_b
1540
1547
  body += '<a href="' + thislink + querystring + '">MLB Network</a>'
1541
- body += '<input type="checkbox" value="' + server + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
1548
+ body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
1542
1549
  body += '</td></tr>' + "\n"
1543
1550
  } // end entitlements check
1544
1551
  } // end country check
@@ -1590,13 +1597,13 @@ app.get('/', async function(req, res) {
1590
1597
  if ( resolution != VALID_RESOLUTIONS[0] ) querystring += '&resolution=' + resolution
1591
1598
  if ( linkType == VALID_LINK_TYPES[1] ) {
1592
1599
  if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
1593
- } else if ( linkType == VALID_LINK_TYPES[VALID_LINK_TYPES.length-1] ) {
1600
+ } else if ( linkType == VALID_LINK_TYPES[4] ) {
1594
1601
  querystring += '&filename=' + gameDate + ' Big Inning'
1595
1602
  }
1596
1603
  querystring += content_protect_b
1597
1604
  multiviewquerystring += content_protect_b
1598
1605
  body += '<a href="' + thislink + querystring + '">Big Inning</a>'
1599
- body += '<input type="checkbox" value="' + server + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
1606
+ body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
1600
1607
  } else {
1601
1608
  body += 'Big Inning'
1602
1609
  }
@@ -1623,11 +1630,11 @@ app.get('/', async function(req, res) {
1623
1630
  if ( linkType != VALID_LINK_TYPES[1] ) {
1624
1631
  streamURL = thislink + '?src=' + encodeURIComponent(streamURL) + '&startFrom=' + VALID_START_FROM[1] + content_protect_b
1625
1632
  }
1626
- if ( linkType == VALID_LINK_TYPES[VALID_LINK_TYPES.length-1] ) {
1633
+ if ( linkType == VALID_LINK_TYPES[4] ) {
1627
1634
  streamURL += '&filename=' + gameDate + ' Game Changer'
1628
1635
  }
1629
1636
  body += '<a href="' + streamURL + '">Game Changer</a>'
1630
- body += '<input type="checkbox" value="' + multiviewquerystring + '" onclick="addmultiview(this, [], excludeTeams)">'
1637
+ body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + multiviewquerystring + '" onclick="addmultiview(this, [], excludeTeams)">'
1631
1638
  } else {
1632
1639
  body += 'Game Changer'
1633
1640
  }
@@ -1876,13 +1883,13 @@ app.get('/', async function(req, res) {
1876
1883
  if ( currentTime < endTime ) {
1877
1884
  if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
1878
1885
  }
1879
- } else if ( linkType == VALID_LINK_TYPES[VALID_LINK_TYPES.length-1] ) {
1886
+ } else if ( linkType == VALID_LINK_TYPES[4] ) {
1880
1887
  querystring += '&filename=' + filename + broadcastName
1881
1888
  }
1882
1889
  querystring += content_protect_b
1883
1890
  multiviewquerystring += content_protect_b
1884
1891
  body += '<a href="' + thislink + querystring + '">' + broadcastName + '</a>'
1885
- body += '<input type="checkbox" value="' + server + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
1892
+ body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this)">'
1886
1893
  } else {
1887
1894
  body += broadcastName
1888
1895
  }
@@ -1971,7 +1978,7 @@ app.get('/', async function(req, res) {
1971
1978
  if ( broadcast.mediaState.mediaStateCode == 'MEDIA_ON' ) {
1972
1979
  if ( force_vod != VALID_FORCE_VOD[0] ) querystring += '&force_vod=' + force_vod
1973
1980
  }
1974
- } else if ( linkType == VALID_LINK_TYPES[VALID_LINK_TYPES.length-1] ) {
1981
+ } else if ( linkType == VALID_LINK_TYPES[4] ) {
1975
1982
  querystring += '&filename=' + filename + station
1976
1983
  }
1977
1984
  querystring += content_protect_b
@@ -1984,7 +1991,7 @@ app.get('/', async function(req, res) {
1984
1991
  body += stationlink
1985
1992
  }
1986
1993
  if ( mediaType == 'MLBTV' ) {
1987
- body += '<input type="checkbox" value="' + server + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this, [\'' + awayteam + '\', \'' + hometeam + '\'])">'
1994
+ body += '<input type="checkbox" value="http://127.0.0.1:' + session.data.port + '/stream.m3u8' + multiviewquerystring + '" onclick="addmultiview(this, [\'' + awayteam + '\', \'' + hometeam + '\'])">'
1988
1995
  }
1989
1996
  if ( resumeStatus ) {
1990
1997
  body += '('
@@ -2954,7 +2961,11 @@ app.get('/download.html', async function(req, res) {
2954
2961
  if ( ! (await protect(req, res)) ) return
2955
2962
 
2956
2963
  try {
2957
- session.requestlog('download', req)
2964
+ if ( req.query.park_audio ) {
2965
+ session.debuglog('parkaudio', req)
2966
+ } else {
2967
+ session.requestlog('download', req)
2968
+ }
2958
2969
 
2959
2970
  let server = 'http://' + req.headers.host
2960
2971
 
@@ -2972,24 +2983,48 @@ app.get('/download.html', async function(req, res) {
2972
2983
 
2973
2984
  ffmpeg_command = ffmpeg({ timeout: 432000 })
2974
2985
 
2975
- // Set input stream and its thread queue size
2976
- ffmpeg_command.input(video_url)
2977
- .addOutputOption('-c', 'copy')
2978
- .addOutputOption('-f', 'mpegts')
2986
+ // park audio
2987
+ if ( req.query.park_audio ) {
2988
+ ffmpeg_command.complexFilter([{
2989
+ filter: 'pan=stereo|c0=c0|c1=-1*c1',
2990
+ inputs: '0:a:0',
2991
+ outputs: 'out0'
2992
+ }])
2993
+
2994
+ // Set input stream, minimize ffmpeg startup latency, re-encode audio to mono, and copy source PTS values
2995
+ ffmpeg_command.input(video_url)
2996
+ .addInputOption('-fflags', 'nobuffer')
2997
+ .addInputOption('-probesize', '32')
2998
+ .addInputOption('-analyzeduration', '0')
2999
+ .addOutputOption('-map', '0:v:0')
3000
+ .addOutputOption('-map', '[out0]')
3001
+ .addOutputOption('-c:v', 'copy')
3002
+ .addOutputOption('-c:a', 'aac')
3003
+ .addOutputOption('-ac:a:0', '1')
3004
+ .addOutputOption('-copyts')
3005
+ .addOutputOption('-muxpreload', '0')
3006
+ .addOutputOption('-muxdelay', '0')
3007
+ } else {
3008
+ // Set input stream
3009
+ ffmpeg_command.input(video_url)
3010
+ .addOutputOption('-c', 'copy')
3011
+ }
3012
+
3013
+ ffmpeg_command.addOutputOption('-f', 'mpegts')
2979
3014
  .output(res)
2980
3015
  .on('start', function(commandLine) {
2981
- session.log('download command started')
3016
+ session.debuglog('download command started')
2982
3017
  if ( argv.debug || argv.ffmpeg_logging ) {
2983
- session.log('download command: ' + commandLine)
3018
+ session.debuglog('download command: ' + commandLine)
2984
3019
  }
2985
3020
  })
2986
3021
  .on('error', function(err, stdout, stderr) {
2987
- session.log('download command stopped: ' + err.message)
3022
+ session.debuglog('download command stopped: ' + err.message)
2988
3023
  if ( stdout ) session.log(stdout)
2989
3024
  if ( stderr ) session.log(stderr)
2990
3025
  })
2991
3026
  .on('end', function() {
2992
- session.log('download command ended')
3027
+ session.debuglog('download command ended')
2993
3028
  })
2994
3029
 
2995
3030
  if ( argv.ffmpeg_logging ) {
@@ -2999,12 +3034,9 @@ app.get('/download.html', async function(req, res) {
2999
3034
  })
3000
3035
  }
3001
3036
 
3002
- var filename = 'mlbserver'
3037
+ var download_headers = {}
3003
3038
  if ( req.query.filename ) {
3004
- filename = req.query.filename
3005
- }
3006
- var download_headers = {
3007
- 'Content-Disposition': 'attachment; filename="' + filename + '.ts"'
3039
+ download_headers['Content-Disposition'] = 'attachment; filename="' + req.query.filename + '.ts"'
3008
3040
  }
3009
3041
  res.writeHead(200, download_headers)
3010
3042
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mlbserver",
3
- "version": "2024.10.07",
3
+ "version": "2024.10.08",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",