Add audioTracks support for custom manifests

This commit is contained in:
Xaekai 2022-02-12 20:40:48 -08:00 committed by Calvin Montgomery
parent 2cf26cdc4c
commit f185e6c3ea
3 changed files with 64 additions and 8 deletions

View file

@ -46,6 +46,10 @@ hasAnyTextTracks = (data) ->
ntracks = data?.meta?.textTracks?.length ? 0
return ntracks > 0
hasAnyAudioTracks = (data) ->
ntracks = data?.meta?.audioTracks?.length ? 0
return ntracks > 0
window.VideoJSPlayer = class VideoJSPlayer extends Player
constructor: (data) ->
if not (this instanceof VideoJSPlayer)
@ -108,13 +112,21 @@ window.VideoJSPlayer = class VideoJSPlayer extends Player
$('<track/>').attr(attrs).appendTo(video)
)
pluginData =
videoJsResolutionSwitcher:
default: @sources[0].res
if hasAnyAudioTracks(data)
pluginData.audioSwitch =
audioTracks: data.meta.audioTracks,
volume: VOLUME
@player = videojs(video[0],
# https://github.com/Dash-Industry-Forum/dash.js/issues/2184
autoplay: @sources[0].type != 'application/dash+xml',
controls: true,
plugins:
videoJsResolutionSwitcher:
default: @sources[0].res
plugins: pluginData
)
@player.ready(=>
# Have to use updateSrc instead of <source> tags

View file

@ -22,8 +22,9 @@ const SOURCE_CONTENT_TYPES = new Set([
'application/dash+xml',
'application/x-mpegURL',
'audio/aac',
'audio/ogg',
'audio/mp4',
'audio/mpeg',
'audio/ogg',
'audio/opus',
'video/mp4',
'video/ogg',
@ -36,8 +37,9 @@ const LIVE_ONLY_CONTENT_TYPES = new Set([
const AUDIO_ONLY_CONTENT_TYPES = new Set([
'audio/aac',
'audio/ogg',
'audio/mp4',
'audio/mpeg',
'audio/ogg',
'audio/opus'
]);
@ -142,6 +144,7 @@ export function convert(id, data) {
const meta = {
direct: sources,
audioTracks: data.audioTracks,
textTracks: data.textTracks,
thumbnail: data.thumbnail, // Currently ignored by Media
live: !!data.live // Currently ignored by Media
@ -170,11 +173,12 @@ export function validate(data) {
validateURL(data.thumbnail);
}
validateSources(data.sources);
validateSources(data.sources, data);
validateAudioTracks(data.audioTracks);
validateTextTracks(data.textTracks);
}
function validateSources(sources) {
function validateSources(sources, data) {
if (!Array.isArray(sources))
throw new ValidationError('sources must be a list');
if (sources.length === 0)
@ -210,6 +214,45 @@ function validateSources(sources) {
}
}
function validateAudioTracks(audioTracks) {
if (typeof audioTracks === 'undefined') {
return;
}
if (!Array.isArray(audioTracks)){
throw new ValidationError('audioTracks must be a list');
}
for (let track of audioTracks) {
if (typeof track.url !== 'string'){
throw new ValidationError('audio track URL must be a string');
}
validateURL(track.url);
if (!AUDIO_ONLY_CONTENT_TYPES.has(track.contentType)){
throw new ValidationError(
`unacceptable audio track contentType "${track.contentType}"`
);
}
if (typeof track.label !== 'string'){
throw new ValidationError('audio track label must be a string');
}
if (!track.label){
throw new ValidationError('audio track label must be nonempty');
}
if (typeof track.language !== 'string'){
throw new ValidationError('audio track language must be a string');
}
if (!track.language){
throw new ValidationError('audio track language must be nonempty');
}
if (!/^[a-z]{2,3}$/.test(track.language)){
throw new ValidationError('audio track language must be a two or three letter IETF BCP 47 subtag');
}
}
}
function validateTextTracks(textTracks) {
if (typeof textTracks === 'undefined') {
return;

View file

@ -38,7 +38,8 @@ Media.prototype = {
scuri: this.meta.scuri,
embed: this.meta.embed,
gdrive_subtitles: this.meta.gdrive_subtitles,
textTracks: this.meta.textTracks
textTracks: this.meta.textTracks,
audioTracks: this.meta.audioTracks
}
};