Files
discord.js/apps/guide/content/docs/voice/audio-player.mdx
Souji bc6005f446 feat(guide): port legacy guide (#10938)
* feat: initial attempt at porting legacy guide

* feat: completion of legacy guide backport

* chore: lockfile shenanigans

* fix: handle svgs

* fix: replace svg with mermaid integration

* chore: format

* chore: remove unnecssary bullet

* chore: cleanup code highlights

* chore: explicit return

* chore: move display components after interactive components in sidebar

* chore: voice

* top link should be installation
* add docs link to sidebar

* feat: subguide-based accent styles

* chore: don't list faq twice

* chore: mention display components in interactive components

* fix: remove unoccs/order rule from guide

* chore: redirect to legacy guide instead of /guide root

* refactor: use `<kbd>`

* refactor: more kbd use

* Update apps/guide/content/docs/legacy/app-creation/handling-events.mdx

Co-authored-by: Naiyar <137700126+imnaiyar@users.noreply.github.com>

* chore: fix typos

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>

* chore: fix typos

* chore: fix links regarding secret stores across coding platforms

* chore: fix typo

* chore: link node method directly

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>

* chore: typos

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>

* chore: typo

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>

* fix: prevent v14 changes from being listed twice

* chore: prefer relative links

* chore: missed link conversion

* chore: missed link conversion

* chore: fix link

* chore: remove legacy code highlight markers

* chore: rephrase and extend contributing guidelines

* feat(setup): suggest cli flag over dotenv package

* chore: move introduction in sidebar

better navigation experience if the 'next page' in intro refers to getting started vs. updating/faq

* fix: replace outdated link

* fix: update voice dependencies

* chore: update node install instructions

* fix: list in missing access callout

* chore: match bun env file format

* chore: restore ffmpeg disclaimer

* fix: lockfile conflict

* chore: action row typo

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>

* chore: no longer use at-next for pino

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>
Co-authored-by: Naiyar <137700126+imnaiyar@users.noreply.github.com>
Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
2025-07-08 13:01:50 +00:00

144 lines
4.9 KiB
Plaintext

---
title: Audio Player
---
Audio players can be used to play audio across voice connections. A single audio player can play the same audio over multiple voice connections.
## Cheat sheet
### Creation
Creating an audio player is simple:
```js
const { createAudioPlayer } = require('@discordjs/voice');
const player = createAudioPlayer();
```
You can also customize the behaviors of an audio player. For example, the default behavior is to pause when there are no active subscribers for an audio player. This behavior can be configured to either pause, stop, or just continue playing through the stream:
```js
const { createAudioPlayer, NoSubscriberBehavior } = require('@discordjs/voice');
const player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Pause,
},
});
```
### Deletion
If you no longer require an audio player, you can `stop()` it and then remove references to it so that it gets garbage collected.
```js
player.stop();
```
### Playing audio
You can create [audio resources](./audio-resources) and then play them on an audio player.
```js
const resource = createAudioResource('/home/user/voice/track.mp3');
player.play(resource);
// Play "track.mp3" across two voice connections
connection1.subscribe(player);
connection2.subscribe(player);
```
<Callout>
**Audio players can play one audio resource at most.** If you try to play another audio resource while one is already
playing on the same player, the existing one is destroyed and replaced with the new one.
</Callout>
### Pausing/unpausing
You can call the `pause()` and `unpause()` methods. While the audio player is paused, no audio will be played. When it is resumed, it will continue where it left off.
```js
player.pause();
// Unpause after 5 seconds
setTimeout(() => player.unpause(), 5_000);
```
## Life cycle
Voice connections have their own life cycle, with five distinct states. You can follow the methods discussed in the [life cycles](./life-cycles) section to subscribe to changes to voice connections.
- **Idle** - the initial state of an audio player. The audio player will be in this state when there is no audio resource for it to play.
- **Buffering** - the state an audio player will be in while it is waiting for an audio resource to become playable. The audio player may transition from this state to either the `Playing` state (success) or the `Idle` state (failure).
- **Playing** - the state a voice connection enters when it is actively playing an audio resource. When the audio resource comes to an end, the audio player will transition to the Idle state.
- **AutoPaused** - the state a voice connection will enter when the player has paused itself because there are no active voice connections to play to. This is only possible with the `noSubscriber` behavior set to `Pause`. It will automatically transition back to `Playing` once at least one connection becomes available again.
- **Paused** - the state a voice connection enters when it is paused by the user.
```js
const { AudioPlayerStatus } = require('@discordjs/voice');
player.on(AudioPlayerStatus.Playing, () => {
console.log('The audio player has started playing!');
});
```
## Handling errors
When an audio player is given an audio resource to play, it will propagate errors from the audio resource for you to handle.
In the error handler, you can choose to either play a new audio resource or stop playback. If you take no action, the audio player will stop itself and revert to the `Idle` state.
Additionally, the error object will also contain a `resource` property that helps you to figure out which audio resource created the error.
Two different examples of how you may handle errors are shown below.
### Taking action within the error handler
In this example, the audio player will only move on to playing the next audio resource if an error has occurred. If playback ends gracefully, nothing will happen. This example avoids a transition into the Idle state.
```js
const { createAudioResource } = require('@discordjs/voice');
const resource = createAudioResource('/home/user/voice/music.mp3', {
metadata: {
title: 'A good song!',
},
});
player.play(resource);
player.on('error', (error) => {
console.error(`Error: ${error.message} with resource ${error.resource.metadata.title}`);
player.play(getNextResource());
});
```
### Taking action within the `Idle` state
In this example, the error event is used only for logging purposes. The audio player will naturally transition into the `Idle` state, and then another resource is played. This has the advantage of working with streams that come to an end gracefully, and those that are interrupted by errors.
```js
const { createAudioResource } = require('@discordjs/voice');
const resource = createAudioResource('/home/user/voice/music.mp3', {
metadata: {
title: 'A good song!',
},
});
player.play(resource);
player.on('error', (error) => {
console.error(error);
});
player.on(AudioPlayerStatus.Idle, () => {
player.play(getNextResource());
});
```