Skip to content

Commit bc88b62

Browse files
committed
fix: lag issues on Windows
This commit fixes lag issues on Windows by using a anti-drift internal.
1 parent 0a3b558 commit bc88b62

File tree

1 file changed

+39
-30
lines changed

1 file changed

+39
-30
lines changed

index.js

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,15 @@ class Connection extends EventEmitter {
5555

5656
this.player = {
5757
sequence: 0,
58-
timestamp: 0
58+
timestamp: 0,
59+
nextPacket: 0
5960
}
6061

6162
this.nonce = 0
6263
this.nonceBuffer = Buffer.alloc(24)
64+
this.packetBuffer = Buffer.allocUnsafe(12)
6365

64-
this.playInterval = null
66+
this.playTimeout = null
6567
this.audioStream = null
6668
}
6769

@@ -306,15 +308,15 @@ class Connection extends EventEmitter {
306308
this.ws.on('error', (error) => this.emit('error', error))
307309
}
308310

309-
sendAudioChunk(packetBuffer, chunk) {
310-
packetBuffer.writeUInt8(0x80, 0)
311-
packetBuffer.writeUInt8(0x78, 1)
311+
sendAudioChunk(chunk) {
312+
this.packetBuffer.writeUInt8(0x80, 0)
313+
this.packetBuffer.writeUInt8(0x78, 1)
312314

313-
packetBuffer.writeUInt16BE(this.player.sequence, 2, 2)
314-
packetBuffer.writeUInt32BE(this.player.timestamp, 4, 4)
315-
packetBuffer.writeUInt32BE(this.udpInfo.ssrc, 8, 4)
315+
this.packetBuffer.writeUInt16BE(this.player.sequence, 2, 2)
316+
this.packetBuffer.writeUInt32BE(this.player.timestamp, 4, 4)
317+
this.packetBuffer.writeUInt32BE(this.udpInfo.ssrc, 8, 4)
316318

317-
packetBuffer.copy(nonce, 0, 0, 12)
319+
this.packetBuffer.copy(nonce, 0, 0, 12)
318320

319321
this.player.timestamp += TIMESTAMP_INCREMENT
320322
if (this.player.timestamp >= MAX_TIMESTAMP) this.player.timestamp = 0
@@ -327,15 +329,15 @@ class Connection extends EventEmitter {
327329
case 'xsalsa20_poly1305': {
328330
const output = Sodium.close(chunk, nonce, this.udpInfo.secretKey)
329331

330-
packet = Buffer.concat([ packetBuffer, output ])
332+
packet = Buffer.concat([ this.packetBuffer, output ])
331333

332334
break
333335
}
334336
case 'xsalsa20_poly1305_suffix': {
335337
const random = Sodium.random(24, this.nonceBuffer)
336338
const output = Sodium.close(chunk, random, this.udpInfo.secretKey)
337339

338-
packet = Buffer.concat([ packetBuffer, output, random ])
340+
packet = Buffer.concat([ this.packetBuffer, output, random ])
339341

340342
break
341343
}
@@ -346,7 +348,7 @@ class Connection extends EventEmitter {
346348

347349
const output = Sodium.close(chunk, this.nonceBuffer, this.udpInfo.secretKey)
348350

349-
packet = Buffer.concat([ packetBuffer, output, this.nonceBuffer.subarray(0, 4) ])
351+
packet = Buffer.concat([ this.packetBuffer, output, this.nonceBuffer.subarray(0, 4) ])
350352

351353
break
352354
}
@@ -368,7 +370,7 @@ class Connection extends EventEmitter {
368370
}
369371

370372
audioStream.once('readable', () => {
371-
if (this.audioStream && this.playInterval) {
373+
if (this.audioStream && this.playTimeout) {
372374
this.statistics = {
373375
packetsSent: 0,
374376
packetsLost: 0,
@@ -390,8 +392,8 @@ class Connection extends EventEmitter {
390392
}
391393

392394
stop(reason) {
393-
clearInterval(this.playInterval)
394-
this.playInterval = null
395+
clearTimeout(this.playTimeout)
396+
this.playTimeout = null
395397

396398
this.audioStream.destroy()
397399
this.audioStream.removeListener('finishBuffering', this._markAsStoppable)
@@ -414,28 +416,34 @@ class Connection extends EventEmitter {
414416
this._updatePlayerState({ status: 'idle', reason: reason ?? 'paused' })
415417

416418
this._setSpeaking(0)
417-
clearInterval(this.playInterval)
419+
clearTimeout(this.playTimeout)
418420
}
419421

420422
_markAsStoppable() {
421423
this.audioStream.canStop = true
422424
}
423425

424-
unpause(reason) {
425-
this._updatePlayerState({ status: 'playing', reason: reason ?? 'unpaused' })
426+
_packetInterval() {
427+
this.playTimeout = setTimeout(() => {
428+
const chunk = this.audioStream.read(OPUS_FRAME_SIZE)
426429

427-
this._setSpeaking(1 << 0)
430+
if (!chunk && this.audioStream.canStop) return this.stop('finished')
428431

429-
const packetBuffer = Buffer.allocUnsafe(12)
432+
if (chunk) this.sendAudioChunk(chunk)
433+
434+
this.player.nextPacket += OPUS_FRAME_DURATION
435+
this._packetInterval()
436+
}, this.player.nextPacket - Date.now())
437+
}
430438

431-
this.playInterval = setInterval(() => {
432-
const chunk = this.audioStream.read(OPUS_FRAME_SIZE)
439+
unpause(reason) {
440+
this._updatePlayerState({ status: 'playing', reason: reason ?? 'unpaused' })
433441

434-
if (!chunk && this.audioStream.canStop) return this.stop('finished')
435-
436-
if (chunk) this.sendAudioChunk(packetBuffer, chunk)
437-
}, OPUS_FRAME_DURATION)
442+
this._setSpeaking(1 << 0)
438443

444+
this.player.nextPacket = Date.now() + OPUS_FRAME_DURATION
445+
this._packetInterval()
446+
439447
this.audioStream.once('finishBuffering', () => this._markAsStoppable())
440448
}
441449

@@ -445,14 +453,15 @@ class Connection extends EventEmitter {
445453
this.hbInterval = null
446454
}
447455

448-
if (this.playInterval) {
449-
clearInterval(this.playInterval)
450-
this.playInterval = null
456+
if (this.playTimeout) {
457+
clearTimeout(this.playTimeout)
458+
this.playTimeout = null
451459
}
452460

453461
this.player = {
454462
sequence: 0,
455-
timestamp: 0
463+
timestamp: 0,
464+
nextPacket: 0
456465
}
457466

458467
if (this.ws && !this.ws.closing) {

0 commit comments

Comments
 (0)