444 lines
12 KiB
Markdown
444 lines
12 KiB
Markdown
# Radio DJ Now Playing Widget
|
||
|
||
A professional music widget perfect for streamers and broadcasters. Display the currently playing song with a beautiful blurred album art background, crystal-clear track information, and automatic refresh every 6 seconds.
|
||
|
||
**Perfect for**: OBS streams, web overlays, Radio station websites, Music player displays
|
||
|
||
## Quick Start
|
||
|
||
1. Place these files in `/new-make-rdj/` directory
|
||
2. Create three files in the same directory:
|
||
- `artist.txt` - Contains artist name
|
||
- `title.txt` - Contains song title
|
||
- `Album-Art.png` - Album artwork (square image recommended)
|
||
3. Use in OBS Browser Source or open `index.html` in a local server
|
||
|
||
## Core Features
|
||
|
||
✨ **Beautiful Design**
|
||
- Dark rounded-corner container (border-radius: 20px)
|
||
- Heavy blur effect on album artwork (blur 40px + 60% brightness)
|
||
- Large, bold typography (30px title, 22px artist)
|
||
- Strong text-shadow for readability: `2px 2px 5px rgba(0,0,0,0.9)`
|
||
|
||
🔄 **Smart Refresh Engine**
|
||
- Polls `artist.txt` and `title.txt` every 6 seconds (default)
|
||
- Only updates display when content actually changes
|
||
- Automatic cache-busting with timestamps (`?v=` parameter)
|
||
|
||
⚙️ **Flexible Configuration**
|
||
- Override refresh rate via URL parameter: `?refreshrate=10`
|
||
- Easy font size customization in CSS
|
||
- Simple image filename change in JavaScript
|
||
|
||
## File Requirements
|
||
|
||
### Required Files in `/new-make-rdj/` directory:
|
||
|
||
| File | Purpose | Format |
|
||
|------|---------|--------|
|
||
| `artist.txt` | Current artist name | Plain text, single line |
|
||
| `title.txt` | Current song title | Plain text, single line |
|
||
| `Album-Art.png` | Album artwork | Image (PNG recommended) |
|
||
|
||
### Example Files:
|
||
|
||
**artist.txt:**
|
||
```
|
||
The Weeknd
|
||
```
|
||
|
||
**title.txt:**
|
||
```
|
||
Blinding Lights
|
||
```
|
||
|
||
**Album-Art.png**
|
||
- Should be square (e.g., 500×500px, 1000×1000px)
|
||
- PNG format recommended for transparency support
|
||
- Updated by your backend whenever the track changes
|
||
|
||
## Usage
|
||
|
||
### Basic Usage
|
||
|
||
Open in a browser that supports local file access (requires Live Server extension) or place behind a web server:
|
||
|
||
```
|
||
http://localhost/new-make-rdj/index.html
|
||
```
|
||
|
||
**NOTE**: Due to browser security (CORS), you cannot directly open the HTML file with `file://` protocol. You must use:
|
||
- **VS Code Live Server extension** (recommended)
|
||
- Python: `python -m http.server 8000`
|
||
- Node.js: `npx http-server`
|
||
- OBS Browser Source (has built-in local access)
|
||
|
||
### Custom Refresh Rate
|
||
|
||
Override the default 6-second refresh rate:
|
||
|
||
```
|
||
http://localhost/new-make-rdj/index.html?refreshrate=10
|
||
```
|
||
|
||
Examples:
|
||
- `?refreshrate=3` - Check every 3 seconds (more responsive, more network load)
|
||
- `?refreshrate=6` - Default (balanced)
|
||
- `?refreshrate=15` - Check every 15 seconds (less network load)
|
||
|
||
### OBS Integration
|
||
|
||
1. **Create Browser Source** in OBS
|
||
2. **Set URL:**
|
||
```
|
||
http://localhost/new-make-rdj/index.html
|
||
```
|
||
Or with custom refresh rate:
|
||
```
|
||
http://localhost/new-make-rdj/index.html?refreshrate=6
|
||
```
|
||
3. **Set Canvas Size:** 650×200 pixels (or larger, widget will scale)
|
||
4. **Enable Refresh:** Ensure "Refresh browser when scene becomes active" is checked
|
||
5. Done! The widget updates automatically
|
||
|
||
## Customization Guide
|
||
|
||
### Changing Title Font Size
|
||
|
||
Edit `style.css` and find this section:
|
||
|
||
```css
|
||
/* Song title */
|
||
.song-title {
|
||
font-size: 30px; /* ← Change this value */
|
||
font-weight: 700;
|
||
color: #ffffff;
|
||
text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.9);
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
letter-spacing: -0.5px;
|
||
line-height: 1.1;
|
||
}
|
||
```
|
||
|
||
**Tips:**
|
||
- Reduce to 24px-26px for more character room
|
||
- Increase to 32px-36px for larger screens
|
||
- Test with your longest song titles
|
||
|
||
### Changing Artist Font Size
|
||
|
||
Edit `style.css` and find this section:
|
||
|
||
```css
|
||
/* Song artist */
|
||
.song-artist {
|
||
font-size: 22px; /* ← Change this value */
|
||
font-weight: 500;
|
||
color: #ffffff;
|
||
text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.9);
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
letter-spacing: -0.3px;
|
||
line-height: 1.1;
|
||
opacity: 1;
|
||
}
|
||
```
|
||
|
||
**Tips:**
|
||
- Keep it 5-8px smaller than title for visual hierarchy
|
||
- Recommended range: 16px-24px
|
||
- Test with your longest artist names
|
||
|
||
### Changing Image Filename
|
||
|
||
If your backend uses a different filename (e.g., `cover.jpg` instead of `Album-Art.png`):
|
||
|
||
1. Open `script.js`
|
||
2. Find this line near the top (around line 9):
|
||
```javascript
|
||
const IMAGE_FILENAME = "Album-Art.png";
|
||
```
|
||
3. Change it to your filename:
|
||
```javascript
|
||
const IMAGE_FILENAME = "cover.jpg";
|
||
```
|
||
4. Save the file
|
||
|
||
**Supported formats:**
|
||
- PNG (recommended)
|
||
- JPG/JPEG
|
||
- WebP
|
||
- GIF
|
||
|
||
The cache-busting mechanism (`?v=timestamp`) works with any format.
|
||
|
||
### Other Customizations
|
||
|
||
#### Blur Strength
|
||
Edit in `style.css`, `.background-image` section:
|
||
```css
|
||
filter: blur(40px) brightness(0.6); /* Change 40px to adjust blur */
|
||
```
|
||
- Increase blur value (e.g., 50px) for more blur
|
||
- Decrease blur value (e.g., 30px) for less blur
|
||
- Adjust brightness (0.6 = 60% intensity) from 0.3 to 0.8
|
||
|
||
#### Container Padding and Spacing
|
||
Edit in `style.css`, `.widget-content` section:
|
||
```css
|
||
gap: 24px; /* Space between album art and text */
|
||
padding: 20px; /* Space inside container around all edges */
|
||
```
|
||
|
||
#### Text Shadow Intensity
|
||
Edit in `style.css`, both `.song-title` and `.song-artist`:
|
||
```css
|
||
text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.9);
|
||
/* ↑ x-offset ↑ y-offset ↑ blur-radius ↑ color + opacity */
|
||
```
|
||
- More blur = softer shadow (e.g., 8px)
|
||
- Less blur = harder shadow (e.g., 3px)
|
||
- Change opacity (0.9 = 90%) for more/less darkness
|
||
|
||
## How It Works
|
||
|
||
### Refresh Cycle (every 6 seconds or custom interval)
|
||
|
||
1. **Fetch**: Requests `artist.txt` and `title.txt` from the server
|
||
2. **Compare**: Checks if content differs from current display
|
||
3. **Update**: Only refreshes DOM if content changed
|
||
4. **Cache Bust**: Appends timestamp to image URL when track changes
|
||
- Example: `Album-Art.png?v=1711701234567`
|
||
5. **Display**: Updates artist and title on-screen
|
||
|
||
### Why Cache Busting?
|
||
|
||
OBS (and browsers) cache images by filename. Without cache busting:
|
||
- The old album art would display for 5-10 seconds
|
||
- User would see wrong artwork until cache expired
|
||
|
||
By appending `?v=` with a timestamp:
|
||
- Each request looks "new" to cached systems
|
||
- Forces reload of latest artwork
|
||
- Works immediately in OBS without manual clearing
|
||
|
||
### Auto-Image Update on Track Change
|
||
|
||
The widget is smart about image updates:
|
||
- **Only updates images when track changes** (not on every poll)
|
||
- Detects change when artist OR title changes
|
||
- Prevents unnecessary re-fetches when nothing changed
|
||
- Significantly reduces network traffic
|
||
|
||
## Technical Requirements
|
||
|
||
### Browser Compatibility
|
||
- Chrome/Chromium ✅
|
||
- Firefox ✅
|
||
- Safari ✅
|
||
- OBS Browser Source ✅
|
||
|
||
### Local File Access
|
||
⚠️ **IMPORTANT:** Due to browser security (CORS), local HTML files need a server.
|
||
|
||
**Setup Options:**
|
||
|
||
1. **VS Code Live Server** (Recommended)
|
||
- Install "Live Server" extension in VS Code
|
||
- Right-click `index.html` → "Open with Live Server"
|
||
|
||
2. **Python** (Built-in on most systems)
|
||
```bash
|
||
python -m http.server 8000
|
||
# Then open: http://localhost:8000/new-make-rdj/index.html
|
||
```
|
||
|
||
3. **Node.js**
|
||
```bash
|
||
npx http-server
|
||
# Then open: http://localhost:8080/new-make-rdj/index.html
|
||
```
|
||
|
||
4. **OBS Browser Source**
|
||
- OBS has built-in local file access
|
||
- Use: `http://localhost/new-make-rdj/index.html`
|
||
|
||
## Backend Integration
|
||
|
||
For your backend service to work with the widget, it should:
|
||
|
||
1. **Monitor** your music source (local player, streaming API, etc.)
|
||
2. **Update** these three files in the `/new-make-rdj/` directory:
|
||
- `artist.txt` → Current artist
|
||
- `title.txt` → Current title
|
||
- `Album-Art.png` → Current album artwork
|
||
3. **Write atomically** (avoid partial updates) for reliability
|
||
4. **Update image file** to ensure cache-busting works
|
||
|
||
Example backend update (Python):
|
||
```python
|
||
import shutil
|
||
from pathlib import Path
|
||
|
||
def update_now_playing(artist, title, artwork_path):
|
||
# Write text files
|
||
Path("artist.txt").write_text(artist)
|
||
Path("title.txt").write_text(title)
|
||
|
||
# Copy artwork (forces new file timestamp)
|
||
shutil.copy2(artwork_path, "Album-Art.png")
|
||
|
||
print(f"Updated: {artist} - {title}")
|
||
```
|
||
|
||
Example (Node.js):
|
||
```javascript
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
function updateNowPlaying(artist, title, artworkPath) {
|
||
fs.writeFileSync('artist.txt', artist);
|
||
fs.writeFileSync('title.txt', title);
|
||
fs.copyFileSync(artworkPath, 'Album-Art.png');
|
||
console.log(`Updated: ${artist} - ${title}`);
|
||
}
|
||
```
|
||
|
||
## Troubleshooting
|
||
|
||
### "Loading..." displays indefinitely
|
||
|
||
**Possible causes:**
|
||
- Files not in the correct directory
|
||
- Browser can't access local files (need Live Server)
|
||
- Filename typo (case-sensitive on Linux/Mac)
|
||
|
||
**Solutions:**
|
||
1. Verify files exist in `/new-make-rdj/`:
|
||
- `artist.txt`, `title.txt`, `Album-Art.png`
|
||
2. Check browser console (F12) for errors:
|
||
- Look for CORS, 404, or network errors
|
||
3. Set up a local server (Live Server, Python, etc.)
|
||
|
||
### Text is hard to read or washed out
|
||
|
||
**Possible causes:**
|
||
- Album artwork is too bright
|
||
- Text shadow isn't rendering properly
|
||
- Dark overlay isn't dark enough
|
||
|
||
**Solutions:**
|
||
1. Increase background darkness:
|
||
```css
|
||
filter: blur(40px) brightness(0.5); /* Reduce brightness */
|
||
```
|
||
2. Increase text shadow:
|
||
```css
|
||
text-shadow: 3px 3px 8px rgba(0, 0, 0, 1); /* Darker/bigger shadow */
|
||
```
|
||
3. Verify CSS file is loaded (check DevTools → Styles)
|
||
4. Try with a different album artwork image
|
||
|
||
### Album art not updating in OBS
|
||
|
||
**Possible causes:**
|
||
- OBS cache not being bypassed
|
||
- Image file permissions issue
|
||
- Backend not updating files correctly
|
||
|
||
**Solutions:**
|
||
1. Refresh the browser source:
|
||
- Right-click browser source → Refresh
|
||
2. Restart OBS completely
|
||
3. Verify backend is actually updating the image file
|
||
4. Check file permissions are readable
|
||
5. Check browser console (F12) for fetch errors
|
||
|
||
### Widget appears too small or too large
|
||
|
||
**Possible causes:**
|
||
- OBS canvas size too small
|
||
- Browser zoom level incorrect
|
||
- CSS container size needs adjustment
|
||
|
||
**Solutions:**
|
||
1. Increase OBS canvas size:
|
||
- Recommended minimum: 650×200px
|
||
- Recommended ideal: 800×240px or larger
|
||
2. Check browser zoom (should be 100%)
|
||
3. Adjust container max-width in CSS:
|
||
```css
|
||
.widget-container {
|
||
max-width: 650px; /* ← Increase this, e.g., to 800px */
|
||
}
|
||
```
|
||
|
||
### Video keeps buffering when opening HTML directly
|
||
|
||
This is the CORS security issue. You MUST use a local server. See "Local File Access" section above.
|
||
|
||
## Design Specifications
|
||
|
||
### Current Settings
|
||
|
||
```css
|
||
/* Container */
|
||
border-radius: 20px;
|
||
max-width: 650px;
|
||
height: 200px;
|
||
|
||
/* Background Blur */
|
||
filter: blur(40px) brightness(0.6);
|
||
|
||
/* Album Art */
|
||
width: 140px;
|
||
height: 140px;
|
||
|
||
/* Title Text */
|
||
font-size: 30px;
|
||
font-weight: 700;
|
||
text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.9);
|
||
|
||
/* Artist Text */
|
||
font-size: 22px;
|
||
font-weight: 500;
|
||
text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.9);
|
||
```
|
||
|
||
## Configuration Summary
|
||
|
||
| Setting | Location | Default | How to Change |
|
||
|---------|----------|---------|---------------|
|
||
| **Refresh Rate** | URL | 6 seconds | `?refreshrate=X` |
|
||
| **Title Size** | `style.css` | 30px | `.song-title { font-size: __ }` |
|
||
| **Artist Size** | `style.css` | 22px | `.song-artist { font-size: __ }` |
|
||
| **Image Filename** | `script.js` | Album-Art.png | `const IMAGE_FILENAME = "..."` |
|
||
| **Blur Intensity** | `style.css` | 40px | `.background-image { filter: blur(__px) }` |
|
||
| **Container Width** | `style.css` | 650px | `.widget-container { max-width: __ }` |
|
||
| **Container Height** | `style.css` | 200px | `.widget-container { height: __ }` |
|
||
|
||
## File Reference
|
||
|
||
- **index.html** - Main HTML structure (semantic class-based design)
|
||
- **style.css** - Complete styling, layout, animations, and design
|
||
- **script.js** - Polling logic, cache-busting, DOM updates
|
||
- **README.md** - This documentation
|
||
|
||
## Support
|
||
|
||
**Questions or issues?**
|
||
|
||
1. Check the Troubleshooting section
|
||
2. Verify all three required files exist in `/new-make-rdj/`
|
||
3. Ensure you're using a local server (not `file://` protocol)
|
||
4. Check browser console (F12) for error messages
|
||
5. Verify backend is updating text files correctly
|
||
|
||
---
|
||
|
||
**Tested with**: OBS 28+, Chrome 120+, Firefox 121+, Safari 16+
|