@irithell-js/yt-play
v0.2.5
Published
YouTube search + download engine (audio/video) with optional caching.
Maintainers
Readme
@irithell-js/yt-play
High-performance YouTube audio/video download engine with intelligent caching, built-in yt-dlp and aria2c binaries for blazing fast downloads.
Features
- ✅ Bundled Binaries - yt-dlp and aria2c included (no system dependencies)
- Ultra Fast Downloads - aria2c acceleration (up to 5x faster)
- Intelligent Caching - TTL-based cache with automatic cleanup
- Smart Quality - Auto-reduces quality for long videos (>1h)
- Container Ready - Works in Docker/isolated environments
- Cross-Platform - Linux (x64/arm64), macOS, Windows
- Zero Config - Auto-detects binaries and optimizes settings
- TypeScript - Full type definitions included
- Dual Format - ESM and CommonJS support
Installation
npm install @irithell-js/yt-playBinaries (yt-dlp + aria2c) are automatically downloaded during installation (this may take a few seconds during the first use).
Quick Start
Basic Usage (ESM)
import { PlayEngine } from "@irithell-js/yt-play";
const engine = new PlayEngine();
// Search and download
const metadata = await engine.search("linkin park numb");
if (!metadata) throw new Error("Not found");
const requestId = engine.generateRequestId();
await engine.preload(metadata, requestId);
// Get audio file
const { file: audioFile } = await engine.getOrDownload(requestId, "audio");
console.log("Audio:", audioFile.path);
// Get video file
const { file: videoFile } = await engine.getOrDownload(requestId, "video");
console.log("Video:", videoFile.path);
// Cleanup cache
engine.cleanup(requestId);Basic Usage (CommonJS)
const { PlayEngine } = require("@irithell-js/yt-play");
const engine = new PlayEngine();
async function download() {
const metadata = await engine.search("song name");
const requestId = engine.generateRequestId();
await engine.preload(metadata, requestId);
const { file } = await engine.getOrDownload(requestId, "audio");
console.log("Downloaded:", file.path);
engine.cleanup(requestId);
}
download();Configuration
Constructor Options
const engine = new PlayEngine({
// Cache settings
cacheDir: "./cache", // Cache directory (default: OS temp)
ttlMs: 5 * 60_000, // Cache TTL in ms (default: 3min)
cleanupIntervalMs: 30_000, // Cleanup interval (default: 30s)
preloadBuffer: true, // Load files into RAM (default: true)
// Quality settings
preferredAudioKbps: 128, // Audio quality: 320|256|192|128|96|64
preferredVideoP: 720, // Video quality: 1080|720|480|360
maxPreloadDurationSeconds: 1200, // Max duration for preload (default: 20min)
// Performance settings (auto-optimized)
useAria2c: true, // Use aria2c for downloads (default: auto)
concurrentFragments: 8, // Parallel fragments (default: 5)
ytdlpTimeoutMs: 300_000, // yt-dlp timeout (default: 5min)
// Binary paths (optional - auto-detected)
ytdlpBinaryPath: "./bin/yt-dlp",
aria2cPath: "./bin/aria2c",
ffmpegPath: "/usr/bin/ffmpeg", // Optional
// Logging
logger: console, // Logger instance (optional)
// cookies (optional for VPS and dockers)
cookiesPath: "./cookies.txt",
// or
cookiesFromBrowser: "firefox", // extract from browser
});Quality Presets
// High quality (larger files)
const hq = new PlayEngine({
preferredAudioKbps: 320,
preferredVideoP: 1080,
});
// Balanced (recommended)
const balanced = new PlayEngine({
preferredAudioKbps: 128,
preferredVideoP: 720,
});
// Low quality (faster, smaller)
const lq = new PlayEngine({
preferredAudioKbps: 96,
preferredVideoP: 480,
});API Reference
PlayEngine Methods
search(query: string): Promise<PlayMetadata | null>
Search for a video on YouTube.
const metadata = await engine.search("artist - song name");
// Returns: { title, author, duration, durationSeconds, thumb, videoId, url }generateRequestId(prefix?: string): string
Generate unique request ID for caching.
const requestId = engine.generateRequestId("audio"); // "audio_1234567890_abc123"preload(metadata: PlayMetadata, requestId: string): Promise<void>
Pre-download audio and video in parallel (cached for TTL duration).
await engine.preload(metadata, requestId);
// Downloads audio + video if <1h, only audio if >1h (96kbps)getOrDownload(requestId: string, type: 'audio' | 'video'): Promise<Result>
Get file from cache or download directly.
const result = await engine.getOrDownload(requestId, "audio");
// Returns: { metadata, file: { path, size, info, buffer? }, direct: boolean }
console.log(result.file.path); // "/tmp/cache/audio_xxx.m4a"
console.log(result.file.size); // 8457234 (bytes)
console.log(result.file.info.quality); // "128kbps m4a"
console.log(result.direct); // false if from cache, true if direct downloadwaitCache(requestId: string, type: 'audio' | 'video', timeoutMs?: number, intervalMs?: number): Promise<CachedFile | null>
Wait for cache to be ready (useful for checking preload status).
const cached = await engine.waitCache(requestId, "audio", 8000, 500);
if (cached) {
console.log("Cache ready:", cached.path);
} else {
console.log("Timeout - falling back to direct download");
}cleanup(requestId: string): void
Remove cached files for a request.
engine.cleanup(requestId); // Deletes audio + video from cachegetFromCache(requestId: string): CacheEntry | undefined
Get cache entry metadata (without downloading).
const entry = engine.getFromCache(requestId);
if (entry) {
console.log(entry.metadata.title);
console.log(entry.audio?.path);
console.log(entry.loading); // true if preload in progress
}Advanced Usage
Handle Long Videos (>1h)
const metadata = await engine.search("2h music mix");
// Automatically uses:
// - Audio: 96kbps (reduced quality)
// - Video: skipped (audio only)
await engine.preload(metadata, requestId);
const { file } = await engine.getOrDownload(requestId, "audio");
// Fast download with reduced qualityCustom Cache Directory
import path from "path";
const engine = new PlayEngine({
cacheDir: path.join(process.cwd(), "downloads"),
ttlMs: 10 * 60_000, // 10 minutes
});Performance Monitoring
const startTime = Date.now();
await engine.preload(metadata, requestId);
const preloadTime = Date.now() - startTime;
console.log(`Preload took ${(preloadTime / 1000).toFixed(2)}s`);Error Handling
try {
const metadata = await engine.search("non-existent-video");
if (!metadata) {
console.error("Video not found");
return;
}
await engine.preload(metadata, requestId);
const { file } = await engine.getOrDownload(requestId, "audio");
console.log("Success:", file.path);
} catch (error) {
console.error("Download failed:", error.message);
}Performance
With aria2c enabled (default):
| Video Length | Audio Download | Video Download | Total Time | | ------------ | -------------- | -------------- | ---------- | | 5 min | ~3-5s | ~6-8s | ~8s | | 1 hour | ~15-20s | Audio only | ~20s | | 2 hours | ~25-30s | Audio only | ~30s |
Times may vary based on network speed and YouTube throttling
The values are based on local tests with optimized caching, for downloading long videos use direct download
File Formats
- Audio: M4A (native format, no conversion needed)
- Video: MP4 (with audio merged)
M4A provides better quality-to-size ratio and downloads 10-20x faster (no re-encoding).
Requirements
- Node.js >= 18.0.0
- ~50MB disk space for binaries (auto-downloaded)
- Optional: ffmpeg for advanced features
Binaries
The package automatically downloads:
- yt-dlp v2025.12.08 (35 MB)
- aria2c v1.37.0 (12 MB)
Binaries are platform-specific and downloaded on first npm install.
Supported Platforms
- Linux x64 / arm64
- macOS x64 / arm64 (Apple Silicon)
- Windows x64
Manual Binary Paths
const engine = new PlayEngine({
ytdlpBinaryPath: "/custom/path/yt-dlp",
aria2cPath: "/custom/path/aria2c",
});Troubleshooting
Slow Downloads
// Enable aria2c explicitly
const engine = new PlayEngine({
useAria2c: true,
concurrentFragments: 10, // Increase parallelism
});Cache Issues
// Clear cache directory manually
import fs from "fs";
fs.rmSync("./cache", { recursive: true, force: true });Binary Not Found
Binaries are auto-downloaded to node_modules/@irithell-js/yt-play/bin/. If missing:
npm rebuild @irithell-js/yt-playLicense
MIT
Contributing
Issues and PRs welcome!
Changelog
Deprecated versions have been removed to prevent errors during use.
0.2.5
- Added support to direct cookies extraction in pre built browsers
0.2.4
- Added support to cookies.txt
0.2.3
- Updated documentation
- Improved error messages
0.2.2
- Many syntax errors fixed
0.2.1
- Added auto-detection for yt-dlp and aria2c binaries
- Fixed CommonJS compatibility
- Improved error handling for long videos
0.2.0
- Initial release with bundled binaries
- aria2c acceleration support
- Intelligent caching system
