Skip to content

Commit

Permalink
Make language selection explicit. Split text and variant selection.
Browse files Browse the repository at this point in the history
Add UI options to select current audio and text language.
Split selectTrack() into selectText() and selectVariant().
Stop automatically disabling ABR manager when a variant is selected.
Add a warning if selectVariant() is called while abr is enabled.

Issue #412.
Issue #626.

Change-Id: I15f1c3c4fdc6d6b641f708fbef19dbcf10cbcfc6
  • Loading branch information
ismena committed Jan 18, 2017
1 parent ca299b2 commit 23a23b9
Show file tree
Hide file tree
Showing 13 changed files with 638 additions and 265 deletions.
4 changes: 1 addition & 3 deletions demo/controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,7 @@ ShakaControls.prototype.onCaptionClick_ = function() {

/** @private */
ShakaControls.prototype.onTracksChange_ = function() {
var hasText = this.player_.getTracks().some(function(track) {
return track.type == 'text';
});
var hasText = this.player_.getTextTracks().length;
this.captionButton_.style.display = hasText ? 'inherit' : 'none';
};

Expand Down
10 changes: 10 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,21 @@ <h1>Shaka Player <span id="version"></span></h1>

<details class="input">
<summary>Info</summary>
<div class="flex">
<label for="audioLanguages">Audio languages:</label>
<select id="audioLanguages" class="flex-grow"></select>
</div>

<div class="flex">
<label for="variantTracks">Video+audio track combinations:</label>
<select id="variantTracks" class="flex-grow"></select>
</div>

<div class="flex">
<label for="textLanguages">Text languages:</label>
<select id="textLanguages" class="flex-grow"></select>
</div>

<div class="flex">
<label for="textTracks">Text tracks:</label>
<select id="textTracks" class="flex-grow"></select>
Expand Down
204 changes: 169 additions & 35 deletions demo/info_section.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ shakaDemo.setupInfo_ = function() {
'change', shakaDemo.onTrackSelected_);
document.getElementById('textTracks').addEventListener(
'change', shakaDemo.onTrackSelected_);
document.getElementById('audioLanguages').addEventListener(
'change', shakaDemo.onAudioLanguageSelected_);
document.getElementById('textLanguages').addEventListener(
'change', shakaDemo.onTextLanguageSelected_);
};


Expand All @@ -39,11 +43,55 @@ shakaDemo.setupInfo_ = function() {
* @private
*/
shakaDemo.onTracksChanged_ = function(event) {
// Update the track lists.
var lists = {
variant: document.getElementById('variantTracks'),
text: document.getElementById('textTracks')
};
// Update language options first and then populate new tracks with
// respect to the chosen languages.
shakaDemo.updateLanguages_();
shakaDemo.updateVariantTracks_();
shakaDemo.updateTextTracks_();
};


/**
* @private
*/
shakaDemo.updateVariantTracks_ = function() {
var trackList = document.getElementById('variantTracks');
var langList = document.getElementById('audioLanguages');
var language = langList.options[langList.selectedIndex].value;

var tracks = shakaDemo.player_.getVariantTracks();

tracks.sort(function(t1, t2) {
// Sort by bandwidth.
return t1.bandwidth - t2.bandwidth;
});

shakaDemo.updateTrackOptions_(trackList, tracks, language);
};


/**
* @private
*/
shakaDemo.updateTextTracks_ = function() {
var trackList = document.getElementById('textTracks');

var langList = document.getElementById('textLanguages');
var language = langList.options[langList.selectedIndex].value;

var tracks = shakaDemo.player_.getTextTracks();

shakaDemo.updateTrackOptions_(trackList, tracks, language);
};


/**
* @param {Element} list
* @param {!Array.<!shakaExtern.Track>} tracks
* @param {!string} language
* @private
*/
shakaDemo.updateTrackOptions_ = function(list, tracks, language) {
var formatters = {
variant: function(track) {
var trackInfo = '';
Expand All @@ -59,31 +107,16 @@ shakaDemo.onTracksChanged_ = function(event) {
}
};

// Clear the old track lists.
Object.keys(lists).forEach(function(type) {
var list = lists[type];
while (list.firstChild) {
list.removeChild(list.firstChild);
}
});

// Populate with the new tracks.
var tracks = shakaDemo.player_.getTracks();
tracks.sort(function(t1, t2) {
// Sort by type, then language, then by bandwidth.
var ret = t1.type.localeCompare(t2.type);
if (ret) return ret;

if (t1.language) {
ret = t1.language.localeCompare(t2.language);
if (ret) return ret;
}
// Remove old tracks
while (list.firstChild) {
list.removeChild(list.firstChild);
}

return t1.bandwidth - t2.bandwidth;
tracks = tracks.filter(function(track) {
return track.language == language;
});

tracks.forEach(function(track) {
var list = lists[track.type];
if (!list) return;
var option = document.createElement('option');
option.textContent = formatters[track.type](track);
option.track = track;
Expand All @@ -94,22 +127,87 @@ shakaDemo.onTracksChanged_ = function(event) {
};


/**
* @private
*/
shakaDemo.updateLanguages_ = function() {
shakaDemo.updateTextLanguages_();
shakaDemo.updateAudioLanguages_();
};


/**
* Updates options for text language selection.
* @private
*/
shakaDemo.updateTextLanguages_ = function() {
var player = shakaDemo.player_;
var list = document.getElementById('textLanguages');
var languages = player.getTextLanguages();
var tracks = player.getTextTracks();

shakaDemo.updateLanguageOptions_(list, languages, tracks);
};


/**
* Updates options for audio language selection.
* @private
*/
shakaDemo.updateAudioLanguages_ = function() {
var player = shakaDemo.player_;
var list = document.getElementById('audioLanguages');
var languages = player.getAudioLanguages();
var tracks = player.getVariantTracks();

shakaDemo.updateLanguageOptions_(list, languages, tracks);
};


/**
* @param {Element} list
* @param {!Array.<!string>} languages
* @param {!Array.<shakaExtern.Track>} tracks
* @private
*/
shakaDemo.updateLanguageOptions_ =
function(list, languages, tracks) {
// Remove old options
while (list.firstChild) {
list.removeChild(list.firstChild);
}

// Using array.filter(f)[0] as an alternative to array.find(f) which is
// not supported in IE11.
var activeTracks = tracks.filter(function(track) {
return track.active == true;
});
var selectedTrack = activeTracks[0];

// Populate list with new options.
languages.forEach(function(lang) {
var option = document.createElement('option');
option.textContent = lang;
option.value = lang;
option.selected = lang == selectedTrack.language;
list.appendChild(option);
});
};


/**
* @param {!Event} event
* @private
*/
shakaDemo.onAdaptation_ = function(event) {
var lists = {
variant: document.getElementById('variantTracks'),
text: document.getElementById('textTracks')
};
var list = document.getElementById('variantTracks');

// Find the row for the active track and select it.
var tracks = shakaDemo.player_.getVariantTracks();

// Find the rows for the active tracks and select them.
var tracks = shakaDemo.player_.getTracks();
tracks.forEach(function(track) {
if (!track.active) return;

var list = lists[track.type];
for (var i = 0; i < list.options.length; ++i) {
var option = list.options[i];
if (option.value == track.id) {
Expand All @@ -131,7 +229,15 @@ shakaDemo.onTrackSelected_ = function(event) {
var track = option.track;
var player = shakaDemo.player_;

player.selectTrack(track, /* clearBuffer */ true);
if (list.id == 'variantTracks') {
// Disable abr manager before changing tracks
var config = {abr: {enabled: false}};
player.configure(config);

player.selectVariantTrack(track, /* clearBuffer */ true);
} else {
player.selectTextTrack(track);
}

// Adaptation might have been changed by calling selectTrack().
// Update the adaptation checkbox.
Expand All @@ -140,6 +246,34 @@ shakaDemo.onTrackSelected_ = function(event) {
};


/**
* @param {!Event} event
* @private
*/
shakaDemo.onAudioLanguageSelected_ = function(event) {
var list = event.target;
var language = list.options[list.selectedIndex].value;
var player = shakaDemo.player_;

player.selectAudioLanguage(language);
shakaDemo.updateVariantTracks_();
};


/**
* @param {!Event} event
* @private
*/
shakaDemo.onTextLanguageSelected_ = function(event) {
var list = event.target;
var language = list.options[list.selectedIndex].value;
var player = shakaDemo.player_;

player.selectTextLanguage(language);
shakaDemo.updateTextTracks_();
};


/** @private */
shakaDemo.updateDebugInfo_ = function() {
var video = shakaDemo.video_;
Expand Down
6 changes: 2 additions & 4 deletions externs/shaka/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,14 +416,12 @@ shakaExtern.AbrConfiguration;
* @property {string} preferredAudioLanguage
* The preferred language to use for audio tracks. If not given it will use
* the 'main' track.
* Changing this during playback will cause the language selection algorithm
* to run again, and may change the active audio track.
* Changing this during playback will not affect the current playback.
* @property {string} preferredTextLanguage
* The preferred language to use for text tracks. If a matching text track
* is found, and the selected audio and text tracks have different languages,
* the text track will be shown.
* Changing this during playback will cause the language selection algorithm
* to run again, and may change the active text track.
* Changing this during playback will not affect the current playback.
* @property {shakaExtern.Restrictions} restrictions
* The application restrictions to apply to the tracks. The track must
* meet all the restrictions to be playable.
Expand Down
8 changes: 8 additions & 0 deletions lib/cast/cast_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,16 @@ shaka.cast.CastUtils.PlayerEvents = [
*/
shaka.cast.CastUtils.PlayerGetterMethods = [
'drmInfo',
'getAudioLanguages',
'getConfiguration',
'getManifestUri',
'getPlaybackRate',
'getPlayheadTimeAsDate',
'getTextLanguages',
'getTextTracks',
'getTracks',
'getStats',
'getVariantTracks',
'isBuffering',
'isInProgress',
'isLive',
Expand Down Expand Up @@ -151,7 +155,11 @@ shaka.cast.CastUtils.PlayerVoidMethods = [
'cancelTrickPlay',
'configure',
'resetConfiguration',
'selectAudioLanguage',
'selectTextLanguage',
'selectTextTrack',
'selectTrack',
'selectVariantTrack',
'setTextTrackVisibility',
'trickPlay'
];
Expand Down
5 changes: 4 additions & 1 deletion lib/offline/offline_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ shaka.offline.OfflineUtils.getStoredContent = function(manifest) {
var period = shaka.offline.OfflineUtils.reconstructPeriod(
manifest.periods[0], [], timeline);

var tracks = shaka.util.StreamUtils.getTracks(period, {});
var tracks = shaka.util.StreamUtils.getVariantTracks(period, null, null);
var textTracks = shaka.util.StreamUtils.getTextTracks(period, null);

tracks.push.apply(tracks, textTracks);

return {
offlineUri: 'offline:' + manifest.key,
Expand Down
16 changes: 9 additions & 7 deletions lib/offline/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -691,8 +691,13 @@ shaka.offline.Storage.prototype.createOfflineManifest_ = function(
*/
shaka.offline.Storage.prototype.createPeriod_ = function(period) {
var StreamUtils = shaka.util.StreamUtils;
var allTracks = StreamUtils.getTracks(period, {});

var variantTracks = StreamUtils.getVariantTracks(period, null, null);
var textTracks = StreamUtils.getTextTracks(period, null);
var allTracks = variantTracks.concat(textTracks);

var tracks = this.config_.trackSelectionCallback(allTracks);

if (this.firstPeriodTracks_ == null) {
this.firstPeriodTracks_ = tracks;
// Now that the first tracks are chosen, filter again. This ensures all
Expand All @@ -701,23 +706,20 @@ shaka.offline.Storage.prototype.createPeriod_ = function(period) {
}

for (var i = tracks.length - 1; i > 0; --i) {
var found = false;
var foundSimilarTracks = false;
for (var j = i - 1; j >= 0; --j) {
if (tracks[i].type == tracks[j].type &&
tracks[i].kind == tracks[j].kind &&
tracks[i].language == tracks[j].language) {
shaka.log.warning(
'Multiple tracks of the same type/kind/language given.');
found = true;
foundSimilarTracks = true;
break;
}
}
if (found) break;
if (foundSimilarTracks) break;
}

var variantTracks = tracks.filter(function(t) {return t.type == 'variant';});
var textTracks = tracks.filter(function(t) {return t.type == 'text';});

var streams = [];

for (var i = 0; i < variantTracks.length; i++) {
Expand Down
Loading

0 comments on commit 23a23b9

Please sign in to comment.