npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dispertisex

v2.0.0

Published

A Discord music playback library for selfbots — queue management, audio streaming, YouTube search & more.

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 dispertisex

Prerequisites

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

Import / 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 --noEmit

See 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. The addTrack / addPlaylist methods are called internally by play() — 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.