With the rise of AI, we are seeing more and more applications that require server-side audio streaming capabilities. In this article, we will show you how to stream audio files into an ODIN room using our Node.js SDK.
Use Cases
There are many use cases for audio streaming:
- AI Voice Assistants: Stream AI-generated audio responses (from OpenAI, AWS Polly, etc.) back to users
- Music Bots: Play background music or sound effects in a room
- Text-to-Speech: Convert text to speech and stream it to room participants
- Audio Processing: Apply effects or transformations to audio before streaming
Our Node.js SDK is perfect for these use cases. It allows you to receive audio streams from users and send audio streams back into the room.
High-Level API (Recommended)
The simplest way to stream audio files is using the high-level API. It handles all the complexity automatically - media ID allocation, StartMedia RPC, and correct timing:
import odin from '@4players/odin-nodejs';
const { OdinClient } = odin;
const accessKey = "__YOUR_ACCESS_KEY__";
const roomId = "Lobby";
const userId = "MusicBot";
async function main() {
const client = new OdinClient();
const token = client.generateToken(accessKey, roomId, userId);
const room = client.createRoom(token);
const userData = {
name: "Music Bot",
avatar: "https://example.com/bot-avatar.png",
userId: "Bot007",
outputMuted: 1,
inputMuted: 0,
platform: "ODIN Node.js SDK",
version: "0.11.0"
};
const data = new TextEncoder().encode(JSON.stringify(userData));
const joinPromise = new Promise(resolve => room.onJoined(resolve));
room.join("https://gateway.odin.4players.io", data);
await joinPromise;
const media = room.createAudioStream(48000, 2);
console.log("Streaming MP3 file...");
await media.sendMP3('./music.mp3');
console.log("MP3 streaming complete!");
media.close();
room.close();
}
main();
The high-level API (sendMP3, sendWAV, sendBuffer) automatically handles:
- Media ID allocation from the room
- Sending the StartMedia RPC to the server
- Decoding audio files to raw PCM
- Sending audio chunks at the correct 20ms intervals
Low-Level API (Full Control)
For advanced use cases where you need full control over audio transmission, use the low-level API:
import odin from '@4players/odin-nodejs';
const { OdinClient } = odin;
import fs from 'fs';
import decode from 'audio-decode';
import AudioBufferStream from 'audio-buffer-stream';
import { encode } from '@msgpack/msgpack';
const accessKey = "__YOUR_ACCESS_KEY__";
const roomId = "Lobby";
const userId = "My Bot";
const userData = {
name: "Music Bot",
avatar: "https://avatars.dicebear.com/api/bottts/123.svg",
userId: "Bot007",
outputMuted: 1,
inputMuted: 0,
platform: "ODIN Node.js SDK",
version: "0.11.0"
};
async function main() {
const client = new OdinClient();
const token = client.generateToken(accessKey, roomId, userId);
const room = client.createRoom(token);
const data = new TextEncoder().encode(JSON.stringify(userData));
room.onJoined(async (event) => {
console.log("Joined room:", event.roomId);
console.log("My peer ID:", event.ownPeerId);
console.log("Available media IDs:", event.mediaIds);
const mediaId = event.mediaIds[0];
const media = room.createAudioStream(48000, 2);
media.setMediaId(mediaId);
const rpc = encode([0, 1, "StartMedia", {
media_id: mediaId,
properties: { kind: "audio" }
}]);
room.sendRpc(new Uint8Array(rpc));
await sendMusicLowLevel(media);
media.close();
room.close();
});
room.join("https://gateway.odin.4players.io", data);
const message = {
kind: 'message',
payload: 'Hello, I am a music bot and will stream some music to you.'
};
room.sendMessage(new TextEncoder().encode(JSON.stringify(message)));
}
async function sendMusicLowLevel(media) {
return new Promise(async (resolve) => {
const audioBuffer = await decode(fs.readFileSync('./music.mp3'));
const chunkLength = audioBuffer.sampleRate / 50;
const audioBufferStream = new AudioBufferStream({
channels: audioBuffer.numberOfChannels,
sampleRate: audioBuffer.sampleRate,
float: true,
bitDepth: 32,
chunkLength: chunkLength
});
const queue = [];
audioBufferStream.on('data', (data) => {
const floats = new Float32Array(new Uint8Array(data).buffer);
queue.push(floats);
});
const interval = setInterval(() => {
if (queue.length > 0) {
const chunk = queue.shift();
media.sendAudioData(chunk);
} else {
clearInterval(interval);
audioBufferStream.end();
console.log("Audio finished");
resolve();
}
}, 20);
audioBufferStream.write(audioBuffer);
});
}
main();
Streaming Decoded AudioBuffers
If you already have decoded audio (e.g., from an AI text-to-speech service), you can stream it directly:
import odin from '@4players/odin-nodejs';
const { OdinClient } = odin;
import decode from 'audio-decode';
import fs from 'fs';
async function streamDecodedAudio() {
const client = new OdinClient();
const token = client.generateToken(accessKey, roomId, userId);
const room = client.createRoom(token);
const joinPromise = new Promise(resolve => room.onJoined(resolve));
room.join("https://gateway.odin.4players.io");
await joinPromise;
const audioBuffer = await decode(fs.readFileSync('./speech.mp3'));
const media = room.createAudioStream(audioBuffer.sampleRate, audioBuffer.numberOfChannels);
await media.sendBuffer(audioBuffer);
media.close();
room.close();
}
Dependencies
For this example, you'll need the following npm packages:
npm install @4players/odin-nodejs audio-decode audio-buffer-stream @msgpack/msgpack
| Package | Description |
|---|
@4players/odin-nodejs | ODIN Node.js SDK |
audio-decode | Decodes MP3, WAV, and other audio formats to raw PCM |
audio-buffer-stream | Converts AudioBuffer to a readable stream |
@msgpack/msgpack | MessagePack encoder (for low-level RPC calls) |
When using the high-level API (sendMP3, sendWAV), you only need @4players/odin-nodejs and audio-decode. The SDK handles the rest internally.
Next Steps
If you can send audio, you might also be interested in receiving audio and transcribing it to text for content moderation or AI interaction. Check out our Transcribe Audio guide.
ODIN Bot SDK
This example is just a starting point. We have built an ODIN Bot SDK in TypeScript on top of the ODIN Node.js SDK that provides simple interfaces for capturing and sending audio streams. Find it on npm: @4players/odin-bot-sdk.