Skip to content

Commit

Permalink
feat(FEC-8390, FEC-8246): support 608/708 captions (#67)
Browse files Browse the repository at this point in the history
parse 608/708 tracks by the video element `textTrack` api
depends on 
kaltura/playkit-js#265
kaltura/playkit-js-ui#254
  • Loading branch information
yairans authored Jul 17, 2018
1 parent f2dca55 commit 39e8e09
Showing 1 changed file with 90 additions and 5 deletions.
95 changes: 90 additions & 5 deletions src/hls-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
* @private
*/
_onRecoveredCallback: ?Function;
_onAddTrack: Function;

/**
* Factory method to create media source adapter.
Expand Down Expand Up @@ -142,6 +143,11 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
if (Utils.Object.hasPropertyPath(config, 'playback.useNativeTextTrack')) {
adapterConfig.subtitleDisplay = Utils.Object.getPropertyPath(config, 'playback.useNativeTextTrack');
}
adapterConfig.hlsConfig.enableCEA708Captions = config.playback.enableCEA708Captions;
adapterConfig.hlsConfig.captionsTextTrack1Label = config.playback.captionsTextTrack1Label;
adapterConfig.hlsConfig.captionsTextTrack1LanguageCode = config.playback.captionsTextTrack1LanguageCode;
adapterConfig.hlsConfig.captionsTextTrack2Label = config.playback.captionsTextTrack2Label;
adapterConfig.hlsConfig.captionsTextTrack2LanguageCode = config.playback.captionsTextTrack2LanguageCode;
return new this(videoElement, source, adapterConfig);
}

Expand Down Expand Up @@ -213,6 +219,21 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
this._onRecoveredCallback = () => this._onRecovered();
this._onVideoErrorCallback = e => this._onVideoError(e);
this._videoElement.addEventListener(EventType.ERROR, this._onVideoErrorCallback);
this._onAddTrack = this._onAddTrack.bind(this);
this._videoElement.addEventListener('addtrack', this._onAddTrack);
this._videoElement.textTracks.onaddtrack = this._onAddTrack;
}

_onAddTrack(event: any) {
if (!this._hls.subtitleTracks.length) {
// parse CEA 608/708 captions that not exposed on hls.subtitleTracks API
const CEATextTrack = this._parseCEATextTrack(event.track);
if (CEATextTrack) {
HlsAdapter._logger.debug('A CEA 608/708 caption has found', CEATextTrack);
this._playerTracks.push(CEATextTrack);
this._trigger(EventType.TRACKS_CHANGED, {tracks: this._playerTracks});
}
}
}

/**
Expand Down Expand Up @@ -438,6 +459,28 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
return textTracks;
}

/**
* Parse a CEA 608/708 text track which not expose on hlsjs api into player text tracks.
* @param {Object} CEATextTrack - A video element text track.
* @returns {?TextTrack} - A parsed text track if the param is a CEA 608/708 caption.
* @private
*/
_parseCEATextTrack(CEATextTrack: Object): ?TextTrack {
let textTrack = null;
if (CEATextTrack.kind === 'captions') {
const settings = {
id: CEATextTrack.id,
active: CEATextTrack.mode === 'showing',
label: CEATextTrack.label,
kind: CEATextTrack.kind,
language: CEATextTrack.language,
index: this._playerTracks.filter(track => track instanceof TextTrack).length
};
textTrack = new TextTrack(settings);
}
return textTrack;
}

/**
* Select an audio track.
* @function selectAudioTrack
Expand Down Expand Up @@ -475,20 +518,59 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
* @public
*/
selectTextTrack(textTrack: TextTrack): void {
if (textTrack instanceof TextTrack && !textTrack.active && this._videoElement.textTracks) {
this._hls.subtitleTrack = textTrack.index;
HlsAdapter._logger.debug('Text track changed', textTrack);
this._onTrackChanged(textTrack);
if (textTrack instanceof TextTrack && !textTrack.active) {
if (this._hls.subtitleTracks.length) {
this._hls.subtitleTrack = textTrack.id;
this._notifyTrackChanged(textTrack);
} else {
this._selectNativeTextTrack(textTrack);
}
}
}

/**
* Select a video element text track.
* @function _selectNativeTextTrack
* @param {TextTrack} textTrack - the track to select.
* @returns {void}
* @private
*/
_selectNativeTextTrack(textTrack: TextTrack): void {
const selectedTrack = Array.from(this._videoElement.textTracks).find(track => track.language === textTrack.language);
if (selectedTrack) {
this._disableNativeTextTracks();
selectedTrack.mode = this._config.subtitleDisplay ? 'showing' : 'hidden';
this._notifyTrackChanged(textTrack);
}
}

_notifyTrackChanged(textTrack: TextTrack): void {
HlsAdapter._logger.debug('Text track changed', textTrack);
this._onTrackChanged(textTrack);
}

/**
* Disables all the video element text tracks.
* @private
* @returns {void}
*/
_disableNativeTextTracks(): void {
Array.from(this._videoElement.textTracks).forEach(track => {
track.mode = 'disabled';
});
}

/** Hide the text track
* @function hideTextTrack
* @returns {void}
* @public
*/
hideTextTrack(): void {
this._hls.subtitleTrack = -1;
if (this._hls.subtitleTracks.length) {
this._hls.subtitleTrack = -1;
} else {
this._disableNativeTextTracks();
}
}

/**
Expand Down Expand Up @@ -766,6 +848,9 @@ export default class HlsAdapter extends BaseMediaSourceAdapter {
this._hls.off(Hlsjs.Events.ERROR, this._onError);
this._hls.off(Hlsjs.Events.LEVEL_SWITCHED, this._onLevelSwitched);
this._hls.off(Hlsjs.Events.AUDIO_TRACK_SWITCHED, this._onAudioTrackSwitched);
this._hls.off(Hlsjs.Events.MANIFEST_LOADED, this._onManifestLoaded);
this._videoElement.textTracks.onaddtrack = null;
this._videoElement.removeEventListener('addtrack', this._onAddTrack);
this._removeRecoveredCallbackListener();
this._removeVideoErrorListener();
this._removeLoadedMetadataListener();
Expand Down

0 comments on commit 39e8e09

Please sign in to comment.