mirror of
https://github.com/ClaperCo/Claper.git
synced 2026-07-10 04:24:14 +02:00
# Conflicts: # lib/claper_web/live/admin_live/event_live.ex # lib/claper_web/live/event_live/manage.ex # lib/claper_web/live/event_live/manage.html.heex # lib/claper_web/live/event_live/manager_settings_component.ex # lib/claper_web/router.ex # priv/gettext/de/LC_MESSAGES/default.po # priv/gettext/default.pot # priv/gettext/en/LC_MESSAGES/default.po # priv/gettext/es/LC_MESSAGES/default.po # priv/gettext/fr/LC_MESSAGES/default.po # priv/gettext/hu/LC_MESSAGES/default.po # priv/gettext/it/LC_MESSAGES/default.po # priv/gettext/lv/LC_MESSAGES/default.po # priv/gettext/nl/LC_MESSAGES/default.po
88 lines
2.3 KiB
JavaScript
88 lines
2.3 KiB
JavaScript
import { Socket } from "phoenix";
|
|
|
|
export class AudioCapture {
|
|
constructor(eventUuid, audioToken) {
|
|
this.eventUuid = eventUuid;
|
|
this.audioToken = audioToken;
|
|
this.socket = null;
|
|
this.channel = null;
|
|
this.stream = null;
|
|
this.audioContext = null;
|
|
this.workletNode = null;
|
|
}
|
|
|
|
async start(deviceId) {
|
|
try {
|
|
const audioConstraints = deviceId
|
|
? { deviceId: { exact: deviceId } }
|
|
: true;
|
|
this.stream = await navigator.mediaDevices.getUserMedia({
|
|
audio: audioConstraints,
|
|
});
|
|
|
|
this.socket = new Socket("/audio", {
|
|
params: { token: this.audioToken },
|
|
});
|
|
this.socket.connect();
|
|
|
|
this.channel = this.socket.channel(`audio:${this.eventUuid}`, {});
|
|
this.channel
|
|
.join()
|
|
.receive("ok", () => {
|
|
console.log("Joined audio channel");
|
|
this.startPCMCapture();
|
|
})
|
|
.receive("error", (resp) => {
|
|
console.error("Unable to join audio channel", resp);
|
|
});
|
|
} catch (err) {
|
|
console.error("Failed to start audio capture:", err);
|
|
}
|
|
}
|
|
|
|
async startPCMCapture() {
|
|
this.audioContext = new AudioContext({ sampleRate: 48000 });
|
|
const source = this.audioContext.createMediaStreamSource(this.stream);
|
|
|
|
await this.audioContext.audioWorklet.addModule("/worklets/pcm-processor.js");
|
|
this.workletNode = new AudioWorkletNode(
|
|
this.audioContext,
|
|
"pcm-processor",
|
|
);
|
|
|
|
this.workletNode.port.onmessage = (event) => {
|
|
if (this.channel) {
|
|
const bytes = new Uint8Array(event.data);
|
|
const base64 = btoa(String.fromCharCode(...bytes));
|
|
this.channel.push("audio_chunk", { data: base64 });
|
|
}
|
|
};
|
|
|
|
source.connect(this.workletNode);
|
|
this.workletNode.connect(this.audioContext.destination);
|
|
}
|
|
|
|
stop() {
|
|
if (this.workletNode) {
|
|
this.workletNode.disconnect();
|
|
this.workletNode = null;
|
|
}
|
|
if (this.audioContext) {
|
|
this.audioContext.close();
|
|
this.audioContext = null;
|
|
}
|
|
if (this.stream) {
|
|
this.stream.getTracks().forEach((track) => track.stop());
|
|
this.stream = null;
|
|
}
|
|
if (this.channel) {
|
|
this.channel.leave();
|
|
this.channel = null;
|
|
}
|
|
if (this.socket) {
|
|
this.socket.disconnect();
|
|
this.socket = null;
|
|
}
|
|
}
|
|
}
|