Repository navigation
Helloooooooooooo WOoooorld
💚 NodeLink v3.9.0
so uh
this one got really big
NodeLink v3.9.0 is finally here, and there are 182 commits between v3.8.0 and v3.9.0. This release ended up touching pretty much every major part of NodeLink, from startup and networking to DSP, memory management, source resolution, voice, clustering, security, configuration, and the internal architecture
There is honestly a lot to talk about here, so instead of just saying that "a bunch of stuff was fixed", here is what actually changed
Startup
One of the first things we wanted to improve was startup time. NodeLink could take around 10 seconds to cold start depending on the environment, and a big part of that was the tsx layer used to execute TypeScript
That layer is now gone
NodeLink now uses native TypeScript execution from Node.js, with support across modern Node.js versions from v22.x through v26.x
The result is a cold start that can now go from around 10 seconds to under 1 second
That is a pretty massive difference for something that can be restarted frequently, especially when running multiple workers or recovering nodes. It also means NodeLink spends considerably less time just getting itself ready before it can actually serve requests
Bun
Bun also became a much bigger part of NodeLink in this release
useBunServer: true is now the default, and instead of treating Bun as just another runtime NodeLink can run on, we are making much better use of its native HTTP and WebSocket implementations
The request shims were improved as well, along with native fetch fast paths and several changes intended to reduce unnecessary allocations and networking overhead
There were also multiple fixes around Bun HTTP, fetch behavior, request shims, dependency updates, and the server structure itself
The goal here was not just "NodeLink works with Bun"
The goal was making Bun a proper first-class server path
Audio processing
This is probably where v3.9.0 got a little out of hand
We started with the base crossfade implementation and kept building on top of it until it turned into the Smart Crossfade Engine
Instead of simply fading one track out while fading another in, NodeLink can now analyze the tracks before a transition happens
It can look at BPM, harmonic key compatibility, the Camelot Wheel, and energy envelopes to determine how a transition should behave
That means the transition is no longer just based on time
It can actually take the music into account
Bass swap
One of the biggest parts of the transition system is the asymmetric multi-band bass-swap crossover
The problem with simply overlapping two tracks is that both tracks usually have their own kick, bass, and low-end energy. During a transition, those frequencies can stack together and make the result sound muddy very quickly
The bass-swap system allows NodeLink to handle the low-end differently during the transition so the outgoing and incoming tracks are not simply fighting over the same frequencies
The goal is keeping the transition powerful without turning the low end into a mess
Vocal anti-clash
There is also progressive vocal anti-clash ducking
Two songs can be harmonically compatible and still sound terrible when both vocal sections are playing at full strength at the same time
NodeLink can progressively reduce conflicting vocal content so one vocal section has room for the other instead of both competing for the same space
This is one of those features that sounds simple when written down, but becomes considerably more complicated once it has to happen continuously while the audio is being processed
Mid/Side spatial morphing
The transition system also makes use of Mid/Side processing for spatial movement
Instead of only changing volume, the stereo field can evolve as the transition progresses
This gives transitions considerably more movement and allows the sound stage to change instead of staying completely static
There are also several effects that can be combined with these transitions, including Schroeder reverb tails, vinyl tape stops, and spinbacks
And then there is Tesseract 4D
The Tesseract filter uses a 4D hypercube rotation approach for spatial DSP, which is probably one of the stranger things currently living inside NodeLink
Voice activated ducking
We also added the new DuckingController
NodeLink can now react to voice activity in Discord voice channels and smoothly lower the music while someone is speaking
When the speech stops, the music can return naturally
This means the system is not just applying a fixed volume reduction. It can react to actual voice activity and dynamically make room for speech
Equalizer performance
The Equalizer also received a pretty important optimization
There is no real reason to spend CPU processing a biquad filter when the filter is effectively doing nothing
Inactive unity-gain filters can now be bypassed completely
That means NodeLink can skip those filters instead of processing them on every audio chunk
The result was up to 56% lower chunk processing time in the tested path, while saving around 5.2ms of CPU core time per second per player
That gets especially interesting when you have many players running simultaneously
One small optimization repeated across many audio frames and many players stops being small very quickly
Memory usage
Memory was another huge focus of this release
The old Opus pipeline relied on a 512KB circular ring buffer, which has now been replaced by a zero-copy leftover frame strategy
The BufferPool bucket depth was also increased from 4 to 16
Together, those changes reached around 97% buffer reuse and reclaimed roughly 200–400MB of RAM in the tested workloads
The changes were not limited to Opus either
Scratch and tape buffers now use lazy allocation, AAC and WebM demuxer caches were tightened, finished filters and mixers are torn down immediately, and MLS key packages are also cleaned up as soon as they are no longer needed
One of the more interesting measurements came from JSArrayBufferData
With 19 active players, retained memory dropped from around 146MB to 19.5MB
That is a pretty huge difference, especially on smaller servers where memory usage matters a lot
NativeDOM
We also completely removed jsdom
It was previously used for the DOM environment required by the YouTube PoToken generation path
Instead of carrying a complete DOM implementation just for that, NodeLink now has its own lightweight NativeDOM
That removes roughly 20MB from node_modules, while also reducing CPU and memory overhead during PoToken generation and SABR streaming
The implementation is specifically designed around what NodeLink actually needs rather than trying to emulate an entire browser DOM
YouTube
YouTube streaming received another major overhaul
The stream handling is now based around bounded HTTP 206 chunking using roughly 12-second / 512KB slices
The idea is to behave more like direct browser media requests and avoid keeping large or fragile ranges open for too long
This helps with connection timeouts and also reduces a number of 416 range failures
We also added more client fallback options, including visionOs and tv_downgraded, giving NodeLink additional ways to deal with aggressive 403 and 429 responses
There were also several changes around visitorData, including fetching, initialization, fallback behavior, and the removal of problematic global caching
The player-side fallback path was improved for watch pages returning 429, and YouTube recovery and itag fallback received another pass
Basically, YouTube will keep changing things, so NodeLink needs to be able to survive those changes without the entire playback pipeline immediately falling apart
Shazam
Shazam also went through a fairly major change
The old HTML scraping approach was fragile, so resolution was moved toward direct Apple Music API handling
There were still fixes around decoy HTML and commerce fallback handling, but the important part is that resolution is no longer tied to the same fragile website structure
That should make the source considerably more resilient to page changes
More sources
There was a lot of work across sources in general
Bilibili URLs are now supported, TikTok video support was added, Newgrounds gained support and additional 403 fallback handling, Instagram direct audio playback was restored, and Instagram handling was improved for more Unicode characters
SoundCloud gained support for shortened URLs and now respects the configured clientId
Spotify gained playlist and artist searching, its search behavior now respects search.maxResults, and recommendations gained a GraphQL fallback
Deezer albums now return the correct playlist load type and stale Deezer CSRF credentials can be refreshed after failures
YouTube Music fallback resolution was fixed, TTS sources received fixes, and Qobuz support was added to monochrome
There was also a lot of general maintenance across multiple sources that does not fit neatly into a single feature name
Stream lifecycle
One of the recurring themes in this release was lifecycle management
Streams should actually disappear when they are finished, recovery should stop when a player is destroyed, event listeners should not survive the stream they belong to, and mix layers should not keep pipelines alive after teardown
There were fixes specifically targeting crossfade destruction, SABR recovery after player destruction, decoder WASM memory leaks, worker crashes during teardown, and general stream lifecycle handling
These are not always bugs that immediately show themselves
They usually appear later as memory growth, stuck players, unexpected events, or workers that mysteriously stop behaving correctly
Seeking and gapless playback
Seek handling also received several fixes
NodeLink can now reuse a seekable resource instead of unnecessarily refetching it, MP4 decoder sample rate handling was fixed, and gapless playback received fixes for its fading start position
Both the JavaScript and normal paths received the relevant gapless fixes
Track-end fade delays are now recomputed when playback speed changes, and the transition field was correctly forwarded across 12 AnimatableFilter subclasses
All of this becomes increasingly important once playback speed, animated filters, transitions, and crossfades start interacting with each other
SABR
SABR received quite a bit of work as well
Its types were reorganized, playback stability was improved, recovery behavior was fixed, stream drops and decoding failures were addressed, and several cases where recovery could continue after a player had already been destroyed were fixed
YouTube recovery and itag fallback were also improved
The overall goal was making SABR behave more like a controlled streaming pipeline instead of a collection of independent recovery mechanisms
Cluster
Cluster mode received some important architectural changes
Worker identity could become ambiguous in some situations, so NodeLink now uses an explicit IPC event socket HELLO handshake for worker identification
This prevents worker ID collisions and keeps worker and player ownership consistent
Players can also self-heal after voice reconnects, missing cluster players can be restored, and loadchapters received a fix for 500 responses in cluster mode
Update checks were also moved so that certain checks only run in the primary process instead of being repeated by every worker
Voice
Voice handling received a lot of smaller but important fixes
Voice errors can now be deferred in cases where immediately reacting to them could cause bad disconnects
Voice reconnects can recover more reliably, channel_id is passed through voice updates, and the default encryption mode is now aead_xchacha20_poly1305_rtpsize
The encryption implementation is backed by sodium-native, with a reported 300% improvement in packet encryption and decryption throughput
Security
There was also another serious security pass in this release
Local file playback received protection against path traversal, the profiler received symlink escape protection, rate-limit handling was improved, worker eviction issues were addressed, API request body hangs were fixed, and routeplanner sub-routes are now registered correctly
Duplicate stream terminal events are prevented, HEAD request handling received better error management, source proxy options became null-safe, and several fallback paths became safer
These are not necessarily the most visible changes when installing a new version, but they matter considerably more once NodeLink is exposed to real traffic
Configuration
Configuration was reorganized quite a bit
diskCacheEnabled was added, configuration migration and cache management were implemented, the configuration schema was flattened, stricter unknown typing was introduced, runtime validation was synchronized with the new structure, and the default configuration was updated to match it
YouTube visitorData and proxy management also received more robust handling
The overall result is a configuration system that should be easier to maintain and safer to evolve
Dependency updates
The dependency update system also received work
Results can now be persisted in a cache, dependency update checks are rate limited, checks can run synchronously during initialization where necessary, automatic dependency updates and restart handling were improved, and package versions were updated
Bun dependency update support was also added
There were also fixes for package etarget errors and target-version handling during auto-update, including protection against reboot loops caused by targeting the wrong package version
TypeScript and code quality
There was quite a lot of cleanup that probably will not show up in a feature list but makes a difference long term
TypeScript was bumped to version 7, many any usages were replaced with proper types, Biome formatting and checks were expanded, project-wide linting was applied, the architecture was modernized, redundant logic was removed, manual debugging instrumentation was added, and compiled files were updated
The Bun implementation was also refactored into a cleaner structure
This release is not only about adding features
A large part of it was making the code behind those features easier to maintain afterwards
Supported clients
Node.js 26 is now supported
Lavalink.lua was added to the supported clients list
General client compatibility was improved, additional parameters were included for other YouTube clients, and several client-specific fallback paths were added or corrected
Monochrome
Monochrome also received several changes
FLAC can now be preferred, a FLAC seek crash was fixed, Qobuz support was added, and monochrome is disabled by default
There were also several stream lifecycle and compatibility improvements around the system
Documentation and maintenance
There were a few smaller project-level changes too
The README and Dockerfile were updated to reflect the newer behavior, deprecated version information was removed, aesthetic support guidelines were added for multiple Discord links, and Magmastream entries were updated with version information
There were also several merge and synchronization commits keeping the development branches aligned
182 commits later
so yeah
that is basically v3.9.0
what started as another release ended up touching startup, Bun, HTTP, WebSocket, DSP, crossfade, equalizer processing, memory management, Opus, AAC, MP4, WASM, YouTube, SABR, Spotify, Deezer, Shazam, SoundCloud, Instagram, Newgrounds, TikTok, Bilibili, voice, cluster, security, configuration, dependencies, TypeScript, and a lot of internal code
there are still things to improve
there are still bugs somewhere
and there will probably be another weird YouTube problem tomorrow
but v3.9.0 is a pretty big step forward for NodeLink
and after 182 commits I think it is safe to say this one got a little bigger than expected
thanks to everyone who contributed code, reported issues, tested things, opened PRs, reviewed changes, or just kept using NodeLink
now it is finally out
Full Changelog
Commit count in v3.8.0..v3.9.0: 182
Added
• 3d073cd tropadoratomcleon-source: add: missing file
• b6f9d38 ToddyTheNoobDud: add: support for oggopus files
• fd41f1a ToddyTheNoobDud: add: support for bilibili.tv urls
• 0eb335e ToddyTheNoobDud: add: visionOs client support
• c81fa1c 1lucas1apk: add: crossfade (initial base)
• 4f11de9 1lucas1apk: add: diskCacheEnabled option to configuration
• 2ef244b 1lucas1apk: add: sequential player patching for groups
• 63bc0c1 ToddyTheNoobDud: add: new preferredSources option in lyrics
• f72cb09 1lucas1apk: add: tesseract 4d rotation dsp filter
• 8e7f947 ToddyTheNoobDud: add: newgrounds source support
• d74264a 1lucas1apk: add: ducking feature to automatically lower music volume when speaking
• 2fa8dd4 ToddyTheNoobDud: add: tv_downgraded client support
• d59014b ToddyTheNoobDud: add: ALAC codec support
• 37ee917 ToddyTheNoobDud: add: new youtube stream handling; fix: major memory leaks/memory retention
• ba3f366 ToddyTheNoobDud: add: more prefixes support
• 3cd7757 ToddyTheNoobDud: add: node 26 support
• 34daff8 ToddyTheNoobDud: add: tiktok video support
Fixed
• f61237d SreerajSK990: fix: resolve ratelimit, worker eviction, body hang, and path traversal
• e77f2f5 ToddyTheNoobDud: fix: stop worker crash when tearing down mix layers with open pipelines
• 9c6962a SreerajSK990: fix(spotify): add GraphQL fallback for recommendations
• fa0f5ac ToddyTheNoobDud: fix: connecting players being detected as dead
• 82cbda7 Akinori: fix: preserve explicit null endTime through seek pipeline
• 7ea699c ToddyTheNoobDud: fix: restore voice reconnects and self-heal missing cluster players
• 1cbb10e ToddyTheNoobDud: fix: musixmatch econnrefused
• 3294dc5 ToddyTheNoobDud: fix: detach event listeners during stream and crossfade destroy
• a825121 ToddyTheNoobDud: fix: resolve MP4 playback failures and decoder WASM memory leaks
• 3d41ad8 Akinori: fix: recompute trackEnd fade delay for playback speed changes
• 644a2c7 ToddyTheNoobDud: fix: resolve shazam decoy html via commerce fallback
• 032ae2d ToddyTheNoobDud: fix: etarget error on package update
• 5519080 Akinori: fix: apply skipMarginMs in updateSponsorBlock
• 360d574 ToddyTheNoobDud: fix: sabr recovery still happening after player destroy
• 171de77 Akinori: fix: forward transition field in 12 AnimatableFilter subclasses
• 3a81d5c ToddyTheNoobDud: fix: tts sources not working
• e905cf4 ToddyTheNoobDud: fix: player watch page 429s causing the source not to load
• 73dd9c9 ToddyTheNoobDud: fix: http errors 416 during itag switch
• fba3dba Akinori: fix: register routeplanner sub-routes correctly
• 26512a5 Shahbaz !!: fix: prevent duplicate stream terminal events
• d7283e8 Lucas Morais Rodrigues: fix: star history
• f6f526f Lucas Morais Rodrigues: fix. star history
• c0f7a9b Razi: fix: resolve audio stream, demuxer, and source bugs
• 3ed2cbd Shahbaz !!: fix: prevent profiler file symlink escapes
• 8870621 SreerajSK990: fix(youtube): resolve letterboxed hqdefault thumbnails
• d436810 1lucas1apk: fix: target package version on auto-update to prevent reboot loops
• 7693a7e ToddyTheNoobDud: fix: visitorData initializing twice
• dbc0c82 ToddyTheNoobDud: fix: player get and false stuck errors
• 98483b9 ToddyTheNoobDud: fix: android failing to search
• ae6db36 Akinori: fix: use seekable resource for seeks instead of refetching
• c703729 GDjkhp: fix: reset fading start postion for gapless (js)
• 24b417f GDjkhp: fix: reset fading start postion for gapless
• 714bb51 ToddyTheNoobDud: fix: prevent circular source fallback resolution
• 3853f63 ToddyTheNoobDud: fix: merge conflict on lyrics
• 7fee2e9 ToddyTheNoobDud: fix: preferredSources is not iterable
• ac84f69 ToddyTheNoobDud: fix: mp4 decoder sample rate issues
• 86e85be ToddyTheNoobDud: fix: make source proxy options null-safe
• cc09a76 ToddyTheNoobDud: fix: shazam failing to resolve
• f4dc20f ToddyTheNoobDud: fix: 403s errors with TV client
• 8e30535 ToddyTheNoobDud: fix: clamp search maxResults to 50 for Spotify API compatibility
• 9a56ca8 ToddyTheNoobDud: fix: return playlist loadType for deezer albums
• ec5c279 ToddyTheNoobDud: fix: refresh stale Deezer CSRF credentials on failure
• aec6fbc ToddyTheNoobDud: fix: resolve youtube music fallback not working
• 8cd02de rafael: fix(spotify): use search.maxResults configuration for search limit
• 4850878 ToddyTheNoobDud: fix: youtube tracks being stuck on connection reset while paused
• 64266c4 1Lucas1apk: fix: remove global caching of visitorData
• 2d23abf 1Lucas1apk: fix: await update checks to run synchronously during initialization
• 8ee7c94 1Lucas1apk: fix: run update checks only in primary process
• 8e66d29 ToddyTheNoobDud: fix: resolve false stuck track detection on stream end
• c4a2fb1 ToddyTheNoobDud: fix: resolve audio stream drops and decoding failures
• 404c49f 1Lucas1apk: fix: defer voice errors to prevent bad disconnects
• 5ac637f 1Lucas1apk: fix: resolve spotify token 400 error caused by clock drift
• 97976b0 1Lucas1apk: fix: update bandcamp stream parsing and regex to prevent fallback
• acaf1e1 ToddyTheNoobDud: fix: loadchapters 500 in cluster mode
• 799e2c0 Ramkrishna: spelling mistake (#208)
• 2138d35 ToddyTheNoobDud: fix: reduce playback memory retention
• ad56e07 ToddyTheNoobDud: fix: shazam failing to resolve songs
• a1afc01 ToddyTheNoobDud: fix: destroy() has already been called on this instance
• 127a974 ToddyTheNoobDud: fix: implement IPC-based worker ID with event socket hello protocol
• 82168e3 UnschooledGamer: fix: enhance error handling for HEAD requests in HTTP source
• e8cc8a5 ToddyTheNoobDud: fix: resolve 11 incompatibilities between player and performanc/voice
• 5c15b29 1Lucas1apk: fix: improve error handling and logging in YouTube cipher service
• fa09a3b 1Lucas1apk: fix: improve error handling and logging in YouTube cipher service
• 32c142d ToddyTheNoobDud: fix: soundcloud urls with query params failing to match
Updated & Improved
• cdb02c6 Lucas Morais Rodrigues: Merge pull request #217 from PerformanC/dev
• 1fdf387 Lucas Morais Rodrigues: Merge pull request #236 from SreerajSK990/fix/core-stability-and-security
• 36c18c4 ToddyTheNoobDud: improve: skip inactive EQ bands and reuse per-frame audio buffers
• 8a5b237 ToddyTheNoobDud: update: make cors configurable
• fb4aee8 Lucas Morais Rodrigues: Merge pull request #231 from filispeen/v3
• be6a555 Lucas Morais Rodrigues: Merge pull request #234 from SreerajSK990/dev
• 0b580ba Lucas Morais Rodrigues: Merge pull request #233 from tropadoratomcleon-source/dev
• a988c62 Lucas Morais Rodrigues: Merge pull request #232 from Akinori107/dev
• 93907a7 ToddyTheNoobDud: improve: refactor shazam to be api only
• 7af723a filispeen: Add Lavalink.lua to supported clients list
• 2b58752 ToddyTheNoobDud: update: add support for searching playlists/artists on spotify
• ff7cc6c Lucas Morais Rodrigues: Merge pull request #229 from Akinori107/dev
• e273f42 ToddyTheNoobDud: update: add player script fallback on error 429
• 351f5c0 ToddyTheNoobDud: improve: bun http/fetch and request shim fixes
• 0a7428d ToddyTheNoobDud: update: make usebunserver default to true
• 2f4134f Lucas Morais Rodrigues: Merge pull request #228 from Akinori107/dev
• 5d32e08 ToddyTheNoobDud: improve: extract bgchallenges from homepage instead of att/get
• 0345c59 Lucas Morais Rodrigues: Merge pull request #227 from Akinori107/dev
• 6299f08 Lucas Morais Rodrigues: Merge pull request #225 from Akinori107/dev
• a92eb23 Lucas Morais Rodrigues: Merge pull request #224 from shhahbaz/fix/prevent-duplicate-stream-events
• 5ca1aa3 ToddyTheNoobDud: update: switch to another visitor_data endpoint
• 4c02946 ToddyTheNoobDud: improve: add fallback to another client during 403s
• ae60a9b Lucas Morais Rodrigues: Merge pull request #222 from shhahbaz/fix/profiler-symlink-escape
• d2eb2bd Lucas Morais Rodrigues: Merge pull request #223 from knownasrazi/fix/audio-stream-bugs
• 22f3535 ToddyTheNoobDud: update: include params in other clients
• 4374f2c 1lucas1apk: Merge branch 'dev' of https://github.com/PerformanC/NodeLink into dev
• 1f9839a 1lucas1apk: improve: enhance smart crossfade transitions and DSP audio effects
• 624fbff Lucas Morais Rodrigues: Merge pull request #221 from SreerajSK990/dev
• 4bbdf8c SreerajSK990: refactor(youtube): use optional chaining for thumbnails
• b4b0bcc 1lucas1apk: Merge branch 'dev' of https://github.com/PerformanC/NodeLink into dev
• c3108d2 ToddyTheNoobDud: update: add support for soundcloud shorten urls
• a1d43d3 ToddyTheNoobDud: improve: visitorData fetching
• 75aa672 1lucas1apk: improve: add mirrorOfficialAlbums option for youtube
• a5e5121 1lucas1apk: update: compiled files in dist
• ff092d7 1lucas1apk: improve: biome write and check
• d57cdc4 ToddyTheNoobDud: improve: general client compatibility
• d62d5f0 toddynnn: Merge pull request #220 from Akinori107/dev
• 76ea67e Lucas Morais Rodrigues: Merge pull request #219 from GDjkhp/dev
• 7f519a6 Lucas Morais Rodrigues: Merge pull request #218 from tropadoratomcleon-source/dev
• 0c90aa5 Emmanuel Lobo: Merge branch 'v3' into dev
• 09db6e6 =: update: readme & dockerfile to reflect new changes
• e34a371 ToddyTheNoobDud: update: respect configured clientId in soundcloud
• 3273cb3 1lucas1apk: Merge branch 'dev' of https://github.com/PerformanC/NodeLink into dev
• 74e3af2 ToddyTheNoobDud: update: add fallback for 403s in newgrounds
• ae4e0d9 ToddyTheNoobDud: improve: support playlist continuations
• b05b301 ToddyTheNoobDud: improve: general maintaince on some sources
• 1bd2a76 ToddyTheNoobDud: update: add direct insta audio playback again
• 3d821fb ToddyTheNoobDud: update: organize sabr types
• c5a0f8b ToddyTheNoobDud: improve: stabilize SABR playback
• f0cb7f0 ToddyTheNoobDud: improve: handle more unicode chars on instagram audio
• e524ed7 ToddyTheNoobDud: improve: memory efficiency & memory leak fixes
• 036ebff ToddyTheNoobDud: update: add support for bun updates in dependecies
• 53c5c9e ToddyTheNoobDud: update: pass the channel_id throught voice updates
• 74483d4 ToddyTheNoobDud: update: bump to typescript 7
• 76d5a66 ToddyTheNoobDud: update: bump clients
• 8b432dd toddynnn: Merge pull request #215 from realkalashnikov/fix/spotify-search
• 24a9afc ToddyTheNoobDud: update: bump version
• 8cbfb71 1Lucas1apk: improve: add aesthetic support guidelines with multiple discord links
• 8db66e0 1Lucas1apk: improve: optimize startup time and drop tsx
• 6b9ce3c ToddyTheNoobDud: update: bump all packages to latest
• e189f47 ToddyTheNoobDud: improve: replace all any usages with correct types & format with biome
• cbb04d5 ToddyTheNoobDud: update: add maintained by on startup
• 7deaa62 Lucas Morais Rodrigues: Merge pull request #212 from kokomo123/patch-1
• 6e64ae5 kokomo123: Remove deprecated version line
• 89aa524 ToddyTheNoobDud: update: remove logger in finishdecode and flush
• b0ede90 1Lucas1apk: update: implement comprehensive manual debug instrumentation
• 3c78be6 1Lucas1apk: improve: modernize architecture and clean up redundancies
• 2419a7d ToddyTheNoobDud: update: include omitBotguardData in player requests
• e5b7a8b 1Lucas1apk: improve: source stability and memory optimizations
• 5e042df 1Lucas1apk: update: improve stuck stream recovery and cache handling
• d36f0aa 1Lucas1apk: update: automatic dependency updates and restart
• 3e9d045 ToddyTheNoobDud: improve: refactor bun support & move to a new file
• 8b1ada1 ToddyTheNoobDud: update: disable monochrome by default
• 17ac8a9 1Lucas1apk: improve: promote core package version logs to info level
• 5e8ba18 1Lucas1apk: improve: implement persistent results cache for dependency checks
• d6551eb 1Lucas1apk: improve: add rate limiting to dependency update checks
• dc0db39 1Lucas1apk: Merge branch 'dev' of https://github.com/PerformanC/NodeLink into dev
• 3098b11 1Lucas1apk: improve: enhanced youtube recovery and itag fallback
• 0beb18a ToddyTheNoobDud: improve: refactor potoken with nativedom & remove jsdom
• 5096f30 Lucas Morais Rodrigues: Update Magmastream entry with version info
• d4f7b52 Lucas Morais Rodrigues: Update Magmastream entry with version info
• 4578973 ToddyTheNoobDud: update: bump version in package.json
• 88b5291 ToddyTheNoobDud: improve: give preference to flac in monochrome; fix: crash on flac seek
• 1162916 ToddyTheNoobDud: update: set mp4box.createFile argument to false
• 6b286b8 ToddyTheNoobDud: make useBunServer default to true
• b94777a ToddyTheNoobDud: improve: stream lifecycle and stream management; fix: bandcamp 403 error
• 2c79e45 ToddyTheNoobDud: update: bump symphonia to 1.1.0
• 936579a 1Lucas1apk: update: bump version to 3.8.1-dev.20260517.1
• 2126718 1Lucas1apk: update: compile source and update build artifacts
• 2dd0378 1Lucas1apk: improve: apply code quality fixes and project-wide linting
• 75a7789 1Lucas1apk: update: implement configuration migration and cache management
• f6f7ced 1Lucas1apk: update: restore robust YouTube visitorData and proxy management logic
• 44bc6f9 1Lucas1apk: update: restore robust YouTube visitorData and proxy management logic
• 372be74 1Lucas1apk: update: sync runtime validation schema with new config structure
• f06155c 1Lucas1apk: update: sync default configuration with new schema
• bfbe8cf 1Lucas1apk: update: flatten config schema and enforce strict unknown typing
• d37908e ToddyTheNoobDud: update: add support for qobuz in monochrome
• af7b092 ToddyTheNoobDud: improve: replace ring buffer with leftover strategy in opus encoder
• 62223ad ToddyTheNoobDud: update: make aead_xchacha20_poly1305_rtpsize the default encryption
• 1eb3fa7 ToddyTheNoobDud: update: add missing type in potoken
• b385604 ToddyTheNoobDud: improve: add v8 heap statics on profiler
What's Changed
• spelling mistake by @ramsquishna in #208
• docs: Remove deprecated version line by @kokomo123 in #212
• fix(spotify): use search.maxResults configuration for search limit by @realkalashnikov in #215
• update: readme & dockerfile to reflect new changes by @tropadoratomcleon-source in #218
• fix: reset fading start postion for gapless by @GDjkhp in #219
• fix: use seekable resource for seeks instead of refetching by @Akinori107 in #220
• fix(youtube): resolve letterboxed hqdefault thumbnails by @SreerajSK990 in #221
• fix: prevent profiler file symlink escapes by @shhahbaz in #222
• fix: resolve audio stream, demuxer, and source bugs by @knownasrazi in #223
• fix: prevent duplicate stream terminal events by @shhahbaz in #224
• fix: register routeplanner sub-routes correctly by @Akinori107 in #225
• fix: forward transition field in 12 AnimatableFilter subclasses by @Akinori107 in #227
• fix: apply skipMarginMs in updateSponsorBlock by @Akinori107 in #228
• fix: recompute trackEnd fade delay for playback speed changes by @Akinori107 in #229
• Add Lavalink.lua to supported clients list by @filispeen in #231
• fix: preserve explicit null endTime through seek pipeline by @Akinori107 in #232
• add: missing file by @tropadoratomcleon-source in #233
• fix(spotify): add GraphQL fallback for recommendations by @SreerajSK990 in #234
• fix: resolve ratelimit, worker eviction, body hang, and path traversal by @SreerajSK990 in #236
• sync: v3 < dev by @1Lucas1apk in #217
New Contributors
• @ramsquishna made their first contribution in #208
• @kokomo123 made their first contribution in #212
• @realkalashnikov made their first contribution in #215
• @tropadoratomcleon-source made their first contribution in #218
• @GDjkhp made their first contribution in #219
• @Akinori107 made their first contribution in #220
• @SreerajSK990 made their first contribution in #221
• @shhahbaz made their first contribution in #222
• @knownasrazi made their first contribution in #223
• @filispeen made their first contribution in #231
Contributors
• @1Lucas1apk (Lucas Morais Rodrigues)
• @ToddyTheNoobDud (toddynnn)
• @SreerajSK990
• @Akinori107 (Akinori)
• @shhahbaz (Shahbaz !!)
• @knownasrazi (Razi)
• @GDjkhp
• @tropadoratomcleon-source
• @filispeen
• @realkalashnikov (rafael)
• @kokomo123
• @ramsquishna (Ramkrishna)
• @UnschooledGamer (Emmanuel Lobo)
Full Changelog: