aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md13
-rw-r--r--source/client/local_user.ts58
-rw-r--r--source/client/logger.ts8
-rw-r--r--source/client/remote_user.ts8
-rw-r--r--source/client/rnnoise.ts15
5 files changed, 65 insertions, 37 deletions
diff --git a/README.md b/README.md
index 9717b0d..84dee35 100644
--- a/README.md
+++ b/README.md
@@ -8,12 +8,13 @@ For configuration just add a set of the following options as query parameters to
Booleans can be either `1`, `true`, `yes` or their opposites.
-| Option name | Type | Description |
-| --------------- | ------- | -------------------------------------- |
-| `username` | string | Sets the username |
-| `rnnoise` | boolean | Enables noise suppression with rnnoise |
-| `audio_enabled` | boolean | Enables audio transmission by default |
-| `video_enabled` | boolean | Enables video transmission by default |
+| Option name | Type | Default | Description |
+| --------------- | ------- | ------- |
+| `username` | string | "guest" | Sets the username |
+| `rnnoise` | boolean | true | Enables noise suppression with rnnoise |
+| `audio_enabled` | boolean | false | Enables audio transmission by default |
+| `video_enabled` | boolean | false | Enables video transmission by default |
+| `mic_gain` | number | 1 | Sets the microphone volume |
## Licence
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