Remedia

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 | sh

On Windows PowerShell:

irm https://remedia.twlite.dev/install.ps1 | iex

The 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 init

This 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 server

The 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.js
import { 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

On this page