diff --git a/script.js b/script.js index a66a2e8..9eeba7e 100644 --- a/script.js +++ b/script.js @@ -2085,7 +2085,7 @@ function initListenerMode() { // Create a hidden audio element to handle the MediaSource const audio = new Audio(); - audio.autoplay = true; + audio.autoplay = false; // Don't autoplay - we use the Enable Audio button audio.hidden = true; document.body.appendChild(audio); @@ -2118,9 +2118,24 @@ function initListenerMode() { } sourceBuffer.addEventListener('updateend', () => { + // Process next chunk in queue if (audioQueue.length > 0 && !sourceBuffer.updating) { sourceBuffer.appendBuffer(audioQueue.shift()); } + + // Periodic cleanup of old buffer data to prevent memory bloat + // Keep the last 60 seconds of audio data + if (audio.buffered.length > 0 && !sourceBuffer.updating && mediaSource.readyState === 'open') { + const end = audio.buffered.end(audio.buffered.length - 1); + const start = audio.buffered.start(0); + if (end - start > 120) { // If buffer is > 2 mins + try { + sourceBuffer.remove(0, end - 60); + } catch (e) { + console.warn('Buffer cleanup skipped:', e.message); + } + } + } }); } catch (e) { console.error('❌ Failed to add SourceBuffer:', e); @@ -2141,6 +2156,7 @@ function initListenerMode() { // Store audio element and context for later activation window.listenerAudio = audio; window.listenerMediaSource = mediaSource; + window.listenerAudioEnabled = false; // Track if user has enabled audio // Initialize socket and join initSocket(); @@ -2166,16 +2182,6 @@ function initListenerMode() { const next = audioQueue.shift(); sourceBuffer.appendBuffer(next); - // Periodic cleanup of old buffer data to prevent memory bloat - // Keep the last 60 seconds of audio data - if (audio.buffered.length > 0 && !sourceBuffer.updating) { - const end = audio.buffered.end(audio.buffered.length - 1); - const start = audio.buffered.start(0); - if (end - start > 120) { // If buffer is > 2 mins - sourceBuffer.remove(0, end - 60); - } - } - // Reset error counter on success if (window.sourceBufferErrorCount) window.sourceBufferErrorCount = 0; } catch (e) { @@ -2197,9 +2203,9 @@ function initListenerMode() { } } - // UI Update + // UI Update (only if audio is already enabled, don't overwrite the enable prompt) const now = Date.now(); - if (now - lastStatusUpdate > 1000) { + if (now - lastStatusUpdate > 1000 && window.listenerAudioEnabled) { const statusEl = document.getElementById('connection-status'); if (statusEl) { statusEl.textContent = `🟢 Connected - ${chunksReceived} chunks (${audioQueue.length} buffered)`; @@ -2230,11 +2236,15 @@ function initListenerMode() { socket.on('connect', () => { const statusEl = document.getElementById('connection-status'); - if (statusEl) statusEl.textContent = '🟢 Connected'; + // Only update if audio is enabled, otherwise keep the "Click Enable Audio" message + if (statusEl && window.listenerAudioEnabled) { + statusEl.textContent = '🟢 Connected'; + } }); socket.on('disconnect', () => { const statusEl = document.getElementById('connection-status'); + // Always show disconnect status as it's critical if (statusEl) statusEl.textContent = '🔴 Disconnected'; }); } @@ -2261,15 +2271,49 @@ async function enableListenerAudio() { console.log('✅ Audio context resumed'); } - // 3. Kickstart the hidden audio element + // 3. Wait for buffered data before attempting playback if (window.listenerAudio) { // Unmute just in case window.listenerAudio.muted = false; window.listenerAudio.volume = settings.volume || 0.8; + // Check if we have buffered data + const hasBufferedData = () => { + return window.listenerAudio.buffered && window.listenerAudio.buffered.length > 0; + }; + + if (!hasBufferedData()) { + console.log('⏳ Waiting for audio data to buffer...'); + if (audioText) audioText.textContent = 'WAITING FOR STREAM...'; + + // Wait up to 5 seconds for data to arrive + const waitForData = new Promise((resolve, reject) => { + let attempts = 0; + const maxAttempts = 50; // 5 seconds (50 * 100ms) + + const checkInterval = setInterval(() => { + attempts++; + + if (hasBufferedData()) { + clearInterval(checkInterval); + console.log('✅ Audio data buffered, ready to play'); + resolve(); + } else if (attempts >= maxAttempts) { + clearInterval(checkInterval); + reject(new Error('Timeout waiting for audio data')); + } + }, 100); + }); + + await waitForData; + } + // Attempt playback await window.listenerAudio.play(); console.log('✅ Audio playback started successfully'); + + // Mark audio as enabled so status updates can now display + window.listenerAudioEnabled = true; } // 4. Hide the button and update status @@ -2293,7 +2337,9 @@ async function enableListenerAudio() { if (audioText) audioText.textContent = 'RETRY ENABLE'; if (stashedStatus) { - stashedStatus.textContent = '⚠️ Browser blocked audio. Please click again.'; + stashedStatus.textContent = '⚠️ ' + (error.message === 'Timeout waiting for audio data' + ? 'No stream data yet. Is the DJ broadcasting?' + : 'Browser blocked audio. Please click again.'); } } } diff --git a/youtube_cookies.txt b/youtube_cookies.txt deleted file mode 100644 index 79e1134..0000000 --- a/youtube_cookies.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Netscape HTTP Cookie File -# This file is generated by yt-dlp. Do not edit. - -.youtube.com TRUE / TRUE 1801589734 LOGIN_INFO AFmmF2swRAIgHdagSv3AtixYxCW7IHLf47R0KcQaW8NADbzvMuNuy3gCIDXXOJZWFSfAZ1jxxCUVVFuFyf1xoS3OhZtjQRiRGtaD:QUQ3MjNmeERNNlZib3lnSWN5ZkVWMWllUVpYNmNhMFROXzd3YWl2TnVMdHIyTlU2ZE92Z2R4aEJDZDRWb0RVZ01XMXUwSGlueTZYRU0zV1RNRXdJdzdhQmU1MlMwN1NaeXd0S2RBbUNQMU1UbVpuRmNqeC1Nekgxb01zajZCdnBZTkpPNVpOV3J3RDZ1QVNyNGpud3lCRTZjSUhpeVpwNFBn -.youtube.com TRUE / FALSE 1801593439 SID g.a0005AjCJ-US8_6a2mKBHcNy8J5xGdIRFU5-3J24Rh__ueKgYF87AJIWypIb2Ik6XVFT5EqrnwACgYKATgSARcSFQHGX2MiGk_57qzeI-IPJkM8tmm03xoVAUF8yKpSfHahHvTEK-ia_rVzU4Yi0076 -.youtube.com TRUE / TRUE 1801593439 __Secure-1PSID g.a0005AjCJ-US8_6a2mKBHcNy8J5xGdIRFU5-3J24Rh__ueKgYF87qT1WAfdS7sFekPiWVXKIfAACgYKAUMSARcSFQHGX2MiuiQpTAzra30LEmDxkHp2-RoVAUF8yKpWWOikkri1UB3MugOGq6e_0076 -.youtube.com TRUE / TRUE 1801593439 __Secure-3PSID g.a0005AjCJ-US8_6a2mKBHcNy8J5xGdIRFU5-3J24Rh__ueKgYF87tL2jiqzMehdfEubeYBuVTQACgYKAYUSARcSFQHGX2MiLLWEo22MP59Bv_AQnTvuIhoVAUF8yKo2FXEl9xZI7eV_iJwo3c9t0076 -.youtube.com TRUE / FALSE 1801593439 HSID AB0zrN4IKxe-HrA0n -.youtube.com TRUE / TRUE 1801593439 SSID Ab6kKLl9bmrQL_Hni -.youtube.com TRUE / FALSE 1801593439 APISID 22L8tjFyV2jsGKge/AZ2PhPO3ivukTdkWs -.youtube.com TRUE / TRUE 1801593439 SAPISID trR-s5Kb4rJZa0jz/AMQf8wrRhlN1gozvu -.youtube.com TRUE / TRUE 1801593439 __Secure-1PAPISID trR-s5Kb4rJZa0jz/AMQf8wrRhlN1gozvu -.youtube.com TRUE / TRUE 1801593439 __Secure-3PAPISID trR-s5Kb4rJZa0jz/AMQf8wrRhlN1gozvu -.youtube.com TRUE / FALSE 0 PREF f6=80&repeat=NONE&tz=UTC&hl=en -.youtube.com TRUE / TRUE 1801508383 __Secure-YENID 12.YTE=S5qLwonI5Vef0tWqM9BVf_no2FGqTz8wCQjAEW6w_bCkldGIesWCVwHjY7lM6hILbuvAm-SQkWeGzqXn42Lz12xLJSRy8ew3DZjHDIsihRhcJx1mdRMlEBrUFZh0kguQ_VAyva8GIrM_3szB4UBUh5EYpiuJcnTFieCEA7vsvEOygkM2bVO-aDcvDCo2KkjcorJ0rFrozxvjNG1gIdgRZb-_eCqLmrHRPrSaBMqSjIQVCYr0UURNAt7jnY4u_ngRfd4gedGFAAigASCRq64Hg0PoA3jlZrRVq-ZTFXrXnAdKDoCJ4NQM_k29X8DLLGPNTtrAzxKn7_u7PeWbeHWfKg -.youtube.com TRUE / TRUE 1801508384 __Secure-YEC CgtfZncxejAtTU92ZyjJruDKBjInCgJFUxIhEh0SGwsMDg8QERITFBUWFxgZGhscHR4fICEiIyQlJiAVYuACCt0CMTIuWVRFPVM1cUx3b25JNVZlZjB0V3FNOUJWZl9ubzJGR3FUejh3Q1FqQUVXNndfYkNrbGRHSWVzV0NWd0hqWTdsTTZoSUxidXZBbS1TUWtXZUd6cVhuNDJMejEyeExKU1J5OGV3M0RaakhESXNpaFJoY0p4MW1kUk1sRUJyVUZaaDBrZ3VRX1ZBeXZhOEdJck1fM3N6QjRVQlVoNUVZcGl1SmNuVEZpZUNFQTd2c3ZFT3lna00yYlZPLWFEY3ZEQ28yS2tqY29ySjByRnJvenh2ak5HMWdJZGdSWmItX2VDcUxtckhSUHJTYUJNcVNqSVFWQ1lyMFVVUk5BdDdqblk0dV9uZ1JmZDRnZWRHRkFBaWdBU0NScTY0SGcwUG9BM2psWnJSVnEtWlRGWHJYbkFkS0RvQ0o0TlFNX2syOVg4RExMR1BOVHRyQXp4S243X3U3UGVXYmVIV2ZLZw%3D%3D -.youtube.com TRUE / TRUE 1798916391 __Secure-1PSIDTS sidts-CjQBflaCdeAx2SdtKMD9zUQdw365y09bcjcMAEVt7wunyzZ8vOXra2-sNlYpujrgrSAB4Oi4EAA -.youtube.com TRUE / TRUE 1798916391 __Secure-3PSIDTS sidts-CjQBflaCdeAx2SdtKMD9zUQdw365y09bcjcMAEVt7wunyzZ8vOXra2-sNlYpujrgrSAB4Oi4EAA -.youtube.com TRUE / FALSE 1798916809 SIDCC AKEyXzXV3xIB5WrVkJilMKV2wq5se8ySH9nuVzyMGS1n32jUeRk4DlqdxAUye7CFMbOYvnuCNA -.youtube.com TRUE / TRUE 1798916809 __Secure-1PSIDCC AKEyXzUqPSmDU8y0QdEdwdIXdKqwnLgAhdkYJPvfudfujzh-JsXcj61JSiUbYmuaxQDVi9COJQ -.youtube.com TRUE / TRUE 1798916809 __Secure-3PSIDCC AKEyXzWBfqFbiZ36NLiL0rulHLMnJZUo5BiDTKTXTkSWCUq15QRHigVH3ZZK9gghuCUVnqfZKw -.youtube.com TRUE / TRUE 1767381013 CONSISTENCY APeVyi9ugkVMpG4vJpUcbJphFq3pD5vJDWaAdsKzDA5ewHpf3ooaflF7egA5RflAGECOzj2iLWP_rYEjQo86XJgjJmh9rD0AUqm6RY1w3FqyfXz7wQ0glrBVgLqqAlmsCb6LVxECHmznH21ZZq88PVQ9m6xdY_IWj6a47_ISRqGIOtOuPztFCXy1bYh78qR8RWJ6DnEPGyI5l8cB0W3O_Q2o11gU35e7MY-ycVMjnt0zq48T -.youtube.com TRUE / TRUE 1782911361 __Secure-ROLLOUT_TOKEN COHd58SY0cK-vgEQqK6mtKvjkQMYi7Ss1_bskQM%3D -.youtube.com TRUE / TRUE 0 YSC Z10UFLfjCRM -.youtube.com TRUE / TRUE 1801508809 VISITOR_PRIVACY_METADATA CgJFUxIhEh0SGwsMDg8QERITFBUWFxgZGhscHR4fICEiIyQlJiAV