boundless-truck-87206
07/24/2025, 8:54 AMtall-airline-16756
07/24/2025, 8:54 AMtall-airline-16756
07/24/2025, 8:55 AMimport { TrackToggle, useLocalParticipant } from "@livekit/components-react";
import { Track } from "livekit-client";
import { useEffect, useState } from "react";
import { Mic, MicOff } from "lucide-react";
type MicrophoneButtonProps = {
isSpaceBarEnabled?: boolean;
};
export const MicrophoneButton = ({
isSpaceBarEnabled = false,
}: MicrophoneButtonProps) => {
const { localParticipant } = useLocalParticipant();
const [isMuted, setIsMuted] = useState(localParticipant.isMicrophoneEnabled);
const [isSpaceBarPressed, setIsSpaceBarPressed] = useState(false);
useEffect(() => {
setIsMuted(localParticipant.isMicrophoneEnabled === false);
}, [localParticipant.isMicrophoneEnabled]);
useEffect(() => {
if (!isSpaceBarEnabled) return;
const handleKeyDown = (event: KeyboardEvent) => {
if (event.code === "Space") {
localParticipant.setMicrophoneEnabled(true);
setIsSpaceBarPressed(true);
}
};
const handleKeyUp = (event: KeyboardEvent) => {
if (event.code === "Space") {
localParticipant.setMicrophoneEnabled(false);
setIsSpaceBarPressed(false);
}
};
window.addEventListener("keydown", handleKeyDown);
window.addEventListener("keyup", handleKeyUp);
return () => {
window.removeEventListener("keydown", handleKeyDown);
window.removeEventListener("keyup", handleKeyUp);
};
}, [isSpaceBarEnabled, localParticipant]);
return (
);
};
2. Integrate into Your Main Component
Use the microphone button in your main voice assistant component:
import { MicrophoneButton } from "./microphone-button";
function ConversationToolbar() {
return (
{/* Other controls */}
);
}
3. Room Setup with LiveKit
Set up your LiveKit room connection and enable microphone access:
import { Room, RoomEvent } from "livekit-client";
import { RoomContext } from "@livekit/components-react";
export default function Page() {
const [room] = useState(new Room());
const onConnectButtonClicked = useCallback(async () => {
const response = await fetch("/api/connection-details");
const connectionDetailsData = await response.json();
await room.connect(connectionDetailsData.serverUrl, connectionDetailsData.participantToken);
await room.localParticipant.setMicrophoneEnabled(true);
}, [room]);
return (
);
}
4. Backend Configuration (Optional)
For advanced push-to-talk functionality, you can configure manual turn control on the backend by setting turn_detection="manual" in the AgentSession constructor and disabling audio input at the start:
session = AgentSession(
turn_detection="manual",
# ... stt, tts, llm, etc.
)
# Disable audio input at the start
session.input.set_audio_enabled(False)
You can then control the user’s turn with session.interrupt(), session.clear_user_turn(), and session.commit_user_turn() methods, and implement this using RPC methods that the frontend can call.
This approach provides a fully functional push-to-talk interface that integrates seamlessly with LiveKit’s voice assistant capabilities in your React/Next.js application.
Sources: complex-agents/teleprompter/teleprompter-frontend/components/microphone-but... | Turn detection and interruptions | LiveKit Docs