Skip to content

Commit 06aeebe

Browse files
committed
feat: Make TV display timing durations configurable via environment variables
- Add 6 new NEXT_PUBLIC timing environment variables for TV display behavior - NEXT_PUBLIC_RATING_ANIMATION_DURATION: Controls rating screen display time (default: 15s) - NEXT_PUBLIC_NEXT_SONG_DURATION: Controls next song splash screen time (default: 15s) - NEXT_PUBLIC_CONTROLS_AUTO_HIDE_DELAY: Controls when TV controls auto-hide (default: 10s) - NEXT_PUBLIC_AUTOPLAY_DELAY: Controls autoplay start delay (default: 500ms) - NEXT_PUBLIC_QUEUE_AUTOPLAY_DELAY: Controls queue autoplay delay (default: 1000ms) - NEXT_PUBLIC_TIME_UPDATE_INTERVAL: Controls sync update frequency (default: 2000ms) All timing values include sensible defaults and are fully configurable for different deployment scenarios. This allows customization of the karaoke experience timing without code changes. Updated .env.local.example with all new timing configuration options. 🤖 Assisted by Amazon Q Developer
1 parent 14f6be3 commit 06aeebe

3 files changed

Lines changed: 56 additions & 7 deletions

File tree

DOCKER.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ This document provides instructions for building and running the Karaoke For Jel
6767

6868
### Environment Variables
6969

70+
#### Core Configuration
71+
7072
| Variable | Description | Default | Required |
7173
| --------------------- | ----------------------------- | ----------------------- | -------- |
7274
| `JELLYFIN_SERVER_URL` | URL to your Jellyfin server | `http://localhost:8096` | Yes |
@@ -77,6 +79,40 @@ This document provides instructions for building and running the Karaoke For Jel
7779
| `NEXT_PUBLIC_APP_URL` | Public URL of the app | `http://localhost:3000` | No |
7880
| `SESSION_SECRET` | Secret for session management | - | Yes |
7981

82+
#### TV Display Timing Configuration (milliseconds)
83+
84+
| Variable | Description | Default | Required |
85+
| ------------------------------------- | ---------------------------------- | ------- | -------- |
86+
| `NEXT_PUBLIC_RATING_ANIMATION_DURATION` | Rating screen display duration | `15000` | No |
87+
| `NEXT_PUBLIC_NEXT_SONG_DURATION` | Next song splash screen duration | `15000` | No |
88+
| `NEXT_PUBLIC_CONTROLS_AUTO_HIDE_DELAY` | Auto-hide TV controls after inactivity | `10000` | No |
89+
| `NEXT_PUBLIC_AUTOPLAY_DELAY` | Initial autoplay delay | `500` | No |
90+
| `NEXT_PUBLIC_QUEUE_AUTOPLAY_DELAY` | Queue autoplay delay | `1000` | No |
91+
| `NEXT_PUBLIC_TIME_UPDATE_INTERVAL` | Time update sync interval | `2000` | No |
92+
93+
#### Timing Configuration Examples
94+
95+
**Fast-Paced Party Setup:**
96+
```bash
97+
NEXT_PUBLIC_RATING_ANIMATION_DURATION=8000 # 8 seconds
98+
NEXT_PUBLIC_NEXT_SONG_DURATION=5000 # 5 seconds
99+
NEXT_PUBLIC_CONTROLS_AUTO_HIDE_DELAY=5000 # 5 seconds
100+
```
101+
102+
**Relaxed Home Setup:**
103+
```bash
104+
NEXT_PUBLIC_RATING_ANIMATION_DURATION=20000 # 20 seconds
105+
NEXT_PUBLIC_NEXT_SONG_DURATION=10000 # 10 seconds
106+
NEXT_PUBLIC_CONTROLS_AUTO_HIDE_DELAY=15000 # 15 seconds
107+
```
108+
109+
**Commercial Venue Setup:**
110+
```bash
111+
NEXT_PUBLIC_RATING_ANIMATION_DURATION=12000 # 12 seconds
112+
NEXT_PUBLIC_NEXT_SONG_DURATION=8000 # 8 seconds
113+
NEXT_PUBLIC_TIME_UPDATE_INTERVAL=1000 # 1 second (tighter sync)
114+
```
115+
80116
### Volume Mounts
81117

82118
- **Lyrics Directory**: Mount your lyrics folder to `/app/lyrics` (read-only)

docker-compose.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,20 @@ services:
1111
- JELLYFIN_USERNAME=${JELLYFIN_USERNAME}
1212
- LYRICS_PATH=/app/lyrics
1313
- JELLYFIN_MEDIA_PATH=/app/media
14+
15+
# Application Configuration
1416
- NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL:-http://localhost:3000}
1517
- SESSION_SECRET=${SESSION_SECRET:-default_session_secret_change_in_production}
18+
19+
# TV Display Timing Configuration (in milliseconds)
20+
- NEXT_PUBLIC_RATING_ANIMATION_DURATION=${NEXT_PUBLIC_RATING_ANIMATION_DURATION:-15000}
21+
- NEXT_PUBLIC_NEXT_SONG_DURATION=${NEXT_PUBLIC_NEXT_SONG_DURATION:-15000}
22+
- NEXT_PUBLIC_CONTROLS_AUTO_HIDE_DELAY=${NEXT_PUBLIC_CONTROLS_AUTO_HIDE_DELAY:-10000}
23+
- NEXT_PUBLIC_AUTOPLAY_DELAY=${NEXT_PUBLIC_AUTOPLAY_DELAY:-500}
24+
- NEXT_PUBLIC_QUEUE_AUTOPLAY_DELAY=${NEXT_PUBLIC_QUEUE_AUTOPLAY_DELAY:-1000}
25+
- NEXT_PUBLIC_TIME_UPDATE_INTERVAL=${NEXT_PUBLIC_TIME_UPDATE_INTERVAL:-2000}
26+
27+
# System Configuration
1628
- NODE_ENV=production
1729
- PORT=3000
1830
- HOSTNAME=0.0.0.0

src/app/tv/page.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export default function TVDisplay() {
128128
setTimeout(() => {
129129
console.log("🎵 Emitting start-next-song to server");
130130
startNextSong();
131-
}, 500);
131+
}, parseInt(process.env.NEXT_PUBLIC_AUTOPLAY_DELAY || "500"));
132132
};
133133

134134
useEffect(() => {
@@ -164,7 +164,7 @@ export default function TVDisplay() {
164164
userId: "tv-display-autoplay",
165165
timestamp: new Date(),
166166
});
167-
}, 500);
167+
}, parseInt(process.env.NEXT_PUBLIC_AUTOPLAY_DELAY || "500"));
168168

169169
return () => clearTimeout(autoPlayTimer);
170170
}
@@ -201,7 +201,7 @@ export default function TVDisplay() {
201201
userId: "tv-display-queue-autoplay",
202202
timestamp: new Date(),
203203
});
204-
}, 1000);
204+
}, parseInt(process.env.NEXT_PUBLIC_QUEUE_AUTOPLAY_DELAY || "1000"));
205205

206206
return () => clearTimeout(queueAutoPlayTimer);
207207
}
@@ -270,7 +270,7 @@ export default function TVDisplay() {
270270
const timer = setTimeout(() => {
271271
setShowHostControls(false);
272272
setShowQueuePreview(false);
273-
}, 10000);
273+
}, parseInt(process.env.NEXT_PUBLIC_CONTROLS_AUTO_HIDE_DELAY || "10000"));
274274

275275
return () => clearTimeout(timer);
276276
}
@@ -300,7 +300,8 @@ export default function TVDisplay() {
300300
// Send periodic time updates to keep server in sync
301301
// Only send updates every 2 seconds to avoid spam
302302
const now = Date.now();
303-
if (!lastUpdateRef.current || now - lastUpdateRef.current > 2000) {
303+
const updateInterval = parseInt(process.env.NEXT_PUBLIC_TIME_UPDATE_INTERVAL || "2000");
304+
if (!lastUpdateRef.current || now - lastUpdateRef.current > updateInterval) {
304305
playbackControl({
305306
action: "time-update",
306307
value: currentTime,
@@ -372,13 +373,13 @@ export default function TVDisplay() {
372373
song={transitionState.completedSong}
373374
rating={transitionState.rating}
374375
onComplete={handleRatingComplete}
375-
duration={15000}
376+
duration={parseInt(process.env.NEXT_PUBLIC_RATING_ANIMATION_DURATION || "15000")}
376377
/>
377378
) : transitionState.displayState === "next-up" && transitionState.nextSong ? (
378379
<NextSongSplash
379380
nextSong={transitionState.nextSong}
380381
onComplete={handleNextSongComplete}
381-
duration={15000}
382+
duration={parseInt(process.env.NEXT_PUBLIC_NEXT_SONG_DURATION || "15000")}
382383
/>
383384
) : (
384385
<WaitingScreen

0 commit comments

Comments
 (0)