Skip to content

Commit

Permalink
feat: New autoShowText config to change initial text visibility behav…
Browse files Browse the repository at this point in the history
…ior (shaka-project#3421)

Adds a new autoShowText config to allow apps to choose the behavior of text visibility on startup.

The default is the old behavior (`AutoShowText.IF_SUBTITLES_MAY_BE_NEEDED`), which is to auto-enabled text only if we think subtitles may be needed.  This is when the user's preferred audio language is unavailable, but the preferred text language **is** available.

A new option has been added (`AutoShowText.IF_PREFERRED_TEXT_LANGUAGE`) that will only consider the user's preferred text language.  If a match is found, text is visible on startup.

Finally, we add two additional options that are extremely simple: `AutoShowText.ALWAYS` and `AutoShowText.NEVER`.  Applications that want complete control over text visibility without any "smart" choices made by the player can use these options.

Co-authored-by: Joey Parrish <[email protected]>
  • Loading branch information
valotvince and joeyparrish authored Sep 21, 2022
1 parent 749cf6d commit 5c24410
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 105 deletions.
2 changes: 2 additions & 0 deletions build/types/core
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
+../../lib/abr/ewma_bandwidth_estimator.js
+../../lib/abr/simple_abr_manager.js

+../../lib/config/auto_show_text.js

+../../lib/debug/asserts.js
+../../lib/debug/log.js

Expand Down
5 changes: 5 additions & 0 deletions demo/common/message_ids.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ shakaDemo.MessageIds = {
AUDIO_ROBUSTNESS: 'DEMO_AUDIO_ROBUSTNESS',
AUTO_CORRECT_DASH_DRIFT: 'DEMO_AUTO_CORRECT_DASH_DRIFT',
AUTO_LOW_LATENCY: 'DEMO_AUTO_LOW_LATENCY',
AUTO_SHOW_TEXT: 'DEMO_AUTO_SHOW_TEXT',
AUTO_SHOW_TEXT_NEVER: 'DEMO_AUTO_SHOW_TEXT_NEVER',
AUTO_SHOW_TEXT_ALWAYS: 'DEMO_AUTO_SHOW_TEXT_ALWAYS',
AUTO_SHOW_TEXT_IF_PREFERRED_TEXT_LANGUAGE: 'DEMO_AUTO_SHOW_TEXT_IF_PREFERRED_TEXT_LANGUAGE',
AUTO_SHOW_TEXT_IF_SUBTITLES_MAY_BE_NEEDED: 'DEMO_AUTO_SHOW_TEXT_IF_SUBTITLES_MAY_BE_NEEDED',
AVAILABILITY_WINDOW_OVERRIDE: 'DEMO_AVAILABILITY_WINDOW_OVERRIDE',
BACKOFF_FACTOR: 'DEMO_BACKOFF_FACTOR',
BASE_DELAY: 'DEMO_BASE_DELAY',
Expand Down
59 changes: 56 additions & 3 deletions demo/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,10 +430,27 @@ shakaDemo.Config = class {
addLanguageSection_() {
const MessageIds = shakaDemo.MessageIds;
const docLink = this.resolveExternLink_('.PlayerConfiguration');

const autoShowTextOptions = shaka.config.AutoShowText;
const localize = (name) => shakaDemoMain.getLocalizedString(name);
const autoShowTextOptionNames = {
'NEVER': localize(MessageIds.AUTO_SHOW_TEXT_NEVER),
'ALWAYS': localize(MessageIds.AUTO_SHOW_TEXT_ALWAYS),
'IF_PREFERRED_TEXT_LANGUAGE':
localize(MessageIds.AUTO_SHOW_TEXT_IF_PREFERRED_TEXT_LANGUAGE),
'IF_SUBTITLES_MAY_BE_NEEDED':
localize(MessageIds.AUTO_SHOW_TEXT_IF_SUBTITLES_MAY_BE_NEEDED),
};

this.addSection_(MessageIds.LANGUAGE_SECTION_HEADER, docLink)
.addTextInput_(MessageIds.AUDIO_LANGUAGE, 'preferredAudioLanguage')
.addTextInput_(MessageIds.TEXT_LANGUAGE, 'preferredTextLanguage')
.addTextInput_(MessageIds.TEXT_ROLE, 'preferredTextRole');
.addTextInput_(MessageIds.TEXT_ROLE, 'preferredTextRole')
.addSelectInput_(
MessageIds.AUTO_SHOW_TEXT,
'autoShowText',
autoShowTextOptions,
autoShowTextOptionNames);
const onChange = (input) => {
shakaDemoMain.setUILocale(input.value);
shakaDemoMain.remakeHash();
Expand Down Expand Up @@ -523,7 +540,7 @@ shakaDemo.Config = class {
}
shakaDemoMain.remakeHash();
};
this.addSelectInput_(MessageIds.LOG_LEVEL, logLevels, onChange);
this.addCustomSelectInput_(MessageIds.LOG_LEVEL, logLevels, onChange);
const input = this.latestInput_.input();
switch (shaka['log']['currentLevel']) {
case Level['DEBUG']:
Expand Down Expand Up @@ -705,7 +722,7 @@ shakaDemo.Config = class {
* @return {!shakaDemo.Config}
* @private
*/
addSelectInput_(name, values, onChange, tooltipMessage) {
addCustomSelectInput_(name, values, onChange, tooltipMessage) {
this.createRow_(name, tooltipMessage);
// The input is not provided a name, as (in this enclosed space) it makes
// the actual field unreadable.
Expand All @@ -714,6 +731,42 @@ shakaDemo.Config = class {
return this;
}

/**
* @param {!shakaDemo.MessageIds} name
* @param {string} valueName
* @param {!Object.<string, ?>} options
* @param {!Object.<string, string>} optionNames
* @param {shakaDemo.MessageIds=} tooltipMessage
* @return {!shakaDemo.Config}
* @private
*/
addSelectInput_(name, valueName, options, optionNames, tooltipMessage) {
const onChange = (input) => {
shakaDemoMain.configure(valueName, options[input.value]);
shakaDemoMain.remakeHash();
};

// If there are any translations missing for option names, fill in the
// constant from the enum. This ensures new enum values are usable in the
// demo in some form, even if they are forgotten in the demo config.
for (const key in options) {
if (!(key in optionNames)) {
optionNames[key] = key;
}
}

this.addCustomSelectInput_(name, optionNames, onChange, tooltipMessage);

const initialValue = shakaDemoMain.getCurrentConfigValue(valueName);
for (const key in options) {
if (options[key] == initialValue) {
this.latestInput_.input().value = key;
}
}

return this;
}

/**
* @param {!shakaDemo.MessageIds} name
* @param {shakaDemo.MessageIds=} tooltipMessage
Expand Down
2 changes: 1 addition & 1 deletion demo/demo.less
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ html, body {
.hamburger-menu .mdl-textfield {
padding: 0;
// The default width of 300px is a bit too wide for us.
width: 200px;
width: 220px;
}

.hamburger-menu .mdl-textfield__label {
Expand Down
5 changes: 5 additions & 0 deletions demo/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
"DEMO_AUDIO_ROBUSTNESS": "Audio Robustness",
"DEMO_AUTO_CORRECT_DASH_DRIFT": "Auto-Correct DASH Drift",
"DEMO_AUTO_LOW_LATENCY": "Auto Low Latency Mode",
"DEMO_AUTO_SHOW_TEXT": "Auto-Show Text",
"DEMO_AUTO_SHOW_TEXT_NEVER": "Never",
"DEMO_AUTO_SHOW_TEXT_ALWAYS": "Always",
"DEMO_AUTO_SHOW_TEXT_IF_PREFERRED_TEXT_LANGUAGE": "If preferred text language",
"DEMO_AUTO_SHOW_TEXT_IF_SUBTITLES_MAY_BE_NEEDED": "If subtitles may be needed",
"DEMO_AVAILABILITY_WINDOW_OVERRIDE": "Availability Window Override",
"DEMO_AXINOM": "Axinom",
"DEMO_AZURE_MEDIA_SERVICES": "Azure Media Services",
Expand Down
20 changes: 20 additions & 0 deletions demo/locales/source.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@
"description": "The name of a configuration value.",
"message": "Auto Low Latency Streaming"
},
"DEMO_AUTO_SHOW_TEXT": {
"description": "The name of a configuration value.",
"message": "Auto-Show Text"
},
"DEMO_AUTO_SHOW_TEXT_NEVER": {
"description": "The name of a configuration value.",
"message": "Never"
},
"DEMO_AUTO_SHOW_TEXT_ALWAYS": {
"description": "The name of a configuration value.",
"message": "Always"
},
"DEMO_AUTO_SHOW_TEXT_IF_PREFERRED_TEXT_LANGUAGE": {
"description": "The name of a configuration value.",
"message": "If preferred text language"
},
"DEMO_AUTO_SHOW_TEXT_IF_SUBTITLES_MAY_BE_NEEDED": {
"description": "The name of a configuration value.",
"message": "If subtitles may be needed"
},
"DEMO_AVAILABILITY_WINDOW_OVERRIDE": {
"description": "The name of a configuration value.",
"message": "Availability Window Override"
Expand Down
3 changes: 3 additions & 0 deletions externs/shaka/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,7 @@ shaka.extern.OfflineConfiguration;

/**
* @typedef {{
* autoShowText: shaka.config.AutoShowText,
* drm: shaka.extern.DrmConfiguration,
* manifest: shaka.extern.ManifestConfiguration,
* streaming: shaka.extern.StreamingConfiguration,
Expand All @@ -1199,6 +1200,8 @@ shaka.extern.OfflineConfiguration;
* textDisplayFactory: shaka.extern.TextDisplayer.Factory
* }}
*
* @property {shaka.config.AutoShowText} autoShowText
* Controls behavior of auto-showing text tracks on load().
* @property {shaka.extern.DrmConfiguration} drm
* DRM configuration and settings.
* @property {shaka.extern.ManifestConfiguration} manifest
Expand Down
33 changes: 33 additions & 0 deletions lib/config/auto_show_text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*! @license
* Shaka Player
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

goog.provide('shaka.config.AutoShowText');

/**
* @enum {number}
* @export
*/
shaka.config.AutoShowText = {
/** Never show text automatically on startup. */
'NEVER': 0,
/** Always show text automatically on startup. */
'ALWAYS': 1,
/**
* Show text automatically on startup if it matches the preferred text
* language.
*/
'IF_PREFERRED_TEXT_LANGUAGE': 2,
/**
* Show text automatically on startup if we think that subtitles may be
* needed. This is specifically if the selected text matches the preferred
* text language AND is different from the initial audio language. (Example:
* You prefer English, but the audio is only available in French, so English
* subtitles should be enabled by default.)
* <br>
* This is the default setting.
*/
'IF_SUBTITLES_MAY_BE_NEEDED': 3,
};
62 changes: 43 additions & 19 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ goog.provide('shaka.Player');

goog.require('goog.asserts');
goog.require('shaka.Deprecate');
goog.require('shaka.config.AutoShowText');
goog.require('shaka.log');
goog.require('shaka.media.AdaptationSetCriteria');
goog.require('shaka.media.BufferingObserver');
Expand Down Expand Up @@ -5478,38 +5479,62 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
/**
* Check if we should show text on screen automatically.
*
* The text should automatically be shown if the text is language-compatible
* with the user's text language preference, but not compatible with the
* audio.
*
* For example:
* preferred | chosen | chosen |
* text | text | audio | show
* -----------------------------------
* en-CA | en | jp | true
* en | en-US | fr | true
* fr-CA | en-US | jp | false
* en-CA | en-US | en-US | false
*
* @param {shaka.extern.Stream} audioStream
* @param {shaka.extern.Stream} textStream
* @return {boolean}
* @private
*/
shouldInitiallyShowText_(audioStream, textStream) {
const AutoShowText = shaka.config.AutoShowText;

if (this.config_.autoShowText == AutoShowText.NEVER) {
return false;
}
if (this.config_.autoShowText == AutoShowText.ALWAYS) {
return true;
}

const LanguageUtils = shaka.util.LanguageUtils;

/** @type {string} */
const preferredTextLocale =
LanguageUtils.normalize(this.config_.preferredTextLanguage);
/** @type {string} */
const audioLocale = LanguageUtils.normalize(audioStream.language);
/** @type {string} */
const textLocale = LanguageUtils.normalize(textStream.language);

return (
LanguageUtils.areLanguageCompatible(textLocale, preferredTextLocale) &&
!LanguageUtils.areLanguageCompatible(audioLocale, textLocale));
if (this.config_.autoShowText == AutoShowText.IF_PREFERRED_TEXT_LANGUAGE) {
// Only the text language match matters.
return LanguageUtils.areLanguageCompatible(
textLocale,
preferredTextLocale);
}

if (this.config_.autoShowText == AutoShowText.IF_SUBTITLES_MAY_BE_NEEDED) {
/* The text should automatically be shown if the text is
* language-compatible with the user's text language preference, but not
* compatible with the audio. These are cases where we deduce that
* subtitles may be needed.
*
* For example:
* preferred | chosen | chosen |
* text | text | audio | show
* -----------------------------------
* en-CA | en | jp | true
* en | en-US | fr | true
* fr-CA | en-US | jp | false
* en-CA | en-US | en-US | false
*
*/
/** @type {string} */
const audioLocale = LanguageUtils.normalize(audioStream.language);

return (
LanguageUtils.areLanguageCompatible(textLocale, preferredTextLocale) &&
!LanguageUtils.areLanguageCompatible(audioLocale, textLocale));
}

shaka.log.alwaysWarn('Invalid autoShowText setting!');
return false;
}

/**
Expand Down Expand Up @@ -6561,7 +6586,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
}
};


/**
* In order to know what method of loading the player used for some content, we
* have this enum. It lets us know if content has not been loaded, loaded with
Expand Down
4 changes: 4 additions & 0 deletions lib/util/player_configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ goog.provide('shaka.util.PlayerConfiguration');

goog.require('goog.asserts');
goog.require('shaka.abr.SimpleAbrManager');
goog.require('shaka.config.AutoShowText');
goog.require('shaka.log');
goog.require('shaka.net.NetworkingEngine');
goog.require('shaka.util.ConfigUtils');
Expand Down Expand Up @@ -256,6 +257,8 @@ shaka.util.PlayerConfiguration = class {
useHeaders: false,
};

const AutoShowText = shaka.config.AutoShowText;

/** @type {shaka.extern.PlayerConfiguration} */
const config = {
drm: drm,
Expand All @@ -264,6 +267,7 @@ shaka.util.PlayerConfiguration = class {
offline: offline,
abrFactory: () => new shaka.abr.SimpleAbrManager(),
abr: abr,
autoShowText: AutoShowText.IF_SUBTITLES_MAY_BE_NEEDED,
preferredAudioLanguage: '',
preferredTextLanguage: '',
preferredVariantRole: '',
Expand Down
Loading

0 comments on commit 5c24410

Please sign in to comment.