diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/client/local_user.ts | 58 | ||||
-rw-r--r-- | source/client/logger.ts | 8 | ||||
-rw-r--r-- | source/client/remote_user.ts | 8 | ||||
-rw-r--r-- | source/client/rnnoise.ts | 15 |
4 files changed, 58 insertions, 31 deletions
diff --git a/source/client/local_user.ts b/source/client/local_user.ts index 78652b3..7f2327e 100644 --- a/source/client/local_user.ts +++ b/source/client/local_user.ts @@ -1,7 +1,7 @@ -import { parameter_bool, parameter_string } from "./helper"; +import { parameter_bool, parameter_number, parameter_string } from "./helper"; import { log } from "./logger"; import { RemoteUser } from "./remote_user"; -import { rnnoise_track } from "./rnnoise"; +import { get_rnnoise_node } from "./rnnoise"; import { Room } from "./room"; import { User } from "./user"; @@ -10,8 +10,12 @@ export class LocalUser extends User { private audio_track?: MediaStreamTrack private video_track?: MediaStreamTrack + private audio_disable_cleanup?: () => void - controls?: { audio: HTMLElement, video: HTMLElement } + mic_gain?: GainNode + default_gain: number = parameter_number("mic_gain", 1) + + controls?: { audio: HTMLElement, video: HTMLElement, mute: HTMLElement } constructor(room: Room, name: string) { super(room, name) @@ -25,10 +29,15 @@ export class LocalUser extends User { create_controls() { const audio_toggle = document.createElement("input") const video_toggle = document.createElement("input") - audio_toggle.type = video_toggle.type = "button" + const mute_toggle = document.createElement("input") + audio_toggle.type = video_toggle.type = mute_toggle.type = "button" audio_toggle.value = "Audio" video_toggle.value = "Video" - let audio = false, video = false + mute_toggle.value = "Mute" + let audio = parameter_bool("audio_enabled", false), + video = parameter_bool("video_enabled", false), + mute = parameter_bool("video_enabled", false) + audio_toggle.addEventListener("click", () => { audio = !audio @@ -40,11 +49,17 @@ export class LocalUser extends User { if (video) this.enable_video() else this.disable_video() }) + mute_toggle.addEventListener("click", () => { + mute = !mute + this.mic_gain?.gain?.setValueAtTime(mute ? 0 : this.default_gain, 0) + if (mute) this.controls?.mute.classList.add("enabled") + else this.controls?.mute.classList.remove("enabled") + }) const el = document.createElement("div") el.classList.add("local-controls") - el.append(audio_toggle, video_toggle) - this.controls = { video: video_toggle, audio: audio_toggle } + el.append(audio_toggle, video_toggle, mute_toggle) + this.controls = { video: video_toggle, audio: audio_toggle, mute: mute_toggle } document.body.append(el) } @@ -86,17 +101,38 @@ export class LocalUser extends User { } : true; const user_media = await window.navigator.mediaDevices.getUserMedia({ audio: audio_contraints }) - let t = user_media.getAudioTracks()[0] + const context = new AudioContext() + const source = context.createMediaStreamSource(user_media) + const destination = context.createMediaStreamDestination() + const gain = context.createGain() + gain.gain.value = this.default_gain + this.mic_gain = gain + let rnnoise: RNNoiseNode; if (use_rnnoise) { - t = await rnnoise_track(t) + rnnoise = await get_rnnoise_node(context) + source.connect(rnnoise) + rnnoise.connect(gain) + } else { + source.connect(gain) } + gain.connect(destination) + this.audio_disable_cleanup = () => { + source.disconnect() + if (rnnoise) rnnoise.disconnect() + gain.disconnect() + destination.disconnect() + this.mic_gain = undefined + } + + const t = destination.stream.getAudioTracks()[0] this.audio_track = t this.room.remote_users.forEach(u => u.peer.addTrack(t)) this.stream.addTrack(t) this.update_view_w() } + async disable_video() { if (!this.video_track) return this.room.remote_users.forEach(u => { @@ -110,6 +146,7 @@ export class LocalUser extends User { } async disable_audio() { if (!this.audio_track) return + if (this.audio_disable_cleanup) this.audio_disable_cleanup() this.room.remote_users.forEach(u => { u.peer.getSenders().forEach(s => { if (s.track == this.audio_track) u.peer.removeTrack(s) @@ -119,5 +156,4 @@ export class LocalUser extends User { this.update_view_w() this.audio_track = undefined } - -}
\ No newline at end of file +} diff --git a/source/client/logger.ts b/source/client/logger.ts index 9960c70..637f5c0 100644 --- a/source/client/logger.ts +++ b/source/client/logger.ts @@ -2,10 +2,10 @@ export type LogTag = "webrtc" | "ws" | "media" | "*" | "misc" const log_tag_color: { [key in LogTag]: string } = { "*": "#FF0000", - webrtc: "#990099", - media: "#999900", - ws: "#009999", - misc: "#000099", + webrtc: "#FF00FF", + media: "#FFFF00", + ws: "#00FFFF", + misc: "#2222FF", } // TODO maybe log time aswell diff --git a/source/client/remote_user.ts b/source/client/remote_user.ts index 8318e0b..3cb4867 100644 --- a/source/client/remote_user.ts +++ b/source/client/remote_user.ts @@ -35,12 +35,12 @@ export class RemoteUser extends User { const offer_description = await this.peer.createOffer() await this.peer.setLocalDescription(offer_description) const offer = { type: offer_description.type, sdp: offer_description.sdp } - log("webrtc", "sent offer", offer) + log("webrtc", "sent offer", { a: offer }) this.room.websocket_send({ receiver: this.name, offer }) } async on_offer(offer: RTCSessionDescriptionInit) { this.negotiation_busy = true - log("webrtc", "got offer", offer) + log("webrtc", "got offer", { a: offer }) const offer_description = new RTCSessionDescription(offer) await this.peer.setRemoteDescription(offer_description) this.answer() @@ -49,12 +49,12 @@ export class RemoteUser extends User { const answer_description = await this.peer.createAnswer() await this.peer.setLocalDescription(answer_description) const answer = { type: answer_description.type, sdp: answer_description.sdp } - log("webrtc", "sent answer", answer) + log("webrtc", "sent answer", { a: answer }) this.room.websocket_send({ receiver: this.name, answer }) this.negotiation_busy = false } async on_answer(answer: RTCSessionDescriptionInit) { - log("webrtc", "got answer", answer) + log("webrtc", "got answer", { a: answer }) const answer_description = new RTCSessionDescription(answer) await this.peer.setRemoteDescription(answer_description) this.negotiation_busy = false diff --git a/source/client/rnnoise.ts b/source/client/rnnoise.ts index 6017288..c9014ef 100644 --- a/source/client/rnnoise.ts +++ b/source/client/rnnoise.ts @@ -11,12 +11,11 @@ declare global { // TODO fix leak -export async function rnnoise_track(track: MediaStreamTrack): Promise<MediaStreamTrack> { +export async function get_rnnoise_node(context: AudioContext): Promise<RNNoiseNode> { log("misc", "rnnoise enabled") - const context = new AudioContext() //@ts-ignore let RNNoiseNode: typeof RNNoiseNode = window.RNNoiseNode; - + let script: HTMLScriptElement; if (!RNNoiseNode) { log("misc", "loading rnnoise...") @@ -32,13 +31,5 @@ export async function rnnoise_track(track: MediaStreamTrack): Promise<MediaStrea } await RNNoiseNode.register(context) - const source_stream = new MediaStream() - source_stream.addTrack(track) - const source = context.createMediaStreamSource(source_stream) - const destination = context.createMediaStreamDestination() - const rnnoise = new RNNoiseNode(context) - source.connect(rnnoise) - rnnoise.connect(destination) - - return destination.stream.getAudioTracks()[0] + return new RNNoiseNode(context) }
\ No newline at end of file |