JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 33
  • Score
    100M100P100Q53324F
  • License MIT

YouTube search + download engine (audio/video) with optional caching.

Package Exports

  • @irithell-js/yt-play

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)
  • Auto-Update System - yt-dlp updates automatically when needed
  • 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 with cookie support
  • Auto-Configuration - Creates yt-dlp.conf with optimal settings
  • 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-play

Binaries (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();

Direct URL Support

// Search by name
const metadata1 = await engine.search("never gonna give you up");

// Or use direct YouTube URL
const metadata2 = await engine.search(
  "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
);

// Both return the same metadata format
console.log(metadata2.title); // "Rick Astley - Never Gonna Give You Up"

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

  // Cookies (required for VPS/Docker environments)
  cookiesPath: "./cookies.txt", // Path to Netscape cookies file
  // OR
  cookiesFromBrowser: "firefox", // Extract from browser: chrome, firefox, edge, safari

  // Logging
  logger: console, // Logger instance (optional)
});

For headless environments (VPS, Docker), YouTube authentication is required:

Option 1: Export cookies from browser

  1. Install browser extension: "Get cookies.txt LOCALLY"
  2. Visit youtube.com and login
  3. Export cookies to cookies.txt
  4. Use in PlayEngine:
const engine = new PlayEngine({
  cookiesPath: "/path/to/cookies.txt",
});

Option 2: Extract directly from browser (requires browser installed)

const engine = new PlayEngine({
  cookiesFromBrowser: "firefox", // chrome, firefox, edge, safari
});

The engine automatically creates yt-dlp.conf with:

  • Node.js runtime detection
  • EJS remote components
  • Cookie authentication
  • Optimal download settings

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 or get metadata from URL.

// Search by name
const metadata = await engine.search("artist - song name");

// Or use direct URL
const metadata = await engine.search(
  "https://www.youtube.com/watch?v=VIDEO_ID",
);

// 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 download

waitCache(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 cache

getFromCache(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
}

Auto-Update System

The engine includes an intelligent auto-update system for yt-dlp:

How it works

  1. Constant Background Checks - Checks GitHub for new yt-dlp releases
  2. Instant Updates on Failure - If a download fails, immediately checks and updates yt-dlp
  3. Automatic Retry - After updating, automatically retries the failed download
  4. Version Detection - Compares installed binary version with latest GitHub release
  5. Zero Downtime - Updates happen in background without blocking your application

Update Behavior

const engine = new PlayEngine();
// ✓ Checks for updates in background

// If download fails
await engine.getOrDownload(requestId, "audio");
// <!> Download failed. Forcing yt-dlp update check...
// >> Updating yt-dlp to 2026.02.04...
// ✓ Updated to 2026.02.04
// >> Retrying download after update...
// ✓ Success

Manual Update Check

To force an update check, simply trigger a download. The system will automatically update if needed.

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 quality

Custom 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);
  // Engine automatically tries to update yt-dlp and retry
}

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 2-5x 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 and manages:

  • yt-dlp (auto-updates to latest version) (~35 MB)
  • aria2c v1.37.0 (12 MB)

Binaries are platform-specific and downloaded on first npm install.

Auto-Update Schedule

  • Background Check: Constant version check
  • On-Demand: Immediately when download fails
  • Version Source: GitHub Releases API

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

If downloads fail with "Sign in to confirm you're not a bot":

  1. Export fresh cookies from your browser
  2. Ensure cookies.txt is in Netscape format
  3. Verify cookie file path is correct
  4. Try cookiesFromBrowser option if browser is installed

Update Check Failures

If auto-update fails:

# Manually update binaries
cd node_modules/@irithell-js/yt-play
node scripts/setup-binaries.mjs

License

MIT

Contributing

Issues and PRs welcome!

Changelog

Deprecated versions have been removed to prevent errors during use.

0.2.8 (Latest)

  • Fixed Codec for shorts to work in all plataforms

0.2.7

  • Fixed parse for shorts

0.2.6

  • Added auto-update system for yt-dlp
  • Direct YouTube URL support in search()
  • Auto-configuration system (creates yt-dlp.conf)
  • Cookie authentication support (cookiesPath/cookiesFromBrowser)
  • Fixed URL search returning wrong video
  • Improved error handling with automatic retry after update

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