From 37aac3c2381ea7c1c9803c675d5a87f3c4e0a887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandrina=20Patr=C3=B3n?= Date: Fri, 11 Feb 2022 13:15:20 -0500 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20Use=20GainNode=20API=20?= =?UTF-8?q?to=20update=20video=20volume.=20(#37491)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use GainNode API to set video volume. * Handle cross-browser differences when creating audio context. --- extensions/amp-story/1.0/media-pool.js | 38 +++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/extensions/amp-story/1.0/media-pool.js b/extensions/amp-story/1.0/media-pool.js index 7bba5200b78c..934fd4e62b8f 100644 --- a/extensions/amp-story/1.0/media-pool.js +++ b/extensions/amp-story/1.0/media-pool.js @@ -161,6 +161,18 @@ export class MediaPool { */ this.sources_ = {}; + /** + * The audio context. + * @private {?AudioContext} + */ + this.audioContext_ = null; + + /** + * Maps a media element's ID to its audio source. + * @private @const {!Object} + */ + this.audioSources_ = {}; + /** * Maps a media element's ID to the element. This is necessary, as elements * are kept in memory when they are swapped out of the DOM. @@ -854,9 +866,9 @@ export class MediaPool { return Promise.resolve(); } - // When a video is muted, reset its volume to the default value of 1. - if (mediaType == MediaType.VIDEO) { - domMediaEl.volume = 1; + const audioSource = this.audioSources_[domMediaEl.id]; + if (audioSource) { + audioSource.disconnect(); } return this.enqueueMediaElementTask_(poolMediaEl, new MuteTask()); @@ -884,7 +896,25 @@ export class MediaPool { if (ampVideoEl) { const volume = ampVideoEl.getAttribute('volume'); if (volume) { - domMediaEl.volume = parseFloat(volume); + // Handle cross-browser differences (see https://googlechrome.github.io/samples/webaudio-method-chaining/). + if (typeof AudioContext === 'function') { + this.audioContext_ = this.audioContext_ || new AudioContext(); + } else if (typeof webkitAudioContext === 'function') { + this.audioContext_ = + this.audioContext_ || new global.webkitAudioContext(); + } + + if (this.audioContext_) { + const audioSource = + this.audioSources_[domMediaEl.id] || + this.audioContext_.createMediaElementSource(domMediaEl); + this.audioSources_[domMediaEl.id] = audioSource; + const gainNode = this.audioContext_.createGain(); + gainNode.gain.value = parseFloat(volume); + audioSource + .connect(gainNode) + .connect(this.audioContext_.destination); + } } } }