musify
v1.2.3
Published
Powerful and elegant music image generator for Discord bots featuring high performance, customizable designs, and seamless integration.
Downloads
469
Maintainers
Readme
🎧 Musify
Professional Music Image Generator for Discord Bots
Create stunning, high-performance music cards with elegant glass design and automatic color extraction
👀 Preview
✨ Features
| Feature | Description | |---------|-------------| | 🔎 Liquid Glass Design | Modern, elegant music card with liquid glass effects - soft shadows, subtle strokes, and glass-like progress bars | | 🎯 Smart Color Extraction | HSL-based color calibration that preserves original hues while optimizing brightness for perfect visibility | | 💎 Glass Morphism Effects | Text with liquid glass styling (semi-transparent strokes + soft shadows) for premium readability | | 📊 Enhanced Progress Bar | Glass-effect progress bar with subtle glow, highlights, and perfect alignment with time labels | | 🎨 Adaptive Color Calibration | Intelligently adjusts color brightness while maintaining original color character (orange stays orange!) | | 🪅 Background Effects | Blur, darkness, and overlay controls for stunning visuals | | 📏 Flexible Scaling | Scale from 0.5x to 2x for different use cases | | ⚡ High Performance | Optimized rendering with minimal memory footprint | | 🔧 TypeScript Ready | Full TypeScript definitions and IntelliSense support | | 🎵 Riffy Integration | Perfect compatibility with Riffy music library | | 🖼️ Multiple Formats | Support for URLs, local paths, and buffer inputs | | 📍 Smart Layout | Intelligent progress bar and time label positioning for both left and right thumbnail placements |
🤔 Quick Start
Installation
npm install musifyBasic Usage
import { Glass } from 'musify';
const Musify = await Glass({
thumbnailImage: 'https://example.com/thumbnail.jpg',
name: 'Bohemian Rhapsody',
author: 'Queen',
requester: 'MusicLover#1234',
progress: 45,
startTime: '2:15',
endTime: '5:55'
});Send to Discord Channel
await channel.send({
files: [{
attachment: Musify,
name: 'now-playing.png'
}]
});Generates a professional music card and returns a PNG buffer.
Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| thumbnailImage | string | - | Required: URL or path to thumbnail |
| thumbnail | 'left' \| 'right' | 'left' | Thumbnail position (left or right side) |
| name | string | 'Musify' | Song title (auto-truncated) |
| author | string | 'Unknown Artist' | Artist name |
| requester | string | 'Unknown' | User who requested the song |
| progress | number | 0 | Progress percentage (0-100) |
| startTime | string | '0:00' | Current time (MM:SS) |
| endTime | string | '0:00' | Total duration (MM:SS) |
| scale | number | 1 | Scale factor (0.5-2) |
| backgroundColor | string | '#1c1c1c' | Fallback background color |
| backgroundImage | string | - | Background image URL |
| backgroundBlur | number | 10 | Background blur (0-50) |
| backgroundDarkness | number | 0.9 | Background darkness (0-1) |
| nameColor | string | 'auto' | Title color (auto-extracted with HSL calibration) |
| authorColor | string | '#FFFFFF' | Artist text color |
| requesterColor | string | 'auto' | Requester text color (auto-extracted) |
| progressColor | string | 'auto' | Progress bar color (auto-extracted) |
| timeColor | string | '#FFFFFF' | Time labels color |
| style | 'v1' \| 'v2' | 'v2' | Card style version (v2 recommended) |
🎯 Usage Examples
Auto Color Extraction with Smart Calibration
const Musify = await Glass({
thumbnailImage: track.info.thumbnail,
name: track.info.title,
author: track.info.author,
requester: track.info.requester.username,
progress: 30,
startTime: '1:30',
endTime: '4:15',
// Colors automatically extracted from thumbnail
// Uses HSL-based calibration to preserve original hues
// Orange stays orange, not yellow! Perfect brightness for visibility
nameColor: 'auto',
progressColor: 'auto',
requesterColor: 'auto'
});Color Calibration Features:
- ✅ Preserves original color hue and saturation
- ✅ Adaptive brightness adjustment (not too bright, not too dark)
- ✅ Maintains color character (orange stays orange, blue stays blue)
- ✅ Optimized for dark backgrounds with perfect visibility
Custom Styling
const Musify = await Glass({
thumbnailImage: 'https://example.com/thumbnail.jpg',
name: 'Custom Styled Track',
author: 'Custom Artist',
requester: 'StylishUser#5678',
progress: 75,
startTime: '3:20',
endTime: '4:30',
scale: 1.2,
backgroundColor: '#2a2a2a',
nameColor: '#FF6B35',
authorColor: '#E8E8E8',
requesterColor: '#FF6B35',
progressColor: '#FF6B35',
timeColor: '#CCCCCC'
});Background Effects
const Musify = await Glass({
thumbnailImage: track.info.thumbnail,
backgroundImage: track.info.thumbnail, // Use same image as background
backgroundBlur: 20, // Strong blur effect
backgroundDarkness: 0.7, // Moderate darkness
name: track.info.title,
author: track.info.author,
requester: track.info.requester.username,
progress: 50,
startTime: '2:45',
endTime: '5:30'
});💎 Visual Enhancements
Liquid Glass Effect
Musify features a premium liquid glass design with:
Text Styling: All text elements (title, author, requester, time labels) feature:
- Semi-transparent dark strokes for depth
- Soft shadows for readability
- Perfect contrast on any background
Progress Bar: Enhanced with glass morphism:
- Subtle glow effect matching the progress color
- White highlight overlay for glass-like surface
- Semi-transparent background with glass effect
- Perfect alignment with time labels
Smart Positioning:
- Progress bar and time labels automatically adjust when thumbnail is on the right
- No overlaps, perfect spacing
- Time labels centered vertically with progress bar
Thumbnail Positioning
const Musify = await Glass({
thumbnailImage: track.info.thumbnail,
thumbnail: 'right', // or 'left' (default)
name: track.info.title,
author: track.info.author,
requester: track.info.requester.username,
progress: 50,
startTime: '2:30',
endTime: '5:00'
});The layout automatically adjusts:
- Text positioning based on thumbnail side
- Progress bar width and position
- Time label alignment
- All elements perfectly spaced
🎵 Riffy Integration
Perfect integration with Riffy music library:
import { Glass } from 'musify';
// Track start event
client.riffy.on('trackStart', async (player, track) => {
const Musify = await Glass({
thumbnailImage: track.info.thumbnail,
name: track.info.title,
author: track.info.author,
requester: track.info.requester.username,
progress: 0,
startTime: '0:00',
endTime: formatTime(track.info.length),
scale: 1.1
});
// Send to Discord
await player.textChannel.send({
files: [{ attachment: Musify, name: 'now-playing.png' }]
});
});
// Progress updates
setInterval(async () => {
if (player.current && player.playing) {
const progress = (player.position / player.current.info.length) * 100;
const startTime = formatTime(player.position);
const endTime = formatTime(player.current.info.length);
const Musify = await Glass({
thumbnailImage: player.current.info.thumbnail,
name: player.current.info.title,
author: player.current.info.author,
requester: player.current.info.requester.username,
progress,
startTime,
endTime,
scale: 1.1
});
// Update message
await message.edit({ files: [{ attachment: Musify, name: 'now-playing.png' }] });
}
}, 5000); // Update every 5 seconds
function formatTime(ms: number): string {
const minutes = Math.floor(ms / 60000);
const seconds = Math.floor((ms % 60000) / 1000);
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}⚡ Performance Optimization
Reuse Configuration Objects
const baseConfig = {
scale: 1.1,
backgroundColor: '#1c1c1c',
authorColor: '#FFFFFF',
timeColor: '#CCCCCC'
};
// Reuse for different tracks
const Musify1 = await Glass({
...baseConfig,
thumbnailImage: track1.info.thumbnail,
name: track1.info.title,
author: track1.info.author,
progress: 30
});
const Musify2 = await Glass({
...baseConfig,
thumbnailImage: track2.info.thumbnail,
name: track2.info.title,
author: track2.info.author,
progress: 60
});Cache Generated Cards
const cardCache = new Map();
async function getCachedCard(trackId: string, progress: number) {
const cacheKey = `${trackId}-${Math.floor(progress / 10)}`; // Cache by 10% intervals
if (cardCache.has(cacheKey)) {
return cardCache.get(cacheKey);
}
const Musify = await Glass(options);
cardCache.set(cacheKey, Musify);
// Limit cache size
if (cardCache.size > 100) {
const firstKey = cardCache.keys().next().value;
cardCache.delete(firstKey);
}
return Musify;
}