dispertisex
v2.0.0
Published
A Discord music playback library for selfbots — queue management, audio streaming, YouTube search & more.
Maintainers
Readme
DispertiseX
A unified media playback library for Discord selfbots — audio, video, and camera streaming with a shared queue.
Built on top of discord.js-selfbot-v13 and @dank074/discord-video-stream, DispertiseX provides a single play() API for all media types. Just pass a song name, URL, or track and tell it what to do via streamType.
Vendor notice: The WebRTC streaming layer under
src/stream/(vendored from@dank074/discord-video-stream) is adapted from@dank074/discord-video-stream(ISC license). See the License section below for full copyright details.
Features
- 🎵 Audio streaming — Stream music from YouTube and other sources via yt-dlp + FFmpeg
- 📺 Video streaming — Stream video to voice channels (GoLive mode)
- 📷 Camera streaming — Camera/mic streaming mode
- 📋 Unified queue — Audio, video, and camera all share one queue, auto-advance between types
- 🔁 Loop modes — None, single track, or entire queue
- 🔊 Volume control — Adjust playback volume (0–200%)
- 🎛️ Audio filters — 14 built-in presets + custom FFmpeg filter support
- ⏸️ Pause / Resume — Pause and resume with position tracking
- 📜 History — Navigate back to previously played tracks
- 🔍 YouTube search — Built-in YouTube search via
youtubei.js - 📂 Playlist support — Resolve YouTube playlists automatically
Supported Platforms & Capabilities
Runtime
| | Requirement |
|---|---|
| Node.js | >= 22.4.0 |
| OS | Windows, Linux, macOS |
| Discord library | discord.js-selfbot-v13 ^3.7.1 (peer dependency) |
| External tools | yt-dlp + FFmpeg (must be installed separately) |
Stream Types
| Type | streamType value | Description |
|---|---|---|
| Audio | "audio" | Music playback (webm/opus) via voice channel |
| GoLive | "video" | Screen-share style video streaming |
| Camera | "camera" | Webcam-style video streaming |
Input Sources
| Source | Format | Audio | Video |
|---|---|---|---|
| YouTube search | text query | ✅ | ✅ (resolved to URL) |
| YouTube video | https://youtube.com/watch?v=... | ✅ | ✅ |
| YouTube playlist | https://youtube.com/playlist?list=... | ✅ | ✅ (queues all) |
| Any yt-dlp URL | any supported URL | ✅ | ✅ |
| Local file | absolute/relative path | ✅ | ✅ |
YouTube Delivery Modes
| Mode | youtubeDelivery | Behavior |
|---|---|---|
| File | "file" | Download to cache, then stream from disk |
| Pipe | "pipe" | Stream directly from yt-dlp stdout (no disk I/O) |
Installation
npm install dispertisexPrerequisites
| Dependency | Type | Notes |
|-----------|------|-------|
| discord.js-selfbot-v13 | peer | npm install discord.js-selfbot-v13 |
| yt-dlp | external | YouTube playback requires this |
| FFmpeg | external | Audio/video encoding requires this |
# Install peer dependency
npm install discord.js-selfbot-v13
# External tools
# Windows: Download ffmpeg.exe and yt-dlp.exe to your project root
# Linux/macOS: apt install ffmpeg / brew install ffmpeg yt-dlpImport / Usage
DispertiseX ships as a dual-module package — you can use it with ESM, CommonJS, or TypeScript.
ESM (recommended)
import { Client } from 'discord.js-selfbot-v13';
import { MediaManager, formatDuration, EVENTS } from 'dispertisex';
const client = new Client();
const manager = new MediaManager(client, {
cacheDir: './cache',
maxCacheFiles: 10,
});See full ESM bot example:
examples/esm.mjs
CommonJS
const { Client } = require('discord.js-selfbot-v13');
const { MediaManager, formatDuration, EVENTS } = require('dispertisex');
const client = new Client();
const manager = new MediaManager(client, {
cacheDir: './cache',
maxCacheFiles: 10,
});See full CJS bot example:
examples/cjs.cjs
TypeScript
DispertiseX includes full type declarations (index.d.ts). Import types alongside the runtime:
import { Client } from 'discord.js-selfbot-v13';
import {
MediaManager,
formatDuration,
EVENTS,
type MediaManagerOptions,
type Track,
type QueueItem,
type PlaybackState,
} from 'dispertisex';
const client = new Client();
const options: MediaManagerOptions = {
cacheDir: './cache',
maxCacheFiles: 10,
};
const manager = new MediaManager(client, options);A tsconfig.json is included in the repo — extend or copy it for your project:
{
"compilerOptions": {
"module": "Preserve",
"moduleResolution": "bundler",
"target": "ES2022",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}Type-check your project with:
npx tsc --noEmitSee full TypeScript bot example:
examples/esm.ts
Quick Start
const { Client } = require('discord.js-selfbot-v13');
const { MediaManager } = require('dispertisex');
const client = new Client();
const manager = new MediaManager(client, {
cacheDir: './cache',
maxCacheFiles: 10
});
client.on('ready', async () => {
console.log(`Logged in as ${client.user.tag}`);
// ── Audio — play by search query or URL ──
// play() handles resolving, joining voice, and playing
const result = await manager.play('123456789012345678', 'never gonna give you up', {
streamType: 'audio',
requester: client.user.id,
});
console.log(`${result.action === 'playing' ? 'Playing' : 'Queued'}: ${result.track?.title}`);
// ── Video — stream to voice channel ──
// Same play() method, just change streamType
await manager.play('123456789012345678', 'https://youtube.com/watch?v=...', {
streamType: 'video',
quality: '1080p',
});
// ── Camera mode ──
await manager.play('123456789012345678', 'https://youtube.com/watch?v=...', {
streamType: 'camera',
});
});
// Queue controls
async function skip() { await manager.skip(); }
async function pause() { manager.pause(); }
async function resume() { manager.resume(); }
async function shuffle() { manager.shuffle(); }
async function clear() { manager.clear(); }
async function leave() { await manager.stop({ leaveVoice: true }); }
client.login('YOUR_TOKEN');API
MediaManager
Constructor
const manager = new MediaManager(client);The manager is automatically attached to client.dispertisex for external access.
play(voiceId, input, options) — THE unified method 🎯
This is the main method. Play anything — audio, video, or camera — through a single API.
await manager.play(voiceChannelId, input, {
streamType: 'audio', // 'audio' | 'video' | 'camera'
requester: 'user123', // optional, for tracking
// Video options (ignored when streamType is 'audio'):
quality: '1080p', // '720p' | '1080p'
youtubeDelivery: 'file', // 'file' (download) | 'pipe' (stream live)
});| Param | Type | Description |
|-------|------|-------------|
| voiceId | string | Discord voice channel ID |
| input | string\|object\|array | Song name, URL, track object, or array of tracks |
| options.streamType | string | 'audio' (default), 'video', or 'camera' |
| options.requester | string | User ID for tracking who requested |
| options.quality | string | Video quality: '720p' or '1080p' |
| options.youtubeDelivery | string | 'file' (download then play) or 'pipe' (stream live) |
Input formats:
| Input | Example | Behavior |
|-------|---------|----------|
| Search query | 'never gonna give you up' | Searches YouTube, plays first result |
| YouTube URL | 'https://youtube.com/watch?v=...' | Plays the video/audio directly |
| YouTube playlist | 'https://youtube.com/playlist?list=...' | Queues all tracks with the chosen streamType |
| Track object | { title: 'Song', url: '...', duration: 240000 } | Plays as-is (audio, video, or camera) |
Queue behavior:
| Current state | play() does | Returns |
|--------------|---------------|---------|
| Nothing playing | ▶️ Starts immediately | { action: 'playing', track } |
| Playing audio/video/camera | ➕ Adds to queue | { action: 'queued', track } |
| Paused | ➕ Adds to queue | { action: 'queued', track } |
Auto-advance: When a track finishes, the next one in queue starts automatically — even across media types:
Queue: [audio] → [video] → [camera] → [audio]
▶️ ▶️ ▶️ ▶️Other public methods
These are called directly on the MediaManager instance:
| Method | Returns | Description |
|--------|---------|-------------|
| join(voiceId) | { streamer, channel } | Join a voice channel |
| skip() | { action, skippedTrack? } | Skip to next track |
| jumpTo(index) | { action, track } | Jump to queue index (0-based) |
| playPrevious() | { action, track } | Go back to previous track |
| pause() | void | Pause playback (audio only) |
| resume() | void | Resume playback (audio only) |
| stop({ leaveVoice }) | void | Stop all playback, optionally leave voice |
| shuffle() | void | Shuffle the queue |
| clear() | void | Clear the queue |
| setLoopMode(mode) | void | 'none' | 'track' | 'queue' |
| setVolume(vol) | void | Volume 0–200 (audio only) |
| setFilter(name) | void | Apply a preset filter by name (audio only) |
| setCustomFilter(str) | void | Set a raw FFmpeg audio filter string (audio only) |
| clearFilter() | void | Remove all filters |
| setQueue(items) | void | Replace entire queue |
| getState() | object | Full playback state snapshot |
| remove(index) | object\|null | Remove a track from queue by index |
| isActive() | boolean | Has an active voice session? |
| destroy() | void | Stop everything and clean up |
Note:
play()and the methods above are all you need. TheaddTrack/addPlaylistmethods are called internally byplay()— you don't need to call them directly.
Audio Filters (audio only — ignored for video/camera)
Use preset filters by name or pass raw FFmpeg filter strings:
// Preset filters
manager.setFilter('bassboost');
manager.setFilter('nightcore');
manager.setFilter('none'); // remove filter
// Custom FFmpeg filter string
manager.setCustomFilter('volume=0.5,bass=g=10');
// Remove filter
manager.clearFilter();Available presets:
| Preset | Description |
|---|---|
| bassboost | Heavy bass boost |
| bass | Light bass boost |
| nightcore | Speed up + pitch up |
| vaporwave | Slow down + pitch down |
| 8d | Rotating 8D audio effect |
| earrape | Extreme volume + distortion |
| chipmunk | High-pitched chipmunk voice |
| tremolo | Volume oscillation |
| vibrato | Pitch oscillation |
| karaoke | Vocal reduction |
| surround | Surround sound effect |
| soft | Softened audio |
| dance | Dance/EDM equalizer |
| pop | Pop music equalizer |
Filters only affect audio streams. Calling
setFilter()/setCustomFilter()while video/camera is playing has no effect.
Low-Level Utilities
For advanced usage — raw pipes, binary resolution, voice session control, metadata extraction, and more — see ADVANCED.md with full parameter tables, return types, and runnable code examples.
Environment Variables
| Variable | Description |
|----------|-------------|
| DISPERTISEX_ROOT | Custom root directory |
| DISPERTISEX_YTDLP | Custom path to yt-dlp binary |
| DISPERTISEX_FFMPEG | Custom path to ffmpeg binary |
License
DispertiseX is MIT.
The vendored streaming layer (src/stream/) is adapted from @dank074/discord-video-stream under the ISC license — copyright (c) Long Nguyen, s074, mrjvs, Elysia, Fede14, Malthe Morsing Larsen.
Copyright (c) contributors of @dank074/discord-video-stream
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.