From 04ac665bbde74d7dc413f72e82b56247823e5e49 Mon Sep 17 00:00:00 2001 From: Serhii Marchenko Date: Mon, 4 Nov 2024 13:56:45 +0200 Subject: [PATCH 1/4] feat(FEC-14087): audio-description flavours --- src/player.ts | 21 +++++++++++++++++++++ src/track/audio-track.ts | 9 +++++++-- src/track/track.ts | 9 +++++++++ src/types/metadata-config.ts | 1 + 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/player.ts b/src/player.ts index ebf5ee0a5..d069d8682 100644 --- a/src/player.ts +++ b/src/player.ts @@ -2470,6 +2470,27 @@ export default class Player extends FakeEventTarget { */ public _updateTracks(tracks: Array): void { Player._logger.debug('Tracks changed', tracks); + + if (this._sources.metadata?.audioFlavors) { + let audioTracksIndex = 0; + // iterate over the audio tracks and set the isAudioDescription flag based on the audioFlavors metadata + tracks.forEach((track) => { + if (track instanceof AudioTrack) { + track.isAudioDescription = Boolean(this._sources.metadata.audioFlavors?.[audioTracksIndex]?.isAudioDescription); + if (track.isAudioDescription) { + // set the language to ad- for audio description tracks + // track.language = `ad-${track.language}`; + track.language = `${track.language}-ad`; + if (!this._sources.metadata?.audioFlavors?.[audioTracksIndex]?.label) { + // add "Audio Description" to the label if custom label is not provided + track.label = `${track.label} - Audio Description`; + } + } + audioTracksIndex++; + } + }); + } + this._tracks = tracks?.concat(this._externalCaptionsHandler.getExternalTracks(tracks)); this._applyABRRestriction(this._config); this._addTextTrackOffOption(); diff --git a/src/track/audio-track.ts b/src/track/audio-track.ts index b7ebabd00..35b6723fa 100644 --- a/src/track/audio-track.ts +++ b/src/track/audio-track.ts @@ -1,10 +1,15 @@ -//@flow import Track from './track'; /** * Audio track representation of the player. * @classdesc */ -class AudioTrack extends Track {} +class AudioTrack extends Track { + /** + * @member - is audio asset has audio description tag + * @type {boolean|undefined} + */ + public isAudioDescription?: boolean; +} export default AudioTrack; diff --git a/src/track/track.ts b/src/track/track.ts index 48bb3f6a3..bd8d1a03a 100644 --- a/src/track/track.ts +++ b/src/track/track.ts @@ -197,6 +197,15 @@ export default class Track { this._available = isAvailable; } + /** + * Setter for the language of the track. + * @public + * @param {string} value - The language of the track. + */ + public set language(value: string) { + this._language = value; + } + /** * @constructor * @param {Object} settings - The track settings object. diff --git a/src/types/metadata-config.ts b/src/types/metadata-config.ts index cc620d0a0..5007729b4 100644 --- a/src/types/metadata-config.ts +++ b/src/types/metadata-config.ts @@ -6,4 +6,5 @@ export type PKMetadataConfigObject = { tags?: Object, epgId?: string, recordingId?: string + audioFlavors?: Array, }; From 9223d21aabf5c46b5c63735154cd35699d83c31e Mon Sep 17 00:00:00 2001 From: Serhii Marchenko Date: Tue, 5 Nov 2024 16:50:39 +0200 Subject: [PATCH 2/4] feat(FEC-14087): add configuration --- docs/configuration.md | 13 +++++++++++++ flow-typed/types/playback-config.js | 1 + src/player-config.js | 1 + src/player.ts | 5 ++--- src/types/playback-config.ts | 1 + 5 files changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index edfa105c7..0fe85e9d2 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -54,6 +54,7 @@ var config = { autoplay: false, loop: false, allowMutedAutoPlay: true, + updateAudioDescriptionFlavors: true, muted: false, pictureInPicture: true, options: { @@ -792,6 +793,7 @@ var config = { > loop: boolean, > autopause: boolean, > allowMutedAutoPlay: boolean, +> updateAudioDescriptionFlavors: boolean, > muted: boolean, > pictureInPicture: boolean, > options: PKPlaybackOptionsObject, @@ -818,6 +820,7 @@ var config = { > autoplay: false, > loop: false, > allowMutedAutoPlay: true, +> updateAudioDescriptionFlavors: true, > muted: false, > pictureInPicture: true, > playAdsWithMSE: false, @@ -1078,6 +1081,16 @@ var config = { > > ## > +> > ### config.playback.updateAudioDescriptionFlavors +> > +> > ##### Type: `boolean` +> > +> > ##### Default: `true` +> > +> > ##### Description: Updates audio flavors that has "audio_description" tag +> +> ## +> > > ### config.playback.autopause > > > > ##### Type: `boolean` diff --git a/flow-typed/types/playback-config.js b/flow-typed/types/playback-config.js index 41dd0effc..a7124bd8b 100644 --- a/flow-typed/types/playback-config.js +++ b/flow-typed/types/playback-config.js @@ -11,6 +11,7 @@ declare type PKPlaybackConfigObject = { preload: string, autoplay: PKAutoPlayTypes, allowMutedAutoPlay: boolean, + updateAudioDescriptionFlavors: boolean, muted: boolean, pictureInPicture: boolean, streamPriority: Array, diff --git a/src/player-config.js b/src/player-config.js index 4e712ef45..4780de8a6 100644 --- a/src/player-config.js +++ b/src/player-config.js @@ -23,6 +23,7 @@ const DefaultConfig = { loop: false, autopause: false, allowMutedAutoPlay: true, + updateAudioDescriptionFlavors: true, muted: false, pictureInPicture: true, options: { diff --git a/src/player.ts b/src/player.ts index d069d8682..3edfdab1d 100644 --- a/src/player.ts +++ b/src/player.ts @@ -2471,7 +2471,7 @@ export default class Player extends FakeEventTarget { public _updateTracks(tracks: Array): void { Player._logger.debug('Tracks changed', tracks); - if (this._sources.metadata?.audioFlavors) { + if (this.config.playback.updateAudioDescriptionFlavors && this._sources.metadata?.audioFlavors) { let audioTracksIndex = 0; // iterate over the audio tracks and set the isAudioDescription flag based on the audioFlavors metadata tracks.forEach((track) => { @@ -2479,8 +2479,7 @@ export default class Player extends FakeEventTarget { track.isAudioDescription = Boolean(this._sources.metadata.audioFlavors?.[audioTracksIndex]?.isAudioDescription); if (track.isAudioDescription) { // set the language to ad- for audio description tracks - // track.language = `ad-${track.language}`; - track.language = `${track.language}-ad`; + track.language = `ad-${track.language}`; if (!this._sources.metadata?.audioFlavors?.[audioTracksIndex]?.label) { // add "Audio Description" to the label if custom label is not provided track.label = `${track.label} - Audio Description`; diff --git a/src/types/playback-config.ts b/src/types/playback-config.ts index d085badca..dc6268bf6 100644 --- a/src/types/playback-config.ts +++ b/src/types/playback-config.ts @@ -14,6 +14,7 @@ export type PKPlaybackConfigObject = { preload: string, autoplay: PKAutoPlayTypes, allowMutedAutoPlay: boolean, + updateAudioDescriptionFlavors: boolean, muted: boolean, pictureInPicture: boolean, streamPriority: Array, From f48ae8e225c45b7b1e3d0770e7c3249b142f9a5e Mon Sep 17 00:00:00 2001 From: Serhii Marchenko Date: Wed, 6 Nov 2024 16:08:27 +0200 Subject: [PATCH 3/4] feat(FEC-14087): address PR comments --- docs/configuration.md | 8 +++---- flow-typed/types/playback-config.js | 2 +- src/player-config.js | 2 +- src/player.ts | 25 ++++---------------- src/track/audio-track.ts | 36 +++++++++++++++++++++++++---- src/types/playback-config.ts | 2 +- 6 files changed, 43 insertions(+), 32 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 0fe85e9d2..66cd2ba50 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -54,7 +54,7 @@ var config = { autoplay: false, loop: false, allowMutedAutoPlay: true, - updateAudioDescriptionFlavors: true, + updateAudioDescriptionLabels: true, muted: false, pictureInPicture: true, options: { @@ -793,7 +793,7 @@ var config = { > loop: boolean, > autopause: boolean, > allowMutedAutoPlay: boolean, -> updateAudioDescriptionFlavors: boolean, +> updateAudioDescriptionLabels: boolean, > muted: boolean, > pictureInPicture: boolean, > options: PKPlaybackOptionsObject, @@ -820,7 +820,7 @@ var config = { > autoplay: false, > loop: false, > allowMutedAutoPlay: true, -> updateAudioDescriptionFlavors: true, +> updateAudioDescriptionLabels: true, > muted: false, > pictureInPicture: true, > playAdsWithMSE: false, @@ -1081,7 +1081,7 @@ var config = { > > ## > -> > ### config.playback.updateAudioDescriptionFlavors +> > ### config.playback.updateAudioDescriptionLabels > > > > ##### Type: `boolean` > > diff --git a/flow-typed/types/playback-config.js b/flow-typed/types/playback-config.js index a7124bd8b..916fafadc 100644 --- a/flow-typed/types/playback-config.js +++ b/flow-typed/types/playback-config.js @@ -11,7 +11,7 @@ declare type PKPlaybackConfigObject = { preload: string, autoplay: PKAutoPlayTypes, allowMutedAutoPlay: boolean, - updateAudioDescriptionFlavors: boolean, + updateAudioDescriptionLabels: boolean, muted: boolean, pictureInPicture: boolean, streamPriority: Array, diff --git a/src/player-config.js b/src/player-config.js index 4780de8a6..15e212c6c 100644 --- a/src/player-config.js +++ b/src/player-config.js @@ -23,7 +23,7 @@ const DefaultConfig = { loop: false, autopause: false, allowMutedAutoPlay: true, - updateAudioDescriptionFlavors: true, + updateAudioDescriptionLabels: true, muted: false, pictureInPicture: true, options: { diff --git a/src/player.ts b/src/player.ts index 3edfdab1d..136975908 100644 --- a/src/player.ts +++ b/src/player.ts @@ -11,7 +11,7 @@ import getLogger, { getLogLevel, LogLevel, LogLevelType, setLogHandler, setLogLe import StateManager from './state/state-manager'; import Track from './track/track'; import VideoTrack from './track/video-track'; -import AudioTrack from './track/audio-track'; +import AudioTrack, { audioDescriptionTrackHandler } from './track/audio-track'; import { PKTextTrack } from './track/text-track'; import TextStyle from './track/text-style'; import { processCues } from './track/text-track-display'; @@ -1294,7 +1294,7 @@ export default class Player extends FakeEventTarget { * @returns {void} * @public */ - public changeQuality(track: any | string): void{ + public changeQuality(track: any | string): void { if (track === 'auto') { this.enableAdaptiveBitrate(); } else { @@ -2042,7 +2042,7 @@ export default class Player extends FakeEventTarget { if (window.self !== window.top) { const head = Utils.Dom.getElementBySelector('head'); let title = head.querySelector('title'); - if (!title){ + if (!title) { title = Utils.Dom.createElement('title'); head.appendChild(title); } @@ -2471,23 +2471,8 @@ export default class Player extends FakeEventTarget { public _updateTracks(tracks: Array): void { Player._logger.debug('Tracks changed', tracks); - if (this.config.playback.updateAudioDescriptionFlavors && this._sources.metadata?.audioFlavors) { - let audioTracksIndex = 0; - // iterate over the audio tracks and set the isAudioDescription flag based on the audioFlavors metadata - tracks.forEach((track) => { - if (track instanceof AudioTrack) { - track.isAudioDescription = Boolean(this._sources.metadata.audioFlavors?.[audioTracksIndex]?.isAudioDescription); - if (track.isAudioDescription) { - // set the language to ad- for audio description tracks - track.language = `ad-${track.language}`; - if (!this._sources.metadata?.audioFlavors?.[audioTracksIndex]?.label) { - // add "Audio Description" to the label if custom label is not provided - track.label = `${track.label} - Audio Description`; - } - } - audioTracksIndex++; - } - }); + if (this.config.playback.updateAudioDescriptionLabels) { + audioDescriptionTrackHandler(tracks, this._sources.metadata?.audioFlavors); } this._tracks = tracks?.concat(this._externalCaptionsHandler.getExternalTracks(tracks)); diff --git a/src/track/audio-track.ts b/src/track/audio-track.ts index 35b6723fa..e6ebe2987 100644 --- a/src/track/audio-track.ts +++ b/src/track/audio-track.ts @@ -1,15 +1,41 @@ import Track from './track'; +enum FlavorAssetTags { + AUDIO_ONLY = 'audio_only', + AUDIO_DESCRIPTION = 'audio_description' +} + /** * Audio track representation of the player. * @classdesc */ class AudioTrack extends Track { - /** - * @member - is audio asset has audio description tag - * @type {boolean|undefined} - */ - public isAudioDescription?: boolean; + /** + * @member - is audio asset has audio description tag + * @type {boolean|undefined} + */ + public isAudioDescription?: boolean; +} + +export function audioDescriptionTrackHandler(tracks: AudioTrack[], audioFlavors?: Array): void { + if (tracks?.length) { + let audioTracksIndex = 0; + // iterate over the audio tracks and set the isAudioDescription flag based on the audioFlavors tags + tracks.forEach((track) => { + if (track instanceof AudioTrack) { + track.isAudioDescription = audioFlavors?.[audioTracksIndex]?.tags?.includes(FlavorAssetTags.AUDIO_DESCRIPTION); + if (track.isAudioDescription) { + // set the language to ad- for audio description tracks + track.language = `ad-${track.language}`; + if (!audioFlavors?.[audioTracksIndex]?.label) { + // add "Audio Description" to the label if custom label is not provided + track.label = `${track.label} - Audio Description`; + } + } + audioTracksIndex++; + } + }); + } } export default AudioTrack; diff --git a/src/types/playback-config.ts b/src/types/playback-config.ts index dc6268bf6..d38eb14d4 100644 --- a/src/types/playback-config.ts +++ b/src/types/playback-config.ts @@ -14,7 +14,7 @@ export type PKPlaybackConfigObject = { preload: string, autoplay: PKAutoPlayTypes, allowMutedAutoPlay: boolean, - updateAudioDescriptionFlavors: boolean, + updateAudioDescriptionLabels: boolean, muted: boolean, pictureInPicture: boolean, streamPriority: Array, From c580c625025ad43ca3787086e3d2504830cbf887 Mon Sep 17 00:00:00 2001 From: Serhii Marchenko Date: Wed, 6 Nov 2024 23:34:48 +0200 Subject: [PATCH 4/4] feat(FEC-14087): address PR comments 2 --- src/track/audio-track.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/track/audio-track.ts b/src/track/audio-track.ts index e6ebe2987..d6b038d37 100644 --- a/src/track/audio-track.ts +++ b/src/track/audio-track.ts @@ -9,22 +9,16 @@ enum FlavorAssetTags { * Audio track representation of the player. * @classdesc */ -class AudioTrack extends Track { - /** - * @member - is audio asset has audio description tag - * @type {boolean|undefined} - */ - public isAudioDescription?: boolean; -} +class AudioTrack extends Track {} export function audioDescriptionTrackHandler(tracks: AudioTrack[], audioFlavors?: Array): void { - if (tracks?.length) { + if (tracks?.length && audioFlavors?.length) { let audioTracksIndex = 0; // iterate over the audio tracks and set the isAudioDescription flag based on the audioFlavors tags tracks.forEach((track) => { if (track instanceof AudioTrack) { - track.isAudioDescription = audioFlavors?.[audioTracksIndex]?.tags?.includes(FlavorAssetTags.AUDIO_DESCRIPTION); - if (track.isAudioDescription) { + const isAudioDescription = audioFlavors[audioTracksIndex]?.tags?.includes(FlavorAssetTags.AUDIO_DESCRIPTION); + if (isAudioDescription) { // set the language to ad- for audio description tracks track.language = `ad-${track.language}`; if (!audioFlavors?.[audioTracksIndex]?.label) {