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.
- package/index.js +61 -29
- 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', '
|
|
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[
|
|
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="' +
|
|
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[
|
|
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="' +
|
|
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[
|
|
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[
|
|
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="' +
|
|
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[
|
|
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="' +
|
|
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
|
-
|
|
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
|
-
//
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
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.
|
|
3016
|
+
session.debuglog('download command started')
|
|
2982
3017
|
if ( argv.debug || argv.ffmpeg_logging ) {
|
|
2983
|
-
session.
|
|
3018
|
+
session.debuglog('download command: ' + commandLine)
|
|
2984
3019
|
}
|
|
2985
3020
|
})
|
|
2986
3021
|
.on('error', function(err, stdout, stderr) {
|
|
2987
|
-
session.
|
|
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.
|
|
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
|
|
3037
|
+
var download_headers = {}
|
|
3003
3038
|
if ( req.query.filename ) {
|
|
3004
|
-
|
|
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
|
|