- How do I install discord-php-helpers/voice in a Laravel project?
- Install the package with Composer using composer require discord-php-helpers/voice, and make sure the base DiscordPHP library (v2 or newer) is installed alongside it. You also need reactphp/event-loop if your application does not already run a ReactPHP loop. After installing, enable ext-ffi and ext-json (plus ext-gmp on 32-bit PHP) and run the bundled scripts/setup-libdave.sh to fetch libdave, which defaults to version 1.2.1. Without libdave present the runtime throws LibDaveNotFoundException, so complete that native step before writing bot code.
- What are the system requirements for discord-php-helpers/voice?
- The package requires PHP 8.3 or higher, ext-json, and ext-ffi with libdave installed, plus ext-gmp on x86 32-bit builds. You also need FFmpeg and Opus tooling for audio processing and libsodium for encryption in most recording setups. Because FFI and native libraries are involved, shared hosting usually will not work and a VPS or Docker environment is the practical baseline.
- Can I use this Discord voice package with Laravel?
- Yes, but only indirectly: the package is an extension of DiscordPHP, which is built on ReactPHP promises and an event loop rather than Laravel's synchronous request lifecycle. A typical integration bridges ReactPHP with Laravel using spatie/async or a custom listener, then boots the Discord client and voice manager inside a long-running worker or Artisan command. If your Laravel app does not already use DiscordPHP, treat the event loop integration as real migration effort rather than a drop-in install.
- Why does the package require ext-ffi and libdave?
- Discord enforces DAVE, the Audio/Video End-to-End Encryption protocol, for voice connections since March 2026, and libdave is the native library that implements the MLS session and media encryption APIs. The package loads those APIs through PHP's FFI extension, so ext-ffi must be enabled and libdave must be discoverable at runtime. There is no pure-PHP fallback; a missing library results in LibDaveNotFoundException.
- How do I make the bot join a voice channel?
- Register an init handler on the Discord client, resolve the target channel with getChannel, and call joinChannel on the voice manager. As of v8.3.1, the documented one-argument form joinChannel($channel) works because the manager defaults to the Discord client it was constructed with. Existing code that passes a client explicitly remains compatible. After joining, the voice client exposes playback and receive streams through the ReactPHP loop.
- How many concurrent voice streams can one instance handle?
- The package supports a maximum of 25 concurrent decoders per instance, which is a hard limit rather than a soft guideline. Beyond that you need to shard the bot or run multiple worker processes, each with its own voice manager and event loop. Benchmark under realistic load before scaling, since decoding plus Opus work is CPU intensive.
- How should I handle errors and failed audio playback?
- Voice failures surface through the granular VoiceException interface, including LibDaveNotFoundException when native dependencies are missing, so wrap join, play, and record calls in try/catch blocks and inspect the specific exception type. Playback also returns promises, and v8.3.1 clarifies how rejection should be handled as well as the pending playback promise that remains after calling stop(). You must implement your own auto-reconnect and fallback logic, because the package reports errors rather than recovering from them.
- Does this package work with Swoole or other async runtimes?
- No; the voice stack is tightly coupled to ReactPHP's event loop through DiscordPHP, so running it inside a Swoole server is not supported. If your application already uses Swoole for HTTP handling, run the Discord bot in a separate ReactPHP worker process instead of mixing the two loops. Legacy Laravel versions without async or promise support are also a poor fit.
- Is discord-php-helpers/voice production ready, and how do I test it?
- CI covers Pest tests, PHPStan, linting, coverage, and a libdave 1.2.1 installation check, but it does not perform a live Discord voice call, so runtime voice behaviour still needs staging smoke tests. Plan for roughly 500 ms of initial connection delay and 20 ms frame timing when designing user experience, and validate playback and recording against a real guild before release. Track the libdave version you pin, since protocol compatibility depends on it.
- What alternatives exist if I only need voice playback or cannot use native dependencies?
- If you only need simple playback and your host cannot support ext-ffi and libdave, consider running a separate Node.js voice service with @discordjs/voice or a Python bot with discord.py, and have Laravel call it over HTTP or a queue. If your app already uses DiscordPHP heavily, staying with this package keeps a single gateway connection and lets you use opcode handling out of the box. Pure PHP CLI bots are also viable for playback-only use cases when no HTTP framework integration is needed.