From 02dd79f03fac03aadfd6ebf18c3bd572a9add1e1 Mon Sep 17 00:00:00 2001 From: Marcin Bachry Date: Tue, 29 Apr 2025 12:40:18 +0200 Subject: [PATCH] Fix battery drain from Web Audio (#29203) * Fix battery drain from Web Audio * move suspend away from constructor * await on resume() * Delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- src/audio/BackgroundAudio.ts | 6 ++++++ src/audio/compat.ts | 9 +++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/audio/BackgroundAudio.ts b/src/audio/BackgroundAudio.ts index c90016eef9..eda10c0904 100644 --- a/src/audio/BackgroundAudio.ts +++ b/src/audio/BackgroundAudio.ts @@ -48,6 +48,12 @@ export class BackgroundAudio { source.buffer = this.sounds[url]; source.loop = loop; source.connect(this.audioContext.destination); + + await this.audioContext.resume(); + source.onended = () => { + this.audioContext.suspend(); + }; + source.start(); return source; } diff --git a/src/audio/compat.ts b/src/audio/compat.ts index 7af6ef68b2..0c972e9b73 100644 --- a/src/audio/compat.ts +++ b/src/audio/compat.ts @@ -15,16 +15,21 @@ import { logger } from "matrix-js-sdk/src/logger"; import { SAMPLE_RATE } from "./VoiceRecording"; export function createAudioContext(opts?: AudioContextOptions): AudioContext { + let ctx: AudioContext; if (window.AudioContext) { - return new AudioContext(opts); + ctx = new AudioContext(opts); } else if (window.webkitAudioContext) { // While the linter is correct that "a constructor name should not start with // a lowercase letter", it's also wrong to think that we have control over this. // eslint-disable-next-line new-cap - return new window.webkitAudioContext(opts); + ctx = new window.webkitAudioContext(opts); } else { throw new Error("Unsupported browser"); } + // Initialize in suspended state, as Firefox starts using + // CPU/battery right away, even if we don't play any sound yet. + void ctx.suspend(); + return ctx; } export function decodeOgg(audioBuffer: ArrayBuffer): Promise {