Skip to content

Commit

Permalink
feat(ui): Add quality selection UI for audio-only content
Browse files Browse the repository at this point in the history
For audio-only content, in the UI, the resolution button becomes a quality button where users can select their desired audioBandwidth.

Issue: shaka-project#2071
  • Loading branch information
nbcl committed Apr 23, 2021
1 parent 568321c commit dcdcfd6
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 33 deletions.
1 change: 1 addition & 0 deletions ui/locales/en-GB.json
Expand Up @@ -26,6 +26,7 @@
"PICTURE_IN_PICTURE": "Picture-in-picture",
"PLAY": "Play",
"PLAYBACK_RATE": "Playback speed",
"QUALITY": "Quality",
"RESOLUTION": "Resolution",
"REWIND": "Rewind",
"SEEK": "Seek",
Expand Down
1 change: 1 addition & 0 deletions ui/locales/en.json
Expand Up @@ -27,6 +27,7 @@
"PICTURE_IN_PICTURE": "Picture-in-Picture",
"PLAY": "Play",
"PLAYBACK_RATE": "Playback speed",
"QUALITY": "Quality",
"RESOLUTION": "Resolution",
"REWIND": "Rewind",
"SEEK": "Seek",
Expand Down
5 changes: 5 additions & 0 deletions ui/locales/source.json
Expand Up @@ -113,6 +113,11 @@
"message": "Playback speed",
"description": "Label for a button used to navigate to a submenu to choose the playback speed in the video player."
},
"QUALITY": {
"description": "Label for a button used to open a submenu to choose a audio quality in the video player.",
"meaning": "Audio quality",
"message": "Quality"
},
"RESOLUTION": {
"description": "Label for a button used to open a submenu to choose a video resolution in the video player.",
"meaning": "Visual quality",
Expand Down
88 changes: 55 additions & 33 deletions ui/resolution_selection.js
Expand Up @@ -60,9 +60,6 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
});

this.updateResolutionSelection_();

// Set up all the strings in the user's preferred language.
this.updateLocalizedStrings_();
}


Expand All @@ -71,27 +68,8 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
/** @type {!Array.<shaka.extern.Track>} */
let tracks = this.player.getVariantTracks();

// Hide resolution menu and button for audio-only content and src= content
// without resolution information.
// TODO: for audio-only content, this should be a bitrate selection menu
// instead.
if (tracks.length && !tracks[0].height) {
shaka.ui.Utils.setDisplay(this.menu, false);
shaka.ui.Utils.setDisplay(this.button, false);
return;
}
// Otherwise, restore it.
shaka.ui.Utils.setDisplay(this.button, true);

tracks.sort((t1, t2) => {
// We have already screened for audio-only content, but the compiler
// doesn't know that.
goog.asserts.assert(t1.height != null, 'Null height');
goog.asserts.assert(t2.height != null, 'Null height');

return t2.height - t1.height;
});

// If there is a selected variant track, then we filter out any tracks in
// a different language. Then we use those remaining tracks to display the
// available resolutions.
Expand All @@ -103,14 +81,38 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
track.channelsCount == selectedTrack.channelsCount);
}

// Remove duplicate entries with the same height. This can happen if
// we have multiple resolutions of audio. Pick an arbitrary one.
// Remove duplicate entries with the same resolution or quality depending.
// on content type. Pick an arbitrary one.
tracks = tracks.filter((track, idx) => {
// Keep the first one with the same height.
const otherIdx = tracks.findIndex((t) => t.height == track.height);
let otherIdx;
if (this.player.isAudioOnly()) {
// Keep the first one with the same bandwidth.
otherIdx = tracks.findIndex(
(t) => t.audioBandwidth == track.audioBandwidth);
} else {
// Keep the first one with the same height.
otherIdx = tracks.findIndex((t) => t.height == track.height);
}
return otherIdx == idx;
});

// Sort the tracks in height or bandwith depending on content type.
if (this.player.isAudioOnly()) {
tracks.sort((t1, t2) => {
goog.asserts.assert(t1.audioBandwidth != null, 'Null audioBandwidth');
goog.asserts.assert(t2.audioBandwidth != null, 'Null audioBandwidth');

return t2.audioBandwidth - t1.audioBandwidth;
});
} else {
tracks.sort((t1, t2) => {
goog.asserts.assert(t1.height != null, 'Null height');
goog.asserts.assert(t2.height != null, 'Null height');

return t2.height - t1.height;
});
}

// Remove old shaka-resolutions
// 1. Save the back to menu button
const backButton = shaka.ui.Utils.getFirstDescendantWithClassName(
Expand All @@ -132,7 +134,13 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
() => this.onTrackSelected_(track));

const span = shaka.util.Dom.createHTMLElement('span');
span.textContent = track.height + 'p';

// Asign textContent depending on content type.
if (this.player.isAudioOnly()) {
span.textContent = track.audioBandwidth + ' bits/s';
} else {
span.textContent = track.height + 'p';
}
button.appendChild(span);

if (!abrEnabled && track == selectedTrack) {
Expand Down Expand Up @@ -176,6 +184,8 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
shaka.ui.Utils.focusOnTheChosenItem(this.menu);
this.controls.dispatchEvent(
new shaka.util.FakeEvent('resolutionselectionupdated'));

this.updateLocalizedStrings_();
}


Expand All @@ -198,14 +208,26 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
updateLocalizedStrings_() {
const LocIds = shaka.ui.Locales.Ids;

this.button.setAttribute(shaka.ui.Constants.ARIA_LABEL,
this.localization.resolve(LocIds.RESOLUTION));
this.backButton.setAttribute(shaka.ui.Constants.ARIA_LABEL,
this.localization.resolve(LocIds.RESOLUTION));
this.backSpan.textContent =
// Assign text attributes depending on content type.
if (this.player.isAudioOnly()) {
this.button.setAttribute(shaka.ui.Constants.ARIA_LABEL,
this.localization.resolve(LocIds.QUALITY));
this.backButton.setAttribute(shaka.ui.Constants.ARIA_LABEL,
this.localization.resolve(LocIds.QUALITY));
this.backSpan.textContent =
this.localization.resolve(LocIds.QUALITY);
this.nameSpan.textContent =
this.localization.resolve(LocIds.QUALITY);
} else {
this.button.setAttribute(shaka.ui.Constants.ARIA_LABEL,
this.localization.resolve(LocIds.RESOLUTION));
this.backButton.setAttribute(shaka.ui.Constants.ARIA_LABEL,
this.localization.resolve(LocIds.RESOLUTION));
this.backSpan.textContent =
this.localization.resolve(LocIds.RESOLUTION);
this.nameSpan.textContent =
this.nameSpan.textContent =
this.localization.resolve(LocIds.RESOLUTION);
}
this.abrOnSpan_.textContent =
this.localization.resolve(LocIds.AUTO_QUALITY);

Expand Down

0 comments on commit dcdcfd6

Please sign in to comment.