Remote quickstart
Install and start remedia-server, then connect a Discord bot to it with @remedia/client.
This guide runs audio on a separate remedia-server process. Your bot only needs @remedia/client:
no FFmpeg and no native addon on the bot machine. Requires Node.js 22.18 or newer in the bot.
1. Install the server
On the machine that will play audio:
curl -fsSL https://remedia.twlite.dev/install.sh | shOn Windows PowerShell:
irm https://remedia.twlite.dev/install.ps1 | iexThe installer provisions remedia-server and FFmpeg 9 together and puts a remedia command on your
path. Open a new terminal afterwards. No Rust toolchain is needed.
See Install the server for options, or run the server in a container with
Docker Compose.
2. Create a configuration
remedia initThis writes remedia.config.json with a random auth.password and username remedia. It listens
on 127.0.0.1:8787 and allows no media sources until you configure some. Edit
media.allowedUrlHosts to list the hosts your bot may play from, for example
["media.example.com"]. See Server configuration.
3. Start and check the server
remedia-server doctor # checks FFmpeg and your configuration
remedia-server # starts the serverThe server prints remedia-server listening on 127.0.0.1:8787. In another terminal,
remedia-server --list shows running servers.
4. Connect your bot
npm install @remedia/client discord.jsimport { Client, Events, GatewayIntentBits } from 'discord.js';
import { RemediaClient } from '@remedia/client';
const discord = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates],
});
discord.once(Events.ClientReady, async (ready) => {
const remedia = await RemediaClient.create({
botUserId: ready.user.id,
nodes: [
{
type: 'remote',
id: 'media-1',
url: 'remedia://127.0.0.1:8787',
auth: { username: 'remedia', password: process.env.REMEDIA_PASSWORD! },
},
],
send(guildId, payload) {
discord.guilds.cache.get(guildId)?.shard.send(payload);
},
});
discord.on(Events.Raw, (packet) => remedia.receive(packet));
const voice = remedia.createDiscordSession({
guildId: '123456789012345678',
channelId: '234567890123456789',
userId: ready.user.id,
});
try {
await voice.connect();
await voice.play({ url: 'https://media.example.com/audio.mp3' });
await voice.wait();
} finally {
await remedia.close();
discord.destroy();
}
});
await discord.login(process.env.DISCORD_TOKEN);Export DISCORD_TOKEN and set REMEDIA_PASSWORD in the bot process to the generated auth.password before running the example. The example logs in, plays one source, and closes both clients.
remedia is the username from the generated configuration. URLs and files are opened by the
server, so a { file } source is a path on the server machine and the URL host must be allowed in
the server configuration. Buffers and Readables need an embedded node.
Use remedias:// instead of remedia:// for a TLS-protected server behind a reverse proxy. Do not
expose the plain listener to the public internet. See Deployment.
Next steps
- Using
@remedia/client: controls, events, and cleanup. - Nodes and routing: several servers, or embedded plus remote.
- Server CLI and Server configuration.
- Executing plugin operations and Playing audio through plugins.