v1.6.0 — Resilience & Plugins
Queue persistence, WS heartbeats, SponsorBlock + live lyrics integration, player protections, destroy reasons, and link policy.
Released 2026-08-04 · npm install yukumo@1.6.0
The reliability release: dead-connection detection, runaway-player guards, and queues that survive redeploys — plus first-class SponsorBlock and live lyrics.
Added
Queue Persistence
queueOptions.persist auto-saves every queue to the configured StorageAdapter (microtask-coalesced — a 500-track playlist add is one write) and restores it on createPlayer(). Persisted queues are kept on shutdown (DisconnectAllNodes) and deleted on normal destroys. New Player.enableQueuePersistence() / Player.restoreQueue() and a Queue.onChanged mutation hook.
WebSocket Heartbeat
Ping/pong dead-connection detection per node (enableHeartbeat, heartbeatIntervalMs = 30000, heartbeatTimeoutMs = 10000). Half-open sockets are terminated and reconnect automatically; new ws.isAlive getter.
SponsorBlock Plugin Integration
player.setSponsorBlock(categories) / getSponsorBlock() / deleteSponsorBlock() plus segmentsLoaded, segmentSkipped, chaptersLoaded, chapterStarted events — server-side auto-skip via the Lavalink SponsorBlock plugin.
Live Lyrics (LavaLyrics)
player.getCurrentLyrics(), subscribeLyrics(), unsubscribeLyrics() plus lyricsFound, lyricsNotFound, lyricsLine events — timestamped lyric lines streamed as the track plays.
Player & Manager API
- Play options —
play()/playTrack()accept{ position, endTime, noReplace, paused, volume }. - Player protections (defaults via
ManagerOptions.playerDefaults) —maxErrorsPerTimesliding-window error-rate destroy ({ threshold: 35000, maxAmount: 3 }),minAutoPlayMsautoplay error-spam guard (10000ms),queueEmptyDestroyMsdestroy-after-queue-end timer. - Destroy reasons —
DestroyReasonsenum;destroy(reason)everywhere;playerDestroynow emits(guildId, reason). - Link policy —
linksAllowed,linksWhitelist,linksBlacklist(substring or RegExp) gate URL queries insearch(). - Custom HTTP headers —
ManagerOptions.httpHeaders(global) andNodeConfig.httpHeaders(per node) on REST + WS handshake. - Player —
toJSON()full snapshot,pinggetter{ ws, lavalink },moveNode(nodeId?)least-loaded auto-pick. - Queue —
sortBy("duration" | "title" | "author" | comparator, order),removeTrack(track | tracks | predicate). - Filters —
setAudioOutput("mono" | "stereo" | "left" | "right")channel-mix presets (AudioOutputsexport). - Custom Player class —
ManagerOptions.playerClass. - Utils —
parseLavalinkConnUrl("lavalink://name:pass@host:port").
Fixed
- Player leak: direct
player.destroy()(auto-disconnect, channel delete) now unregisters fromPlayerManagerand decrementsnode.playerCount. - Race: track-end handling (natural end / stuck / skip) is serialized — no more double queue-advances.
positioninterpolates betweenplayerUpdateframes (clamped to track length) instead of being up to ~5s stale;seek()clamps to[0, length].resume()on an idle player no longer fakes"playing";pause()/resume()are idempotent.setVolume()is remembered while the node session is down and applied on next play.skip()with nothing playing no longer crashes the autoplay path.- Empty-VC and queue-empty timers are
unref()ed — they no longer keep the process alive.