From 3c2e365b9cc0161a5373ccbbf1d1c971fa79435b Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 7 Nov 2024 10:24:08 +0200 Subject: [PATCH] feat(FEC-14087): define audio-description audio tracks (#797) ### Description of the Changes resolves: https://kaltura.atlassian.net/browse/FEC-14087 ### CheckLists - [ ] changes have been done against master branch, and PR does not conflict - [ ] new unit / functional tests have been added (whenever applicable) - [ ] test are passing in local environment - [ ] Travis tests are passing (or test results are not worse than on master branch :)) - [ ] Docs have been updated --- docs/configuration.md | 13 +++++++++++++ flow-typed/types/playback-config.js | 1 + src/player-config.js | 1 + src/player.ts | 11 ++++++++--- src/track/audio-track.ts | 27 ++++++++++++++++++++++++++- src/track/track.ts | 9 +++++++++ src/types/metadata-config.ts | 1 + src/types/playback-config.ts | 1 + 8 files changed, 60 insertions(+), 4 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index edfa105c7..66cd2ba50 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -54,6 +54,7 @@ var config = { autoplay: false, loop: false, allowMutedAutoPlay: true, + updateAudioDescriptionLabels: true, muted: false, pictureInPicture: true, options: { @@ -792,6 +793,7 @@ var config = { > loop: boolean, > autopause: boolean, > allowMutedAutoPlay: boolean, +> updateAudioDescriptionLabels: boolean, > muted: boolean, > pictureInPicture: boolean, > options: PKPlaybackOptionsObject, @@ -818,6 +820,7 @@ var config = { > autoplay: false, > loop: false, > allowMutedAutoPlay: true, +> updateAudioDescriptionLabels: true, > muted: false, > pictureInPicture: true, > playAdsWithMSE: false, @@ -1078,6 +1081,16 @@ var config = { > > ## > +> > ### config.playback.updateAudioDescriptionLabels +> > +> > ##### 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..916fafadc 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, + updateAudioDescriptionLabels: boolean, muted: boolean, pictureInPicture: boolean, streamPriority: Array, diff --git a/src/player-config.js b/src/player-config.js index 4e712ef45..15e212c6c 100644 --- a/src/player-config.js +++ b/src/player-config.js @@ -23,6 +23,7 @@ const DefaultConfig = { loop: false, autopause: false, allowMutedAutoPlay: true, + updateAudioDescriptionLabels: true, muted: false, pictureInPicture: true, options: { diff --git a/src/player.ts b/src/player.ts index ebf5ee0a5..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); } @@ -2470,6 +2470,11 @@ export default class Player extends FakeEventTarget { */ public _updateTracks(tracks: Array): void { Player._logger.debug('Tracks changed', tracks); + + if (this.config.playback.updateAudioDescriptionLabels) { + audioDescriptionTrackHandler(tracks, this._sources.metadata?.audioFlavors); + } + 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..d6b038d37 100644 --- a/src/track/audio-track.ts +++ b/src/track/audio-track.ts @@ -1,10 +1,35 @@ -//@flow 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 {} +export function audioDescriptionTrackHandler(tracks: AudioTrack[], audioFlavors?: Array): void { + 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) { + 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) { + // 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/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, }; diff --git a/src/types/playback-config.ts b/src/types/playback-config.ts index d085badca..d38eb14d4 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, + updateAudioDescriptionLabels: boolean, muted: boolean, pictureInPicture: boolean, streamPriority: Array,