This commit is contained in:
Mid 2025-06-17 22:10:19 +03:00
parent 079fd61390
commit e929b5af1e
3 changed files with 51 additions and 48 deletions

View File

@ -18,6 +18,8 @@
var AudCtx var AudCtx
var AudScript, AudWorklet var AudScript, AudWorklet
var AudHz var AudHz
var AudDejitter
var AudMuted = true
function create_audio(hz, channels) { function create_audio(hz, channels) {
if(AudCtx) { if(AudCtx) {
@ -28,6 +30,9 @@
AudHz = hz AudHz = hz
// Fill up buffer for 1 second before playing
AudDejitter = AudHz
var DebugSine = 0 var DebugSine = 0
AudCtx = new AudioContext({sampleRate: hz}) AudCtx = new AudioContext({sampleRate: hz})
@ -52,8 +57,10 @@
while(AudioQueue.length && leftToWrite) { while(AudioQueue.length && leftToWrite) {
var amount = Math.min(leftToWrite, AudioQueue[0].left.length) var amount = Math.min(leftToWrite, AudioQueue[0].left.length)
if(!AudMuted) {
outL.set(AudioQueue[0].left.subarray(0, amount), offset) outL.set(AudioQueue[0].left.subarray(0, amount), offset)
if(outR) outR.set(AudioQueue[0].right.subarray(0, amount), offset) if(outR) outR.set(AudioQueue[0].right.subarray(0, amount), offset)
}
AudioQueue[0].left = AudioQueue[0].left.subarray(amount) AudioQueue[0].left = AudioQueue[0].left.subarray(amount)
if(outR) AudioQueue[0].right = AudioQueue[0].right.subarray(amount) if(outR) AudioQueue[0].right = AudioQueue[0].right.subarray(amount)
@ -77,11 +84,16 @@
interruptcontrols() interruptcontrols()
function togglemute() { function togglemute() {
if(AudCtx) if(!AudCtx) {
if(document.querySelector(".MKVSpeakerOn").style.display == "none") { return;
}
AudCtx.resume() AudCtx.resume()
} else {
AudCtx.suspend() AudMuted = !AudMuted
if(AudWorklet) {
AudWorklet.port.postMessage(AudMuted)
} }
document.querySelectorAll(".MKVSpeaker *").forEach(function(el) { el.style.display = el.style.display == "none" ? "" : "none" }) document.querySelectorAll(".MKVSpeaker *").forEach(function(el) { el.style.display = el.style.display == "none" ? "" : "none" })
@ -127,23 +139,11 @@
} else if(e.data.samples) { } else if(e.data.samples) {
AudioQueue.push({left: e.data.left, right: e.data.right || e.data.left}) AudioQueue.push({left: e.data.left, right: e.data.right || e.data.left})
// Audio may be loaded but it might not play because of autoplay permissions // Prevent the audio queue filling up and causing ever-increasing AV desync
// In this case the audio queue will fill up and cause ever-increasing AV desync if(AudCtx.state != "running") {
if(AudCtx && AudCtx.state != "running") {
var durationInAudioQueue = AudioQueue.length ? AudioQueue.reduce((acc, el) => acc + el.left.length, 0) : 0 var durationInAudioQueue = AudioQueue.length ? AudioQueue.reduce((acc, el) => acc + el.left.length, 0) : 0
//if(AudWorklet) {
// // With audio worklets, crop to 1024 samples max to prevent ring buffer overflow
//
// crop_audio_queue(Math.max(durationInAudioQueue - 1024, 0))
//} else {
// // Without audio worklets we use a FIFO and can crop to the duration in the video queue
//
var durationToRemove = Math.max(durationInAudioQueue - (VideoQueue.length ? (VideoQueue[VideoQueue.length - 1].t - VideoQueue[0].t) : 0) * AudHz / 1000, 0) var durationToRemove = Math.max(durationInAudioQueue - (VideoQueue.length ? (VideoQueue[VideoQueue.length - 1].t - VideoQueue[0].t) : 0) * AudHz / 1000, 0)
//
crop_audio_queue(durationToRemove) crop_audio_queue(durationToRemove)
//}
} }
} }
@ -165,10 +165,6 @@
} }
} }
Canvus.onclick = function() {
if(AudCtx) AudCtx.resume()
}
var VideoBufferingOffset = 0 var VideoBufferingOffset = 0
function toHex(buffer) { function toHex(buffer) {
@ -337,7 +333,7 @@
this.currentClusterTime = EBMLParser.vi_to_i(data) this.currentClusterTime = EBMLParser.vi_to_i(data)
if(!RenderStartTime) { if(!RenderStartTime) {
RenderStartTime = document.timeline.currentTime + 1000 RenderStartTime = document.timeline.currentTime + 600
} }
if(!VideoStartTime) { if(!VideoStartTime) {
VideoStartTime = this.currentClusterTime VideoStartTime = this.currentClusterTime
@ -444,11 +440,16 @@
function render(timestamp) { function render(timestamp) {
document.querySelector(".MKVControls").style.opacity = Math.max(0, Math.min(1, 5 - (timestamp - LastControlsInterrupt) / 1000)) document.querySelector(".MKVControls").style.opacity = Math.max(0, Math.min(1, 5 - (timestamp - LastControlsInterrupt) / 1000))
var nextImg = null
while(RenderStartTime && VideoQueue.length && VideoQueue[0].t + VideoBufferingOffset <= (timestamp - RenderStartTime)) { while(RenderStartTime && VideoQueue.length && VideoQueue[0].t + VideoBufferingOffset <= (timestamp - RenderStartTime)) {
CanvCtx.putImageData(VideoQueue[0].imgData, 0, 0) nextImg = VideoQueue[0].imgData
VideoQueue.shift() VideoQueue.shift()
} }
if(nextImg) {
CanvCtx.putImageData(nextImg, 0, 0)
}
requestAnimationFrame(render) requestAnimationFrame(render)
} }
requestAnimationFrame(render) requestAnimationFrame(render)

View File

@ -122,19 +122,13 @@
<script> <script>
document.querySelector("#BLARF").setAttribute("data-target", STREAM_SOURCE_WS) document.querySelector("#BLARF").setAttribute("data-target", STREAM_SOURCE_WS)
function randomHex(size) {
return [...self.crypto.getRandomValues(new Uint8Array(size))].map(b=>b.toString(16).padStart(2, "0")).join("")
}
const un = 'lol' + randomHex(16)
if(ENABLE_CHAT) { if(ENABLE_CHAT) {
converse.initialize({ converse.initialize({
view_mode: 'embedded', view_mode: 'embedded',
websocket_url: CHAT_HOST_WS_URL, websocket_url: CHAT_HOST_WS_URL,
login: 'anonymous', authentication: 'anonymous',
jid: un + '@' + CHAT_HOST, jid: CHAT_HOST,
auto_login: true, auto_login: true,
password: 'lol',
auto_join_rooms: [CHAT_MUC], auto_join_rooms: [CHAT_MUC],
show_message_avatar: false, show_message_avatar: false,
show_controlbox_by_default: false, show_controlbox_by_default: false,

View File

@ -14,12 +14,18 @@ class RawPCMWorklet extends AudioWorkletProcessor {
this.ringR = new Float32Array(65536) this.ringR = new Float32Array(65536)
this.ringWrite = 0 this.ringWrite = 0
this.ringRead = 0 this.ringRead = 0
this.mute = true
for(var z = 0; z < 65536; z++) { for(var z = 0; z < 65536; z++) {
this.ringL[z] = Math.sin(z / 128 * 2 * Math.PI) * 0.3 this.ringL[z] = Math.sin(z / 128 * 2 * Math.PI) * 0.3
} }
this.port.onmessage = (event) => { this.port.onmessage = (event) => {
if(event.data === true || event.data === false) {
this.mute = event.data
return
}
var newaudioframes = event.data var newaudioframes = event.data
var newlen = newaudioframes.left.length var newlen = newaudioframes.left.length
@ -60,6 +66,7 @@ class RawPCMWorklet extends AudioWorkletProcessor {
var available = Math.min(left.length, Math.max(0, this.ringWrite - this.ringRead)) var available = Math.min(left.length, Math.max(0, this.ringWrite - this.ringRead))
if(this.mute === false) {
if(this.ringRead % this.ringL.length + available <= this.ringL.length) { if(this.ringRead % this.ringL.length + available <= this.ringL.length) {
left.set(this.ringL.slice(this.ringRead % this.ringL.length, this.ringRead % this.ringL.length + available)) left.set(this.ringL.slice(this.ringRead % this.ringL.length, this.ringRead % this.ringL.length + available))
right.set(this.ringR.slice(this.ringRead % this.ringL.length, this.ringRead % this.ringL.length + available)) right.set(this.ringR.slice(this.ringRead % this.ringL.length, this.ringRead % this.ringL.length + available))
@ -72,6 +79,7 @@ class RawPCMWorklet extends AudioWorkletProcessor {
left.set(this.ringL.slice(0, available - boundary), boundary) left.set(this.ringL.slice(0, available - boundary), boundary)
right.set(this.ringR.slice(0, available - boundary), boundary) right.set(this.ringR.slice(0, available - boundary), boundary)
} }
}
this.ringRead += left.length this.ringRead += left.length