Enable AudioContext and proxy for all users, not just extension users
- Set crossorigin="anonymous" as a static HTML attribute on audio/video elements so all users can use createMediaElementSource (required for Web Audio API) - Remove window.__tidalOriginExtension guards from AudioContext init/changeSource: binaural DSP, EQ, M/S processing, and audio graph now active for everyone - Route direct (non-DASH) stream URLs through getProxyUrl in player.js so non-extension users get CORS headers from the proxy for lossless/MP4 audio - Proxy preloader src as well so browser cache warms with the proxied URL - Add idempotency guard in getProxyUrl to prevent double-proxying when Shaka retries segment requests (proxied URL still contains "tidal.com" in params) - Extension users: still bypass proxy and get CDN URLs directly (unchanged) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9138ec5289
commit
7b8a6e6cab
4 changed files with 41 additions and 54 deletions
10
index.html
10
index.html
|
|
@ -115,14 +115,8 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
<audio id="audio-player" style="display: none"></audio>
|
||||
<video id="video-player" style="display: none"></video>
|
||||
<script>
|
||||
if (window.__tidalOriginExtension) {
|
||||
document.getElementById('audio-player').crossOrigin = 'anonymous';
|
||||
document.getElementById('video-player').crossOrigin = 'anonymous';
|
||||
}
|
||||
</script>
|
||||
<audio id="audio-player" crossorigin="anonymous" style="display: none"></audio>
|
||||
<video id="video-player" crossorigin="anonymous" style="display: none"></video>
|
||||
<div id="context-menu">
|
||||
<ul>
|
||||
<li data-action="shuffle-play-card" data-type-filter="album,playlist,mix,user-playlist">
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ class AudioContextManager {
|
|||
|
||||
this.audio = audioElement;
|
||||
|
||||
if (isIos && !window.__tidalOriginExtension) {
|
||||
if (isIos) {
|
||||
console.log('[AudioContext] Skipping Web Audio initialization on iOS for lock screen compatibility');
|
||||
return;
|
||||
}
|
||||
|
|
@ -490,24 +490,22 @@ class AudioContextManager {
|
|||
this.audioContext = new AudioContext();
|
||||
}
|
||||
|
||||
if (window.__tidalOriginExtension) {
|
||||
if (!this.sources.has(audioElement)) {
|
||||
const src = this.audioContext.createMediaElementSource(audioElement);
|
||||
this.sources.set(audioElement, src);
|
||||
}
|
||||
this.source = this.sources.get(audioElement);
|
||||
|
||||
try {
|
||||
this.audioContext.destination.channelCount = Math.min(this.audioContext.destination.maxChannelCount, 8);
|
||||
this.audioContext.destination.channelCountMode = 'explicit';
|
||||
this.audioContext.destination.channelInterpretation = 'discrete';
|
||||
} catch {
|
||||
// Some browsers may not support changing destination channel count
|
||||
}
|
||||
|
||||
this.binauralDsp = new BinauralDSP(this.audioContext);
|
||||
void this._loadBinauralSettings();
|
||||
if (!this.sources.has(audioElement)) {
|
||||
const src = this.audioContext.createMediaElementSource(audioElement);
|
||||
this.sources.set(audioElement, src);
|
||||
}
|
||||
this.source = this.sources.get(audioElement);
|
||||
|
||||
try {
|
||||
this.audioContext.destination.channelCount = Math.min(this.audioContext.destination.maxChannelCount, 8);
|
||||
this.audioContext.destination.channelCountMode = 'explicit';
|
||||
this.audioContext.destination.channelInterpretation = 'discrete';
|
||||
} catch {
|
||||
// Some browsers may not support changing destination channel count
|
||||
}
|
||||
|
||||
this.binauralDsp = new BinauralDSP(this.audioContext);
|
||||
void this._loadBinauralSettings();
|
||||
|
||||
this.analyser = this.audioContext.createAnalyser();
|
||||
this.analyser.fftSize = 1024;
|
||||
|
|
@ -528,16 +526,14 @@ class AudioContextManager {
|
|||
|
||||
this.monoMergerNode = this.audioContext.createChannelMerger(2);
|
||||
|
||||
if (window.__tidalOriginExtension) {
|
||||
this._connectGraph();
|
||||
}
|
||||
this._connectGraph();
|
||||
|
||||
// Auto-recover from unexpected suspensions (e.g. background throttling)
|
||||
this.audioContext.addEventListener('statechange', () => {
|
||||
if (this.audioContext.state === 'interrupted' || this.audioContext.state === 'suspended') {
|
||||
console.log(`[AudioContext] State changed to ${this.audioContext.state}, attempting resume`);
|
||||
setTimeout(() => {
|
||||
if (this.audioContext && this.audioContext.state !== 'running' && (window.__tidalOriginExtension ? this.source : true)) {
|
||||
if (this.audioContext && this.audioContext.state !== 'running') {
|
||||
this.audioContext.resume().catch((e) => {
|
||||
console.warn('[AudioContext] Auto-resume failed:', e);
|
||||
});
|
||||
|
|
@ -559,31 +555,27 @@ class AudioContextManager {
|
|||
}
|
||||
if (this.audio === audioElement) return;
|
||||
|
||||
if (window.__tidalOriginExtension) {
|
||||
try {
|
||||
if (this.source) {
|
||||
try {
|
||||
this.source.disconnect();
|
||||
} catch {
|
||||
// node may already be disconnected
|
||||
}
|
||||
try {
|
||||
if (this.source) {
|
||||
try {
|
||||
this.source.disconnect();
|
||||
} catch {
|
||||
// node may already be disconnected
|
||||
}
|
||||
|
||||
this.audio = audioElement;
|
||||
|
||||
if (!this.sources.has(audioElement)) {
|
||||
this.sources.set(audioElement, this.audioContext.createMediaElementSource(audioElement));
|
||||
}
|
||||
this.source = this.sources.get(audioElement);
|
||||
|
||||
if (this.isInitialized) {
|
||||
this._connectGraph();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('changeSource failed:', e);
|
||||
}
|
||||
} else {
|
||||
|
||||
this.audio = audioElement;
|
||||
|
||||
if (!this.sources.has(audioElement)) {
|
||||
this.sources.set(audioElement, this.audioContext.createMediaElementSource(audioElement));
|
||||
}
|
||||
this.source = this.sources.get(audioElement);
|
||||
|
||||
if (this.isInitialized) {
|
||||
this._connectGraph();
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('changeSource failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -663,7 +663,7 @@ export class Player {
|
|||
const preloader = new Audio();
|
||||
preloader.preload = 'auto';
|
||||
preloader.muted = true;
|
||||
preloader.src = streamUrl;
|
||||
preloader.src = getProxyUrl(streamUrl);
|
||||
streamInfo.preloader = preloader; // Hold reference
|
||||
}
|
||||
}
|
||||
|
|
@ -1282,7 +1282,7 @@ export class Player {
|
|||
} catch {}
|
||||
this.shakaInitialized = false;
|
||||
}
|
||||
activeElement.src = streamUrl;
|
||||
activeElement.src = getProxyUrl(streamUrl);
|
||||
this.applyAudioEffects();
|
||||
this.updateAdaptiveQualityBadge();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
export const getProxyUrl = (url) => {
|
||||
if (window.__tidalOriginExtension) return url;
|
||||
if (url.startsWith('https://audio-proxy.binimum.org/')) return url;
|
||||
return `https://audio-proxy.binimum.org/proxy-audio?url=${url}`;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue