diff options
-rw-r--r-- | client-web/scripts/gen_param_table.ts | 21 | ||||
-rw-r--r-- | client-web/source/helper.ts | 4 | ||||
-rw-r--r-- | client-web/source/preferences.ts | 55 | ||||
-rw-r--r-- | client-web/source/user/local.ts | 12 | ||||
-rw-r--r-- | readme.md | 25 |
5 files changed, 78 insertions, 39 deletions
diff --git a/client-web/scripts/gen_param_table.ts b/client-web/scripts/gen_param_table.ts new file mode 100644 index 0000000..cc9a5ac --- /dev/null +++ b/client-web/scripts/gen_param_table.ts @@ -0,0 +1,21 @@ +import { PrefDecl, PREF_DECLS } from "../source/preferences.ts"; + +console.log(`Option name|Type|Default|Description`); +console.log(`---|---|---|---`); + +const P = PREF_DECLS as Record<string, PrefDecl<unknown>> +for (const key in P) { + const e = P[key]; + if (key == "username") e.default = "guest-…" // maybe generalize + const q = (e: string) => `\`${e}\`` + console.log([ + q(key), + typeof e.type, + e.default === undefined ? "-" : q(JSON.stringify(e.default)), + (e.description ?? "*none*") + ( + e.possible_values + ? " (" + e.possible_values.map(e => JSON.stringify(e)).map(q).join(" / ") + ")" + : "" + ) + ].join("|")); +}
\ No newline at end of file diff --git a/client-web/source/helper.ts b/client-web/source/helper.ts index 8dafd29..b4eb20e 100644 --- a/client-web/source/helper.ts +++ b/client-web/source/helper.ts @@ -1,9 +1,5 @@ /// <reference lib="dom" /> -export function hex_id(len = 8): string { - if (len > 8) return hex_id() + hex_id(len - 8) - return Math.floor(Math.random() * 16 ** len).toString(16).padStart(len, "0") -} const elem = (s: string) => document.createElement(s) diff --git a/client-web/source/preferences.ts b/client-web/source/preferences.ts index b47956b..d6b6656 100644 --- a/client-web/source/preferences.ts +++ b/client-web/source/preferences.ts @@ -1,31 +1,55 @@ -import { hex_id } from "./helper.ts"; +// there should be no deps to dom APIs in this file for the tablegen to work + +export function hex_id(len = 8): string { + if (len > 8) return hex_id() + hex_id(len - 8) + return Math.floor(Math.random() * 16 ** len).toString(16).padStart(len, "0") +} + +// TODO this could be simpler +const string = "", bool = false, number = 0; // example types for ts +export const PREF_DECLS = { + username: { type: string, default: "guest-" + hex_id(), description: "Username" }, + warn_redirect: { type: bool, default: false, description: "Interal option that is set by a server redirect." }, + + /* MEDIA */ + microphone_enabled: { type: bool, default: false, description: "Add one microphone track on startup" }, + screencast_enabled: { type: bool, default: false, description: "Add one screencast track on startup" }, + camera_enabled: { type: bool, default: false, description: "Add one camera track on startup" }, + rnnoise: { type: bool, default: true, description: "Use RNNoise for noise suppression" }, + native_noise_suppression: { type: bool, default: false, description: "Suggest the browser to do noise suppression" }, + microphone_gain: { type: number, default: 1, description: "Amplify microphone volume" }, + video_fps: { type: number, description: "Preferred framerate (in 1/s) for screencast and camera" }, + video_resolution: { type: number, description: "Preferred width for screencast and camera" }, + camera_facing_mode: { type: string, possible_values: ["environment", "user"], description: "Prefer user-facing or env-facing camera" }, + auto_gain_control: { type: bool, description: "Automatically adjust mic gain" }, + echo_cancellation: { type: bool, description: "Cancel echo" }, +} export interface PrefDecl<T> { - name: string, - default: T, - type?: Type, - description: string, + default?: T, + type: T, + description?: string, possible_values?: T[] optional?: boolean, } type Type = "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"; +type TypeMapper = { "string": string, "number": number, "boolean": boolean } -type PrefMap<T extends { [key: string]: { default: unknown } }> = { [Key in keyof T]: T[Key]["default"] } +type PrefMap<T extends { [key: string]: { type: unknown } }> = { [Key in keyof T]: T[Key]["type"] } export function register_prefs<T extends Record<string, PrefDecl<unknown>>>(ds: T): PrefMap<T> { const p: PrefMap<T> = {} as PrefMap<T> for (const key in ds) { const d = ds[key]; - let type = typeof d.default; - if (type == "undefined") { if (d.type) type = d.type; else throw new Error("type needed"); } - let value = get_param(type, d.name) ?? d.default; + const type = typeof d.type; + let value = get_param(type, key) ?? d.default; if (d.possible_values) if (!d.possible_values.includes(value)) value = d.default p[key] = value } return p } -const raw_params = load_params().p; +const raw_params = globalThis.Deno ? {} : load_params().p; export function load_params(): { p: { [key: string]: string }, rname: string } { const q: Record<string, string> = {} const [rname, params] = window.location.hash.substring(1).split("?") @@ -56,15 +80,4 @@ export function get_param<T>(ty: string, key: string): T | undefined { return undefined } -const PREF_DECLS = { - rnnoise: { name: "rnnoise", default: true, description: "Use RNNoise for noise suppression" }, - native_noise_suppression: { name: "native_noise_suppression", default: false, description: "Suggest the browser to do noise suppression" }, - username: { name: "username", default: "guest-" + hex_id(), description: "Username" }, - microphone_gain: { name: "microphone_gain", default: 1, description: "Amplify microphone volume" }, - microphone_enabled: { name: "microphone_enabled", default: false, description: "Add one microphone track on startup" }, - camera_enabled: { name: "camera_enabled", default: false, description: "Add one camera track on startup" }, - screencast_enabled: { name: "screencast_enabled", default: false, description: "Add one screencast track on startup" }, - camera_facing_mode: { name: "camera_facing_mode", default: undefined as undefined | string, type: "string" as const, possible_values: ["environment", "user", undefined], description: "Prefer user-facing or env-facing camera" }, - warn_redirect: { name: "warn_redirect", default: false, description: "Interal option that is set by a server redirect." }, -} export const PREFS = register_prefs(PREF_DECLS) diff --git a/client-web/source/user/local.ts b/client-web/source/user/local.ts index bafa56f..ac52692 100644 --- a/client-web/source/user/local.ts +++ b/client-web/source/user/local.ts @@ -89,7 +89,11 @@ export class LocalUser extends User { async create_camera_track() { log("media", "requesting user media (camera)") const user_media = await window.navigator.mediaDevices.getUserMedia({ - video: { facingMode: { ideal: PREFS.camera_facing_mode } } + video: { + facingMode: { ideal: PREFS.camera_facing_mode }, + frameRate: { ideal: PREFS.video_fps }, + width: { ideal: PREFS.video_resolution } + } }) return new TrackHandle(user_media.getVideoTracks()[0], true) } @@ -109,9 +113,9 @@ export class LocalUser extends User { autoGainControl: { ideal: true }, } : { channelCount: { ideal: 1 }, - noiseSuppression: { ideal: false }, - echoCancellation: { ideal: true }, - autoGainControl: { ideal: true }, + noiseSuppression: { ideal: PREFS.native_noise_suppression }, + echoCancellation: { ideal: PREFS.echo_cancellation }, + autoGainControl: { ideal: PREFS.auto_gain_control }, }; const user_media = await window.navigator.mediaDevices.getUserMedia({ audio: audio_contraints }) @@ -47,16 +47,21 @@ Configuration parameters are added like query params but **after** the section. The page will not automatically reload if the section changes. Booleans can be either `1`, `true`, `yes` or their opposites. -| Option name | Default | Description | -| -------------------------- | --------- | -------------------------------------------------------------- | -| `rnnoise` | `true` | Use RNNoise for noise suppression | -| `native_noise_suppression` | `false` | Suggest the browser to do noise suppression | -| `username` | `guest-…` | "Username | -| `microphone_gain` | `1` | Amplify microphone volume | -| `microphone_enabled` | `false` | Add one microphone track on startup | -| `camera_enabled` | `false` | Add one camera track on startup | -| `screencast_enabled` | `false` | Add one screencast track on startup | -| `camera_facing_mode` | undefined | Prefer user-facing or env-facing camera (`environment`/`user`) | +| Option name | Type | Default | Description | +| -------------------------- | ------- | ----------- | -------------------------------------------------------------------- | +| `username` | string | `"guest-…"` | Username | +| `warn_redirect` | boolean | `false` | Interal option that is set by a server redirect. | +| `microphone_enabled` | boolean | `false` | Add one microphone track on startup | +| `screencast_enabled` | boolean | `false` | Add one screencast track on startup | +| `camera_enabled` | boolean | `false` | Add one camera track on startup | +| `rnnoise` | boolean | `true` | Use RNNoise for noise suppression | +| `native_noise_suppression` | boolean | `false` | Suggest the browser to do noise suppression | +| `microphone_gain` | number | `1` | Amplify microphone volume | +| `video_fps` | number | - | Preferred framerate (in 1/s) for screencast and camera | +| `video_resolution` | number | - | Preferred width for screencast and camera | +| `camera_facing_mode` | string | - | Prefer user-facing or env-facing camera (`"environment"` / `"user"`) | +| `auto_gain_control` | boolean | - | Automatically adjust mic gain | +| `echo_cancellation` | boolean | - | Cancel echo | ## Todo-List |