@tf2pickup-org/mumble-client
Version:
A simple bot for managing mumble servers
144 lines (107 loc) • 3.67 kB
Markdown
This document covers the full audio data extraction and sending capabilities of `@tf2pickup-org/mumble-client`.
```typescript
import { Client, AudioCodec, FullAudioPacket } from '@tf2pickup-org/mumble-client';
const client = new Client({
host: 'mumble://example.com',
port: 64738,
username: 'audio-bot',
});
await client.connect();
if (client.isConnected()) {
const socket = client.socket;
socket.fullAudioPacket.subscribe((packet: FullAudioPacket) => {
console.log(`Audio from user ${packet.source}`);
console.log(`Codec: ${AudioCodec[packet.codec]}`);
console.log(`Sequence: ${packet.sequence}`);
console.log(`Audio data length: ${packet.audioData.length} bytes`);
console.log(`Is final packet: ${packet.hasTerminator}`);
processAudio(packet.audioData, packet.codec);
});
}
async function processAudio(encodedAudio: Buffer, codec: AudioCodec) {
if (codec === AudioCodec.Opus) {
const text = await transcribeOpus(encodedAudio);
console.log('Transcribed:', text);
}
}
```
```typescript
import { AudioCodec } from '@tf2pickup-org/mumble-client';
const opusFrames: Buffer[] = await generateOpusAudio();
for (let i = 0; i < opusFrames.length; i++) {
await socket.sendAudio({
data: opusFrames[i],
codec: AudioCodec.Opus,
target: 0,
isTerminator: i === opusFrames.length - 1,
});
// Add delay matching frame duration (typically 20ms for Opus)
await sleep(20);
}
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
```
```typescript
import { Client, AudioCodec, FullAudioPacket } from '@tf2pickup-org/mumble-client';
async function createVoiceChatBot() {
const client = new Client({
host: 'mumble://example.com',
port: 64738,
username: 'voice-assistant',
});
await client.connect();
if (!client.isConnected()) {
throw new Error('Failed to connect');
}
const socket = client.socket;
socket.fullAudioPacket.subscribe(async (packet: FullAudioPacket) => {
if (packet.codec !== AudioCodec.Opus) {
console.warn('Only Opus codec supported');
return;
}
if (packet.hasTerminator) {
const text = await transcribeAudio(packet.audioData);
console.log('User said:', text);
const responseText = await generateResponse(text);
console.log('Bot responds:', responseText);
const audioFrames = await textToSpeech(responseText);
for (let i = 0; i < audioFrames.length; i++) {
await socket.sendAudio({
data: audioFrames[i],
codec: AudioCodec.Opus,
target: 0,
isTerminator: i === audioFrames.length - 1,
});
await sleep(20);
}
}
});
console.log('Voice chat bot ready!');
}
async function transcribeAudio(opus: Buffer): Promise<string> {
return 'transcribed text';
}
async function generateResponse(text: string): Promise<string> {
return 'bot response';
}
async function textToSpeech(text: string): Promise<Buffer[]> {
return [];
}
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
```
- **Opus** (recommended): Modern, efficient codec. Default for Mumble 1.2.4+
- **CELT Alpha/Beta**: Legacy codecs, less common
- **Speex**: Old codec, rarely used
Most modern Mumble servers use **Opus exclusively**.
- Opus frames are typically **20ms** of audio
- Send frames at the same rate as their duration
- Set `isTerminator: true` on the last frame to signal end of transmission