Tweak voice broadcast chunk decoding (#9713)
This commit is contained in:
parent
8ced72dba6
commit
254815cbcf
2 changed files with 39 additions and 27 deletions
|
@ -143,13 +143,14 @@ export class VoiceBroadcastPlayback
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!event.getId() && !event.getTxnId()) {
|
||||||
|
// skip events without id and txn id
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this.chunkEvents.addEvent(event);
|
this.chunkEvents.addEvent(event);
|
||||||
this.setDuration(this.chunkEvents.getLength());
|
this.setDuration(this.chunkEvents.getLength());
|
||||||
|
|
||||||
if (this.getState() !== VoiceBroadcastPlaybackState.Stopped) {
|
|
||||||
await this.enqueueChunk(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.getState() === VoiceBroadcastPlaybackState.Buffering) {
|
if (this.getState() === VoiceBroadcastPlaybackState.Buffering) {
|
||||||
await this.start();
|
await this.start();
|
||||||
this.updateLiveness();
|
this.updateLiveness();
|
||||||
|
@ -183,18 +184,7 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private async enqueueChunks(): Promise<void> {
|
private async loadPlayback(chunkEvent: MatrixEvent): Promise<void> {
|
||||||
const promises = this.chunkEvents.getEvents().reduce((promises, event: MatrixEvent) => {
|
|
||||||
if (!this.playbacks.has(event.getId() || "")) {
|
|
||||||
promises.push(this.enqueueChunk(event));
|
|
||||||
}
|
|
||||||
return promises;
|
|
||||||
}, [] as Promise<void>[]);
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async enqueueChunk(chunkEvent: MatrixEvent): Promise<void> {
|
|
||||||
const eventId = chunkEvent.getId();
|
const eventId = chunkEvent.getId();
|
||||||
|
|
||||||
if (!eventId) {
|
if (!eventId) {
|
||||||
|
@ -215,6 +205,14 @@ export class VoiceBroadcastPlayback
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unloadPlayback(event: MatrixEvent): void {
|
||||||
|
const playback = this.playbacks.get(event.getId()!);
|
||||||
|
if (!playback) return;
|
||||||
|
|
||||||
|
playback.destroy();
|
||||||
|
this.playbacks.delete(event.getId()!);
|
||||||
|
}
|
||||||
|
|
||||||
private onPlaybackPositionUpdate = (
|
private onPlaybackPositionUpdate = (
|
||||||
event: MatrixEvent,
|
event: MatrixEvent,
|
||||||
position: number,
|
position: number,
|
||||||
|
@ -261,6 +259,7 @@ export class VoiceBroadcastPlayback
|
||||||
if (newState !== PlaybackState.Stopped) return;
|
if (newState !== PlaybackState.Stopped) return;
|
||||||
|
|
||||||
await this.playNext();
|
await this.playNext();
|
||||||
|
this.unloadPlayback(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
private async playNext(): Promise<void> {
|
private async playNext(): Promise<void> {
|
||||||
|
@ -283,10 +282,11 @@ export class VoiceBroadcastPlayback
|
||||||
private async playEvent(event: MatrixEvent): Promise<void> {
|
private async playEvent(event: MatrixEvent): Promise<void> {
|
||||||
this.setState(VoiceBroadcastPlaybackState.Playing);
|
this.setState(VoiceBroadcastPlaybackState.Playing);
|
||||||
this.currentlyPlaying = event;
|
this.currentlyPlaying = event;
|
||||||
await this.getPlaybackForEvent(event)?.play();
|
const playback = await this.getOrLoadPlaybackForEvent(event);
|
||||||
|
playback?.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPlaybackForEvent(event: MatrixEvent): Playback | undefined {
|
private async getOrLoadPlaybackForEvent(event: MatrixEvent): Promise<Playback | undefined> {
|
||||||
const eventId = event.getId();
|
const eventId = event.getId();
|
||||||
|
|
||||||
if (!eventId) {
|
if (!eventId) {
|
||||||
|
@ -294,6 +294,10 @@ export class VoiceBroadcastPlayback
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.playbacks.has(eventId)) {
|
||||||
|
await this.loadPlayback(event);
|
||||||
|
}
|
||||||
|
|
||||||
const playback = this.playbacks.get(eventId);
|
const playback = this.playbacks.get(eventId);
|
||||||
|
|
||||||
if (!playback) {
|
if (!playback) {
|
||||||
|
@ -301,9 +305,18 @@ export class VoiceBroadcastPlayback
|
||||||
logger.warn("unable to find playback for event", event);
|
logger.warn("unable to find playback for event", event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to load the playback for the next event for a smooth(er) playback
|
||||||
|
const nextEvent = this.chunkEvents.getNext(event);
|
||||||
|
if (nextEvent) this.loadPlayback(nextEvent);
|
||||||
|
|
||||||
return playback;
|
return playback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getCurrentPlayback(): Playback | undefined {
|
||||||
|
if (!this.currentlyPlaying) return;
|
||||||
|
return this.playbacks.get(this.currentlyPlaying.getId()!);
|
||||||
|
}
|
||||||
|
|
||||||
public getLiveness(): VoiceBroadcastLiveness {
|
public getLiveness(): VoiceBroadcastLiveness {
|
||||||
return this.liveness;
|
return this.liveness;
|
||||||
}
|
}
|
||||||
|
@ -365,11 +378,8 @@ export class VoiceBroadcastPlayback
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentPlayback = this.currentlyPlaying
|
const currentPlayback = this.getCurrentPlayback();
|
||||||
? this.getPlaybackForEvent(this.currentlyPlaying)
|
const skipToPlayback = await this.getOrLoadPlaybackForEvent(event);
|
||||||
: null;
|
|
||||||
|
|
||||||
const skipToPlayback = this.getPlaybackForEvent(event);
|
|
||||||
|
|
||||||
if (!skipToPlayback) {
|
if (!skipToPlayback) {
|
||||||
logger.warn("voice broadcast chunk to skip to not found", event);
|
logger.warn("voice broadcast chunk to skip to not found", event);
|
||||||
|
@ -396,14 +406,13 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
|
|
||||||
public async start(): Promise<void> {
|
public async start(): Promise<void> {
|
||||||
await this.enqueueChunks();
|
|
||||||
const chunkEvents = this.chunkEvents.getEvents();
|
const chunkEvents = this.chunkEvents.getEvents();
|
||||||
|
|
||||||
const toPlay = this.getInfoState() === VoiceBroadcastInfoState.Stopped
|
const toPlay = this.getInfoState() === VoiceBroadcastInfoState.Stopped
|
||||||
? chunkEvents[0] // start at the beginning for an ended voice broadcast
|
? chunkEvents[0] // start at the beginning for an ended voice broadcast
|
||||||
: chunkEvents[chunkEvents.length - 1]; // start at the current chunk for an ongoing voice broadcast
|
: chunkEvents[chunkEvents.length - 1]; // start at the current chunk for an ongoing voice broadcast
|
||||||
|
|
||||||
if (this.playbacks.has(toPlay?.getId() || "")) {
|
if (toPlay) {
|
||||||
return this.playEvent(toPlay);
|
return this.playEvent(toPlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +431,7 @@ export class VoiceBroadcastPlayback
|
||||||
|
|
||||||
this.setState(VoiceBroadcastPlaybackState.Paused);
|
this.setState(VoiceBroadcastPlaybackState.Paused);
|
||||||
if (!this.currentlyPlaying) return;
|
if (!this.currentlyPlaying) return;
|
||||||
this.getPlaybackForEvent(this.currentlyPlaying)?.pause();
|
this.getCurrentPlayback()?.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
public resume(): void {
|
public resume(): void {
|
||||||
|
@ -433,7 +442,7 @@ export class VoiceBroadcastPlayback
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(VoiceBroadcastPlaybackState.Playing);
|
this.setState(VoiceBroadcastPlaybackState.Playing);
|
||||||
this.getPlaybackForEvent(this.currentlyPlaying)?.play();
|
this.getCurrentPlayback()?.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -387,6 +387,9 @@ describe("VoiceBroadcastPlayback", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should play until the end", () => {
|
it("should play until the end", () => {
|
||||||
|
// assert first chunk was unloaded
|
||||||
|
expect(chunk1Playback.destroy).toHaveBeenCalled();
|
||||||
|
|
||||||
// assert that the second chunk is being played
|
// assert that the second chunk is being played
|
||||||
expect(chunk2Playback.play).toHaveBeenCalled();
|
expect(chunk2Playback.play).toHaveBeenCalled();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue