ytmusic-advanced
v1.1.0
Published
Advanced YouTube Music API client for searching and retrieving music data including songs, albums, artists, and playlists
Downloads
15
Maintainers
Readme
ytmusic-advanced: Complete Integration Guide
🎯 Overview
ytmusic-advanced is now a fully self-contained YouTube Music/YouTube API client that eliminates the need for:
- ❌ @distube/ytdl-core
- ❌ YouTube.js
- ❌ ytmusicapi
Everything you need is built-in with superior reliability and performance.
🚀 Quick Start
Installation
npm install ytmusic-advancedBasic Usage
import YTMusicAdvanced from "ytmusic-advanced";
// Initialize client
const client = await YTMusicAdvanced.initialize({
cacheEnabled: true,
timeout: 20000,
});
// Search with intelligent ranking
const results = await client.searchMusic("Shape of You Ed Sheeran");
// Get direct audio URLs
const audioData = await client.getAudioURLs(results.items[0].videoId);
console.log("Direct Audio URL:", audioData.bestAudio.url);
console.log("Bitrate:", audioData.bestAudio.bitrate);
console.log("Expires At:", audioData.expiresAt);🎵 Complete Feature Guide
1. Intelligent Search
Search with automatic quality filtering and relevance scoring:
// High-quality music search
const results = await client.searchMusic("Imagine Dragons Bones", {
limit: 10,
preferOfficial: true,
minRelevanceScore: 0.6,
});
// Each result includes:
// - Relevance score (0-1)
// - Quality score (0-1)
// - Authenticity score (0-1)
// - Technical quality score (0-1)
results.items.forEach((item) => {
console.log(`${item.rank}. ${item.title}`);
console.log(` Score: ${item.totalScore.toFixed(2)}`);
console.log(` Quality: ${item.scores.quality.toFixed(2)}`);
});2. Direct Audio URL Extraction
Get playable audio URLs with multiple quality options:
const audioData = await client.getAudioURLs("dQw4w9WgXcQ");
if (audioData.success) {
// Best quality audio
console.log("Best Audio:", audioData.bestAudio.url);
// All available formats
console.log(`Found ${audioData.formats.length} formats`);
// Filtered by quality
console.log("High Quality:", audioData.audioByQuality.high);
console.log("Medium Quality:", audioData.audioByQuality.medium);
console.log("Low Quality:", audioData.audioByQuality.low);
// Metadata
console.log("Title:", audioData.title);
console.log("Duration:", audioData.duration, "seconds");
console.log("URL expires:", audioData.expiresAt);
}3. Search + Audio URLs (One Call)
Get search results with direct playback URLs:
const results = await client.searchWithAudio("Coldplay Yellow", {
limit: 5,
maxAudioFetches: 3, // Fetch URLs for top 3 results
});
results.items.forEach((item) => {
if (item.audioData) {
console.log(`✅ ${item.title}`);
console.log(` Play: ${item.audioData.directURL}`);
} else {
console.log(`⏳ ${item.title} (audio not fetched)`);
}
});4. Advanced Search with Filters
const results = await client.advancedSearch("The Weeknd", {
contentType: "official", // 'official', 'lyrics', 'audio', 'video'
minDuration: 120, // At least 2 minutes
maxDuration: 360, // At most 6 minutes
quality: "high", // 'high', 'medium', 'low'
sortBy: "quality", // 'relevance', 'quality', 'popularity'
});5. Quick Search (Fast Response)
Get first 5 high-quality results quickly:
const results = await client.quickSearch("Travis Scott");
// Returns only top 5 results with quick processing🔧 Advanced Configuration
With IP Rotation (For High-Volume Usage)
const client = await YTMusicAdvanced.initialize({
cacheEnabled: true,
timeout: 20000,
// IP rotation (optional)
enableIPRotation: true,
proxyList: [
{ host: "proxy1.example.com", port: 8080 },
{ host: "proxy2.example.com", port: 8080 },
{ host: "proxy3.example.com", port: 8080 },
],
// Retry configuration
maxRetries: 3,
retryDelay: 1000,
// Cache settings
cacheTTL: 300000, // 5 minutes
});Mode Switching
// Start in YouTube Music mode
const client = await YTMusicAdvanced.initialize({ mode: "music" });
// Switch to regular YouTube
client.switchMode("youtube");
// Switch back to Music
client.switchMode("music");📊 Real-World Examples
Example 1: Music Player Integration
class MusicPlayer {
constructor() {
this.client = null;
this.currentTrack = null;
}
async initialize() {
this.client = await YTMusicAdvanced.initialize({
cacheEnabled: true,
timeout: 15000,
});
}
async search(query) {
const results = await this.client.searchMusic(query, {
limit: 20,
minRelevanceScore: 0.5,
});
return results.items.map((item) => ({
id: item.videoId,
title: item.title,
artist: item.artists?.[0]?.name || "Unknown",
duration: item.duration,
thumbnail: item.thumbnails?.[0]?.url,
score: item.totalScore,
}));
}
async play(videoId) {
const audioData = await this.client.getAudioURLs(videoId);
if (!audioData.success) {
throw new Error("Failed to get audio URL");
}
this.currentTrack = {
videoId,
title: audioData.title,
url: audioData.bestAudio.url,
expiresAt: new Date(audioData.expiresAt),
};
return this.currentTrack.url;
}
needsRefresh() {
if (!this.currentTrack) return false;
return new Date() >= this.currentTrack.expiresAt;
}
async refreshURL() {
if (!this.currentTrack) return;
const audioData = await this.client.getAudioURLs(this.currentTrack.videoId);
this.currentTrack.url = audioData.bestAudio.url;
this.currentTrack.expiresAt = new Date(audioData.expiresAt);
return this.currentTrack.url;
}
}
// Usage
const player = new MusicPlayer();
await player.initialize();
const results = await player.search("Dua Lipa Levitating");
const trackURL = await player.play(results[0].id);
// Play audio using trackURL in your audio playerExample 2: Playlist Downloader
async function downloadPlaylist(playlistName, songs) {
const client = await YTMusicAdvanced.initialize();
const downloads = [];
for (const song of songs) {
try {
// Search for song
const results = await client.searchMusic(song, {
limit: 1,
preferOfficial: true,
});
if (results.items.length === 0) {
console.log(`❌ Not found: ${song}`);
continue;
}
const track = results.items[0];
// Get audio URL
const audioData = await client.getAudioURLs(track.videoId);
if (audioData.success) {
downloads.push({
title: track.title,
artist: track.artists?.[0]?.name,
url: audioData.bestAudio.url,
quality: audioData.bestAudio.quality,
bitrate: audioData.bestAudio.bitrate,
});
console.log(`✅ ${track.title} - ${audioData.bestAudio.quality}`);
}
// Rate limiting
await new Promise((resolve) => setTimeout(resolve, 1000));
} catch (error) {
console.error(`❌ Error: ${song}`, error.message);
}
}
return downloads;
}
// Usage
const songs = [
"The Weeknd Blinding Lights",
"Doja Cat Paint The Town Red",
"Taylor Swift Anti-Hero",
];
const downloads = await downloadPlaylist("My Playlist", songs);Example 3: Music Discovery API
import express from "express";
import YTMusicAdvanced from "ytmusic-advanced";
const app = express();
const client = await YTMusicAdvanced.initialize();
// Search endpoint
app.get("/api/search", async (req, res) => {
try {
const { q, limit = 10 } = req.query;
const results = await client.searchMusic(q, {
limit: parseInt(limit),
minRelevanceScore: 0.5,
});
res.json({
success: true,
query: q,
results: results.items.map((item) => ({
id: item.videoId,
title: item.title,
artist: item.artists?.[0]?.name,
duration: item.duration,
thumbnail: item.thumbnails?.[0]?.url,
quality_score: item.scores.quality,
relevance_score: item.scores.relevance,
})),
});
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
});
// Stream endpoint
app.get("/api/stream/:videoId", async (req, res) => {
try {
const { videoId } = req.params;
const audioData = await client.getAudioURLs(videoId);
if (!audioData.success) {
return res.status(404).json({ success: false, error: "Not found" });
}
res.json({
success: true,
stream_url: audioData.bestAudio.url,
expires_at: audioData.expiresAt,
metadata: {
title: audioData.title,
author: audioData.author,
duration: audioData.duration,
thumbnail: audioData.thumbnail?.url,
},
formats: audioData.formats.map((f) => ({
quality: f.quality,
bitrate: f.bitrate,
codec: f.codec,
container: f.container,
url: f.url,
})),
});
} catch (error) {
res.status(500).json({ success: false, error: error.message });
}
});
app.listen(3000, () => {
console.log("Music API running on http://localhost:3000");
});🛡️ Error Handling
try {
const audioData = await client.getAudioURLs(videoId);
if (!audioData.success) {
console.error("Extraction failed:", audioData.error);
// Handle gracefully
}
// Check expiry
const expiryTime = new Date(audioData.expiresAt);
if (expiryTime < new Date()) {
console.warn("URL already expired, refreshing...");
// Refresh URL
}
} catch (error) {
if (error.code === "NETWORK_ERROR") {
console.error("Network issue, retry later");
} else if (error.code === "RATE_LIMIT_ERROR") {
console.error("Rate limited, wait before retry");
} else {
console.error("Unexpected error:", error.message);
}
}🎯 Best Practices
1. Cache Management
// Enable caching for better performance
const client = await YTMusicAdvanced.initialize({
cacheEnabled: true,
cacheTTL: 300000, // 5 minutes
});
// Clear cache when needed
await client.clearCache();
// Get cache stats
const stats = client.getStatus();
console.log("Cache size:", stats.cacheSize);2. Rate Limiting
// Built-in rate limiting (1 request per second)
// For high-volume usage, add delays:
const results = await client.searchMusic(query);
for (const item of results.items) {
const audio = await client.getAudioURLs(item.videoId);
await new Promise((resolve) => setTimeout(resolve, 1000));
}3. URL Expiry Handling
class AudioURLManager {
constructor(client) {
this.client = client;
this.urlCache = new Map();
}
async getURL(videoId) {
const cached = this.urlCache.get(videoId);
// Check if cached and not expired
if (cached && new Date(cached.expiresAt) > new Date()) {
return cached.url;
}
// Fetch new URL
const audioData = await this.client.getAudioURLs(videoId);
this.urlCache.set(videoId, {
url: audioData.bestAudio.url,
expiresAt: audioData.expiresAt,
});
return audioData.bestAudio.url;
}
}📈 Performance Tips
- Enable caching - Reduces API calls by 70-80%
- Use quick search for instant results
- Limit audio fetches in bulk operations
- Implement IP rotation for high-volume usage
- Monitor expiry times and refresh URLs proactively
🔍 Comparison with Other Libraries
| Feature | ytmusic-advanced | @distube/ytdl-core | YouTube.js | | -------------------- | ---------------- | ------------------ | ---------- | | Audio URL Extraction | ✅ Built-in | ✅ Yes | ✅ Yes | | Search | ✅ Intelligent | ❌ No | ✅ Yes | | Quality Scoring | ✅ Yes | ❌ No | ❌ No | | Signature Handling | ✅ Automatic | ✅ Yes | ✅ Yes | | IP Rotation | ✅ Yes | ❌ No | ❌ No | | Caching | ✅ Multi-tier | ❌ No | ❌ Limited | | TypeScript | ✅ Yes | ✅ Yes | ✅ Yes | | Dependencies | 📦 Minimal | 📦 Many | 📦 Many |
🆘 Troubleshooting
"No streaming data available"
// Try different extraction strategies automatically
const audioData = await client.getAudioURLs(videoId);
// The library tries:
// 1. Android client (most reliable)
// 2. iOS client (fallback)
// 3. Web client (last resort)"URL expired"
// URLs typically expire after 6 hours
// Refresh when needed:
const needsRefresh = new Date() >= new Date(audioData.expiresAt);
if (needsRefresh) {
const newAudio = await client.getAudioURLs(videoId);
}Rate Limiting
// Built-in rate limiting
// For heavy usage, enable IP rotation:
const client = await YTMusicAdvanced.initialize({
enableIPRotation: true,
proxyList: [...] // Your proxy list
});📝 License
MIT License - Feel free to use in commercial projects
🤝 Contributing
Issues and pull requests welcome at: https://github.com/your-repo/ytmusic-advanced
✨ You now have everything you need to build production-ready music applications without any external dependencies!
