aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/client/helper.ts29
-rw-r--r--source/client/local_user.ts45
-rw-r--r--source/client/logger.ts5
-rw-r--r--source/client/rnnoise.ts45
-rw-r--r--source/client/room.ts4
5 files changed, 117 insertions, 11 deletions
diff --git a/source/client/helper.ts b/source/client/helper.ts
index 19c4f46..9fb4052 100644
--- a/source/client/helper.ts
+++ b/source/client/helper.ts
@@ -1,3 +1,5 @@
+import { parameters } from "."
+
export function get_query_params(): { [key: string]: string } {
const q: { [key: string]: string } = {}
for (const kv of window.location.search.substr(1).split("&")) {
@@ -12,3 +14,30 @@ export function hex_id(len: number = 8): string {
return Math.floor(Math.random() * 16 ** len).toString(16).padStart(len, "0")
}
+
+export function parameter_bool(name: string, def: boolean): boolean {
+ const v = parameters[name]
+ if (!v) return def
+ if (v == "0" || v == "false" || v == "no") return false
+ if (v == "1" || v == "true" || v == "yes") return true
+ alert(`parameter ${name} is invalid`)
+ return def
+}
+
+export function parameter_number(name: string, def: number): number {
+ const v = parameters[name]
+ if (!v) return def
+ const n = parseFloat(v)
+ if (Number.isNaN(n)) {
+ alert(`parameter ${name} is invalid`)
+ return def
+ }
+ return n
+}
+
+export function parameter_string(name: string, def: string): string {
+ const v = parameters[name]
+ if (!v) return def
+ return v
+}
+
diff --git a/source/client/local_user.ts b/source/client/local_user.ts
index 3fe6216..cda9b53 100644
--- a/source/client/local_user.ts
+++ b/source/client/local_user.ts
@@ -1,5 +1,7 @@
+import { parameter_bool, parameter_string } from "./helper";
import { log } from "./logger";
import { RemoteUser } from "./remote_user";
+import { rnnoise_track } from "./rnnoise";
import { Room } from "./room";
import { User } from "./user";
@@ -9,12 +11,14 @@ export class LocalUser extends User {
private audio_track?: MediaStreamTrack
private video_track?: MediaStreamTrack
- controls: { audio?: HTMLElement, video?: HTMLElement } = {}
+ controls?: { audio: HTMLElement, video: HTMLElement }
constructor(room: Room, name: string) {
super(room, name)
this.el.classList.add("local")
this.create_controls()
+ if (parameter_bool("audio_enabled", false)) this.enable_audio()
+ if (parameter_bool("video_enabled", false)) this.enable_video()
}
create_controls() {
@@ -39,9 +43,21 @@ export class LocalUser extends User {
const el = document.createElement("div")
el.classList.add("local-controls")
el.append(audio_toggle, video_toggle)
+ this.controls = { video: video_toggle, audio: audio_toggle }
document.body.append(el)
}
+ update_view_w() {
+ this.update_view()
+ if (this.stream.getAudioTracks().length > 0)
+ this.controls?.audio.classList.add("enabled")
+ else this.controls?.audio.classList.remove("enabled")
+
+ if (this.stream.getVideoTracks().length > 0)
+ this.controls?.video.classList.add("enabled")
+ else this.controls?.video.classList.remove("enabled")
+ }
+
async add_initial_to_remote(ru: RemoteUser) {
if (this.audio_track) ru.peer.addTrack(this.audio_track)
if (this.video_track) ru.peer.addTrack(this.video_track)
@@ -54,16 +70,31 @@ export class LocalUser extends User {
const t = this.video_track = user_media.getVideoTracks()[0]
this.room.remote_users.forEach(u => u.peer.addTrack(t))
this.stream.addTrack(t)
- this.update_view()
+ this.update_view_w()
}
async enable_audio() {
if (this.audio_track) return
log("media", "requesting user media (audio)")
- const user_media = await window.navigator.mediaDevices.getUserMedia({ audio: true })
- const t = this.audio_track = user_media.getAudioTracks()[0]
+
+ const use_rnnoise = parameter_bool("rnnoise", true)
+ const audio_contraints = use_rnnoise ? {
+ channelCount: { ideal: 1 },
+ noiseSuppression: { ideal: false },
+ echoCancellation: { ideal: true },
+ autoGainControl: { ideal: false },
+ } : true;
+
+ const user_media = await window.navigator.mediaDevices.getUserMedia({ audio: audio_contraints })
+ let t = user_media.getAudioTracks()[0]
+
+ if (use_rnnoise) {
+ t = await rnnoise_track(t)
+ }
+
+ this.audio_track = t
this.room.remote_users.forEach(u => u.peer.addTrack(t))
this.stream.addTrack(t)
- this.update_view()
+ this.update_view_w()
}
async disable_video() {
if (!this.video_track) return
@@ -73,7 +104,7 @@ export class LocalUser extends User {
})
})
this.stream.removeTrack(this.video_track)
- this.update_view()
+ this.update_view_w()
this.video_track = undefined
}
async disable_audio() {
@@ -84,7 +115,7 @@ export class LocalUser extends User {
})
})
this.stream.removeTrack(this.audio_track)
- this.update_view()
+ this.update_view_w()
this.audio_track = undefined
}
diff --git a/source/client/logger.ts b/source/client/logger.ts
index ea319b1..9960c70 100644
--- a/source/client/logger.ts
+++ b/source/client/logger.ts
@@ -1,10 +1,11 @@
-export type LogTag = "webrtc" | "ws" | "media" | "*"
+export type LogTag = "webrtc" | "ws" | "media" | "*" | "misc"
const log_tag_color: { [key in LogTag]: string } = {
"*": "#FF0000",
webrtc: "#990099",
media: "#999900",
- ws: "#009999"
+ ws: "#009999",
+ misc: "#000099",
}
// TODO maybe log time aswell
diff --git a/source/client/rnnoise.ts b/source/client/rnnoise.ts
new file mode 100644
index 0000000..6bd632e
--- /dev/null
+++ b/source/client/rnnoise.ts
@@ -0,0 +1,45 @@
+import { log } from "./logger"
+
+declare global {
+ class RNNoiseNode extends AudioWorkletNode {
+ static register(context: AudioContext): Promise<void>
+ constructor(context: AudioContext)
+ onstatus: (data: any) => void
+ update(something: boolean): void
+ }
+}
+
+
+export async function rnnoise_track(track: MediaStreamTrack): Promise<MediaStreamTrack> {
+ log("misc", "rnnoise enabled")
+ const context = new AudioContext({ sampleRate: 48000 })
+ //@ts-ignore
+ let RNNoiseNode: typeof RNNoiseNode = window.RNNoiseNode;
+
+ let script: HTMLScriptElement;
+ if (!RNNoiseNode) {
+ log("misc", "loading rnnoise...")
+ script = document.createElement("script")
+ script.src = "/static/rnnoise/rnnoise-runtime.js"
+ script.defer = true
+ document.head.appendChild(script)
+ //@ts-ignore
+ while (!window.RNNoiseNode) await new Promise<void>(r => setTimeout(() => r(), 100))
+ //@ts-ignore
+ RNNoiseNode = window.RNNoiseNode;
+ log("misc", "rnnoise loaded")
+ }
+
+ 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)
+ // rnnoise.onstatus = console.log
+ // rnnoise.update(true)
+
+ return destination.stream.getAudioTracks()[0]
+} \ No newline at end of file
diff --git a/source/client/room.ts b/source/client/room.ts
index fd48eff..3e3ed19 100644
--- a/source/client/room.ts
+++ b/source/client/room.ts
@@ -4,7 +4,7 @@ import { RemoteUser } from "./remote_user";
import { User } from "./user";
import { LocalUser } from "./local_user";
import { parameters } from ".";
-import { hex_id } from "./helper";
+import { hex_id, parameter_string } from "./helper";
export class Room {
@@ -25,7 +25,7 @@ export class Room {
this.websocket.onmessage = (ev) => {
this.websocket_message(JSON.parse(ev.data))
}
- this.local_user = new LocalUser(this, parameters.username ?? `guest-${hex_id()}`)
+ this.local_user = new LocalUser(this, parameter_string("username", `guest-${hex_id()}`))
}
websocket_send(data: CSPacket) {