Skip to content

Commit

Permalink
feat: caption refactor + support cvaa & default audio/text tracks (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
OrenMe authored and Dan Ziv committed Oct 2, 2017
1 parent 8ea0371 commit 187cf78
Show file tree
Hide file tree
Showing 17 changed files with 5,162 additions and 6,857 deletions.
10,195 changes: 3,371 additions & 6,824 deletions dist/playkit.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/playkit.js.map

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions src/assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,18 @@
background-position: center center;
background-repeat: no-repeat;
}

.playkit-subtitles {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
}

.playkit-subtitles > div > div {
-webkit-transition: 0.3s ease-in-out;
-moz-transition: 0.3s ease-in-out;
-o-transition: 0.3s ease-in-out;
transition: 0.3s ease-in-out;
}
113 changes: 106 additions & 7 deletions src/engines/html5/html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {HTML5_EVENTS as Html5Events, CUSTOM_EVENTS as CustomEvents} from '../../
import MediaSourceProvider from './media-source/media-source-provider'
import VideoTrack from '../../track/video-track'
import AudioTrack from '../../track/audio-track'
import TextTrack from '../../track/text-track'
import {TextTrack as PKTextTrack} from '../../track/text-track'
import {Cue} from '../../track/vtt-cue'
import * as Utils from '../../utils/util'

/**
Expand All @@ -33,6 +34,20 @@ export default class Html5 extends FakeEventTarget implements IEngine {
*/
_mediaSourceAdapter: ?IMediaSourceAdapter;

/**
* Flag to indicate first time text track cue change.
* @type {Object.<number, boolean>}
* @private
*/
_showTextTrackFirstTime: { [number]: boolean } = {};

/**
* player config object.
* @type {Object}
* @private
*/
_config: Object;

/**
* @type {string} - The engine id.
*/
Expand Down Expand Up @@ -69,9 +84,10 @@ export default class Html5 extends FakeEventTarget implements IEngine {
*/
constructor(source: Source, config: Object) {
super();
this._config = config;
this._eventManager = new EventManager();
this._createVideoElement();
this._loadMediaSourceAdapter(source, config);
this._loadMediaSourceAdapter(source);
this.attach();
}

Expand All @@ -93,6 +109,7 @@ export default class Html5 extends FakeEventTarget implements IEngine {
this._el.parentNode.removeChild(this._el);
}
}
this._showTextTrackFirstTime = {};
this._eventManager.destroy();
}

Expand Down Expand Up @@ -121,6 +138,7 @@ export default class Html5 extends FakeEventTarget implements IEngine {
this._eventManager.listen(this._mediaSourceAdapter, CustomEvents.AUDIO_TRACK_CHANGED, (event: FakeEvent) => this.dispatchEvent(event));
this._eventManager.listen(this._mediaSourceAdapter, CustomEvents.TEXT_TRACK_CHANGED, (event: FakeEvent) => this.dispatchEvent(event));
this._eventManager.listen(this._mediaSourceAdapter, CustomEvents.ABR_MODE_CHANGED, (event: FakeEvent) => this.dispatchEvent(event));
this._eventManager.listen(this._mediaSourceAdapter, CustomEvents.TEXT_CUE_CHANGED, (event: FakeEvent) => this.dispatchEvent(event));
}
}

Expand All @@ -137,6 +155,7 @@ export default class Html5 extends FakeEventTarget implements IEngine {
this._eventManager.unlisten(this._mediaSourceAdapter, CustomEvents.VIDEO_TRACK_CHANGED);
this._eventManager.unlisten(this._mediaSourceAdapter, CustomEvents.AUDIO_TRACK_CHANGED);
this._eventManager.unlisten(this._mediaSourceAdapter, CustomEvents.TEXT_TRACK_CHANGED);
this._eventManager.unlisten(this._mediaSourceAdapter, CustomEvents.TEXT_CUE_CHANGED);
}
}

Expand All @@ -162,12 +181,11 @@ export default class Html5 extends FakeEventTarget implements IEngine {
/**
* Loads the appropriate media source extension adapter.
* @param {Source} source - The selected source object.
* @param {Object} config - The media source extension configuration.
* @private
* @returns {void}
*/
_loadMediaSourceAdapter(source: Source, config: Object): void {
this._mediaSourceAdapter = MediaSourceProvider.getMediaSourceAdapter(this.getVideoElement(), source, config);
_loadMediaSourceAdapter(source: Source): void {
this._mediaSourceAdapter = MediaSourceProvider.getMediaSourceAdapter(this.getVideoElement(), source, this._config);
}

/**
Expand All @@ -194,13 +212,93 @@ export default class Html5 extends FakeEventTarget implements IEngine {

/**
* Select a new text track.
* @param {TextTrack} textTrack - The text track object to set.
* @param {PKTextTrack} textTrack - The playkit text track object to set.
* @returns {void}
*/
selectTextTrack(textTrack: TextTrack): void {
selectTextTrack(textTrack: PKTextTrack): void {
this._removeCueChangeListener();
if (this._mediaSourceAdapter) {
this._mediaSourceAdapter.selectTextTrack(textTrack);
}
this._addCueChangeListener(textTrack);
}

/**
* Add cuechange listener to active textTrack.
* @param {PKTextTrack} textTrack - The playkit text track object to set.
* @returns {void}
* @private
*/
_addCueChangeListener(textTrack: PKTextTrack): void {
let textTrackEl = this._getSelectedTextTrackElement();
if (textTrackEl) {
/*
There's a quirk in TextTrackAPI that a text track added to video element will not fire cuechange event if it
didn't have it's mode set to showing for at least until a single cue has been change.
After first time it seems there's time tracking which allows the cuechange to fire even though the track mode
is set to hidden
This is not the case with a track DOM element added to a video element where cuechange will be fired even if
track mode is set only to hidden and was never set to showing
*/
if (this._config.playback.useNativeTextTrack) {
textTrackEl.mode = "showing";
} else {
textTrackEl.mode = this._showTextTrackFirstTime[textTrack.index] ? "hidden" : "showing";
this._showTextTrackFirstTime[textTrack.index] = true;
textTrackEl.oncuechange = (e) => this._onCueChange(e);
}
}
}

/**
* Remove cuechange listener to active textTrack
* @returns {void}
* @private
*/
_removeCueChangeListener(): void {
let textTrackEl: TextTrack = this._getSelectedTextTrackElement();
if (textTrackEl) {
textTrackEl.oncuechange = null;
}
}

/**
* oncuechange event handler.
* @param {FakeEvent} e - The event arg.
* @returns {void}
* @private
*/
_onCueChange(e: FakeEvent): void {
let textTrack: TextTrack = e.currentTarget;
let activeCues: Array<Cue> = [];
textTrack.mode = 'hidden';
for (let cue of textTrack.activeCues) {
//Normalize cues to be of type of VTT model
if (cue instanceof window.VTTCue) {
activeCues.push(cue);
} else if (cue instanceof window.TextTrackCue) {
activeCues.push(new Cue(cue.startTime, cue.endTime, cue.text));
}
}
this.dispatchEvent(new FakeEvent(CustomEvents.TEXT_CUE_CHANGED, {cues: activeCues}));
}

/**
* Get currently selected text track
* @returns {?TextTrack} - returns the active text track element if available
* @private
*/
_getSelectedTextTrackElement(): ?TextTrack {
const textTracks = this._el.textTracks;
for (let track in textTracks) {
if (textTracks.hasOwnProperty(track)) {
const textTrack = textTracks[parseInt(track)];
if (textTrack && textTrack.mode !== "disabled") {
return textTrack;
}
}
}
return null;
}

/**
Expand All @@ -213,6 +311,7 @@ export default class Html5 extends FakeEventTarget implements IEngine {
if (this._mediaSourceAdapter) {
this._mediaSourceAdapter.hideTextTrack();
}
this._removeCueChangeListener();
}

/**
Expand Down
13 changes: 7 additions & 6 deletions src/engines/html5/media-source/adapters/native-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {HTML5_EVENTS as Html5Events} from '../../../../event/events'
import Track from '../../../../track/track'
import VideoTrack from '../../../../track/video-track'
import AudioTrack from '../../../../track/audio-track'
import TextTrack from '../../../../track/text-track'
import {TextTrack as PKTextTrack} from '../../../../track/text-track'
import BaseMediaSourceAdapter from '../base-media-source-adapter'
import {getSuitableSourceForResolution} from '../../../../utils/resolution'
import * as Utils from '../../../../utils/util'
Expand Down Expand Up @@ -344,7 +344,7 @@ export default class NativeAdapter extends BaseMediaSourceAdapter {
language: textTracks[i].language,
index: i
};
parsedTracks.push(new TextTrack(settings));
parsedTracks.push(new PKTextTrack(settings));
}
}
return parsedTracks;
Expand Down Expand Up @@ -440,15 +440,16 @@ export default class NativeAdapter extends BaseMediaSourceAdapter {
/**
* Select a text track
* @function selectTextTrack
* @param {TextTrack} textTrack - the track to select
* @param {PKTextTrack} textTrack - The playkit text track
* @returns {void}
* @public
*/
selectTextTrack(textTrack: TextTrack): void {
selectTextTrack(textTrack: PKTextTrack): void {
let textTracks = this._videoElement.textTracks;
if ((textTrack instanceof TextTrack) && (textTrack.kind === 'subtitles' || textTrack.kind === 'captions') && textTracks && textTracks[textTrack.index]) {
if ((textTrack instanceof PKTextTrack) && (textTrack.kind === 'subtitles' || textTrack.kind === 'captions') && textTracks && textTracks[textTrack.index]) {
this._disableTextTracks();
textTracks[textTrack.index].mode = 'showing';
textTracks[textTrack.index].mode = 'hidden';
NativeAdapter._logger.debug('Text track changed', textTrack);
this._onTrackChanged(textTrack);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/event/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ const CUSTOM_EVENTS: { [event: string]: string } = {
* Fires when the active text track has been changed
*/
TEXT_TRACK_CHANGED: 'texttrackchanged',
/**
* Fires when the active text track cue has changed
*/
TEXT_CUE_CHANGED: 'textcuechanged',
/**
* Fires when the player tracks have been changed
*/
Expand Down
1 change: 1 addition & 0 deletions src/player-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"playback": {
"audioLanguage": "",
"textLanguage": "",
"useNativeTextTrack": false,
"volume": 1,
"playsinline": false,
"preload": "none",
Expand Down
Loading

0 comments on commit 187cf78

Please sign in to comment.