77 lines
1.7 KiB
TypeScript
77 lines
1.7 KiB
TypeScript
import { SoundGroupNode, SoundGroupNodeOptions } from "./SoundGroupNode";
|
|
|
|
export interface TabSourceNodeOptions extends SoundGroupNodeOptions {
|
|
}
|
|
|
|
export class TabSourceNode extends SoundGroupNode<TabSourceNodeOptions> {
|
|
|
|
public readonly type = 'tabSource';
|
|
|
|
private stream?: MediaStream;
|
|
private source?: MediaStreamAudioSourceNode;
|
|
|
|
|
|
play() {
|
|
if (!this.isPlaying) {
|
|
this.setup()
|
|
this.ctx.audioContext.resume();
|
|
}
|
|
}
|
|
|
|
private async setup() {
|
|
try {
|
|
this.stream = await navigator.mediaDevices.getDisplayMedia({
|
|
video: {
|
|
displaySurface: "browser",
|
|
frameRate: {ideal: 1}
|
|
},
|
|
audio: {
|
|
// @ts-ignore
|
|
suppressLocalAudioPlayback: false,
|
|
echoCancellation: false,
|
|
noiseSuppression: false,
|
|
sampleRate: 44100,
|
|
},
|
|
preferCurrentTab: false,
|
|
selfBrowserSurface: "exclude",
|
|
systemAudio: "exclude",
|
|
surfaceSwitching: "include",
|
|
monitorTypeSurfaces: "include",
|
|
});
|
|
console.log(this.stream);
|
|
this.source = this.ctx.audioContext.createMediaStreamSource(this.stream);
|
|
this.source.connect(this.gainNode);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
|
|
stop() {
|
|
this.stream?.getTracks().forEach(track => {
|
|
track.stop();
|
|
});
|
|
this.source?.disconnect();
|
|
this.source = undefined;
|
|
this.stream = undefined;
|
|
}
|
|
|
|
get isPlaying(): boolean {
|
|
return !!(this.stream && this.source);
|
|
}
|
|
|
|
togglePlay(): void {
|
|
if (this.isPlaying) {
|
|
this.stop();
|
|
} else {
|
|
this.play();
|
|
}
|
|
}
|
|
|
|
serializeOptions() {
|
|
return {
|
|
...super.serializeOptions(),
|
|
type: this.type,
|
|
} as const;
|
|
}
|
|
|
|
} |