feat(fe): real mic capture for voice transmit (kirim suara)
Sebelumnya tombol Live/Muted cuma kirim voice:transmit:start/stop ke gateway — TIDAK ADA audio yang dikirim (0 getUserMedia/AudioContext di frontend). MicControl cuma toggle state kosong. - lib/audio/mic-transmit.ts (BARU): getUserMedia → AudioContext 48kHz → AudioWorklet (downsample 24kHz mono s16le + volume + chunk 20ms) → frame 'PCM\0' + Int16LE → ws.sendBinary. Worklet inline via Blob URL (aman untuk static export). - useMicTransmit(ws): aktif = start capture + voice:transmit:start; nonaktif = stop capture + voice:transmit:stop; setVolume untuk slider. - voice page: volume slider sekarang beneran ngatur gain mic; disconnect ikut matiin mic. Verifikasi: tsc PASS, biome 0 error, next build PASS. Test mic butuh real device (headless browser tidak punya mic) — protokol: connect voice → Live → ngomong → orang di channel denger.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import useSWR, { useSWRConfig } from "swr";
|
||||
import { useAction } from "@/hooks/use-action";
|
||||
import { voiceApi } from "@/lib/api";
|
||||
import { MicTransmitter } from "@/lib/audio/mic-transmit";
|
||||
import type { ActiveSpeaker, Channel, VoiceStatus } from "@/lib/types";
|
||||
import type { WsHook } from "@/lib/ws-hook";
|
||||
|
||||
@@ -65,10 +66,27 @@ export function useVoiceDisconnect() {
|
||||
return useAction(() => voiceApi.disconnect(), { onSuccess: invalidate });
|
||||
}
|
||||
|
||||
export function useMicTransmit() {
|
||||
return useAction((active: boolean) =>
|
||||
voiceApi.sendCommand(
|
||||
active ? "voice:transmit:start" : "voice:transmit:stop",
|
||||
),
|
||||
);
|
||||
export function useMicTransmit(ws: {
|
||||
sendBinary: (data: ArrayBufferLike) => void;
|
||||
}) {
|
||||
const transmitterRef = useRef<MicTransmitter | null>(null);
|
||||
|
||||
const action = useAction(async (active: boolean) => {
|
||||
if (active) {
|
||||
const transmitter = new MicTransmitter((frame) => ws.sendBinary(frame));
|
||||
transmitterRef.current = transmitter;
|
||||
await transmitter.start();
|
||||
await voiceApi.sendCommand("voice:transmit:start");
|
||||
} else {
|
||||
transmitterRef.current?.stop();
|
||||
transmitterRef.current = null;
|
||||
await voiceApi.sendCommand("voice:transmit:stop");
|
||||
}
|
||||
});
|
||||
|
||||
const setVolume = useCallback((volume: number) => {
|
||||
transmitterRef.current?.setVolume(volume / 100);
|
||||
}, []);
|
||||
|
||||
return { ...action, setVolume };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user