Skip to content

Commit

Permalink
Fix audio track selection (#5697)
Browse files Browse the repository at this point in the history
  • Loading branch information
absidue authored Sep 15, 2024
1 parent bedae6c commit ad320ac
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ScreenshotButton } from './player-components/ScreenshotButton'
import { StatsButton } from './player-components/StatsButton'
import { TheatreModeButton } from './player-components/TheatreModeButton'
import {
findMostSimilarAudioBandwidth,
getSponsorBlockSegments,
logShakaError,
qualityLabelToDimension,
Expand Down Expand Up @@ -135,7 +136,6 @@ export default defineComponent({
const hasLoaded = ref(false)

const hasMultipleAudioTracks = ref(false)
let hasMultipleAudioChannelCounts = false
const isLive = ref(false)

const useOverFlowMenu = ref(false)
Expand Down Expand Up @@ -1182,11 +1182,15 @@ export default defineComponent({

/**
* @param {number} quality
* @param {number | undefined} audioBandwidth
* @param {string | undefined} label
*/
function setDashQuality(quality) {
function setDashQuality(quality, audioBandwidth, label) {
let variants = player.getVariantTracks()

if (hasMultipleAudioTracks.value) {
if (label) {
variants = variants.filter(variant => variant.label === label)
} else if (hasMultipleAudioTracks.value) {
// default audio track
variants = variants.filter(variant => variant.audioRoles.includes('main'))
}
Expand All @@ -1204,9 +1208,21 @@ export default defineComponent({
}

matches.sort((a, b) => isPortrait ? b.width - a.width : b.height - a.height)
variants = matches

player.selectVariantTrack(variants[0])
let chosenVariant

if (typeof audioBandwidth === 'number') {
const width = matches[0].width
const height = matches[0].height

matches = matches.filter(variant => variant.width === width && variant.height === height)

chosenVariant = findMostSimilarAudioBandwidth(matches, audioBandwidth)
} else {
chosenVariant = matches[0]
}

player.selectVariantTrack(chosenVariant)
}

/**
Expand Down Expand Up @@ -1247,7 +1263,6 @@ export default defineComponent({
}

hasMultipleAudioTracks.value = false
hasMultipleAudioChannelCounts = false

events.dispatchEvent(new CustomEvent('setLegacyFormat', {
detail: {
Expand Down Expand Up @@ -2316,7 +2331,6 @@ export default defineComponent({
}

hasMultipleAudioTracks.value = player.getAudioLanguagesAndRoles().length > 1
hasMultipleAudioChannelCounts = new Set(player.getVariantTracks().map(track => track.channelsCount)).size > 1

if (props.format === 'dash') {
const firstVariant = player.getVariantTracks()[0]
Expand Down Expand Up @@ -2509,7 +2523,7 @@ export default defineComponent({

const wasPaused = video_.paused

const useAutoQuality = oldFormat === 'legacy' ? defaultQuality.value === 'auto' : player.getConfiguration().abr.enabled
let useAutoQuality = oldFormat === 'legacy' ? defaultQuality.value === 'auto' : player.getConfiguration().abr.enabled

if (!wasPaused) {
video_.pause()
Expand All @@ -2530,8 +2544,8 @@ export default defineComponent({
}

if (newFormat === 'audio' || newFormat === 'dash') {
/** @type {{language: string, role: string, channelsCount: number}|undefined} */
let audioTrack
let label
let audioBandwidth
let dimension

if (oldFormat === 'legacy' && newFormat === 'dash') {
Expand All @@ -2540,31 +2554,58 @@ export default defineComponent({
if (!useAutoQuality) {
dimension = qualityLabelToDimension(legacyFormat.qualityLabel)
}
} else if (oldFormat !== 'legacy' && (hasMultipleAudioTracks.value || hasMultipleAudioChannelCounts)) {
} else if (oldFormat !== 'legacy') {
const track = player.getVariantTracks().find(track => track.active)

audioTrack = {
language: track.language,
role: track.audioRoles[0],
channelsCount: track.channelsCount
if (typeof track.audioBandwidth === 'number') {
audioBandwidth = track.audioBandwidth
}

if (track.label) {
label = track.label
}
}

if (oldFormat === 'audio' && newFormat === 'dash' && !useAutoQuality && defaultQuality.value !== 'auto') {
dimension = defaultQuality.value
if (oldFormat === 'audio' && newFormat === 'dash' && !useAutoQuality) {
if (defaultQuality.value !== 'auto') {
dimension = defaultQuality.value
} else {
// Use auto as we don't know what resolution to pick
useAutoQuality = true
}
}

player.configure(getPlayerConfig(newFormat, useAutoQuality))

try {
await player.load(props.manifestSrc, playbackPosition, props.manifestMimeType)

if (dimension) {
setDashQuality(dimension)
}
if (useAutoQuality) {
if (label) {
player.selectVariantsByLabel(label)
}
} else {
if (dimension) {
setDashQuality(dimension, audioBandwidth, label)
} else {
let variants = player.getVariantTracks()

if (label) {
variants = variants.filter(variant => variant.label === label)
}

if (audioTrack) {
player.selectAudioLanguage(audioTrack.language, audioTrack.role, audioTrack.channelsCount)
let chosenVariant

if (typeof audioBandwidth === 'number') {
chosenVariant = findMostSimilarAudioBandwidth(variants, audioBandwidth)
} else {
chosenVariant = variants.reduce((previous, current) => {
return previous === null || current.bandwidth > previous.bandwidth ? current : previous
}, null)
}

player.selectVariantTrack(chosenVariant)
}
}
} catch (error) {
handleError(error, 'loading dash/audio manifest for format switch', `${oldFormat} -> ${newFormat}`)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import shaka from 'shaka-player'

import i18n from '../../../i18n/index'
import { findMostSimilarAudioBandwidth } from '../../../helpers/player/utils'

export class AudioTrackSelection extends shaka.ui.SettingsMenu {
/**
Expand Down Expand Up @@ -30,7 +31,6 @@ export class AudioTrackSelection extends shaka.ui.SettingsMenu {
this.updateAudioTracks_()
})

// selectVariantsByLabel doesn't trigger variant changed
this.eventManager.listen(this.player, 'adaptation', () => {
this.updateAudioTracks_()
})
Expand All @@ -40,9 +40,14 @@ export class AudioTrackSelection extends shaka.ui.SettingsMenu {
this.updateAudioTracks_()
}

/** @private */
updateAudioTracks_() {
const tracks = this.player.getVariantTracks()
/**
* @private
* @param {shaka.extern.TrackList=} tracks
*/
updateAudioTracks_(tracks) {
if (!tracks) {
tracks = this.player.getVariantTracks()
}

const selectedTrack = tracks.find(track => track.active)

Expand All @@ -68,7 +73,7 @@ export class AudioTrackSelection extends shaka.ui.SettingsMenu {

const button = document.createElement('button')
button.addEventListener('click', () => {
this.onAudioTrackSelected_(track)
this.onAudioTrackSelected_(track.label)
})

const span = document.createElement('span')
Expand Down Expand Up @@ -116,11 +121,31 @@ export class AudioTrackSelection extends shaka.ui.SettingsMenu {
}

/**
* @param {shaka.extern.Track} track
* @param {string} label
* @private
*/
onAudioTrackSelected_(track) {
this.player.selectVariantsByLabel(track.label)
onAudioTrackSelected_(label) {
if (this.player.getConfiguration().abr.enabled) {
this.player.selectVariantsByLabel(label)
} else {
const variants = this.player.getVariantTracks()
const previousVariant = variants.find(variant => variant.active)

let matchingVariants = variants.filter(variant => variant.label === label)

if (!this.player.isAudioOnly()) {
matchingVariants = matchingVariants.filter(variant => {
return variant.width === previousVariant.width &&
variant.height === previousVariant.height &&
variant.frameRate === previousVariant.frameRate &&
variant.hdr === previousVariant.hdr
})
}

const closestVariant = findMostSimilarAudioBandwidth(matchingVariants, previousVariant.audioBandwidth)

this.player.selectVariantTrack(closestVariant, true)
}
}

/** @private */
Expand Down
20 changes: 20 additions & 0 deletions src/renderer/helpers/player/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,23 @@ export function repairInvidiousManifest(periods) {
}
}
}

/**
* @param {shaka.extern.TrackList} variants
* @param {number} bandwidthToMatch
*/
export function findMostSimilarAudioBandwidth(variants, bandwidthToMatch) {
let closestAudioBandwithDifference = Infinity
let closestVariant

for (const variant of variants) {
const difference = Math.abs(variant.audioBandwidth - bandwidthToMatch)

if (difference < closestAudioBandwithDifference) {
closestAudioBandwithDifference = difference
closestVariant = variant
}
}

return closestVariant
}

0 comments on commit ad320ac

Please sign in to comment.