v0.4.0-rc — Nightingale
Pre-releasePossessing a beautiful, creative, and evocative song through both night and day, the humble Nightingale has long been seen as a symbol of poetry and love.
In keeping with the spirit of this release's passerine of choice, songbird now sings more melodiously than ever!
This release has been a long time coming, and as such Nightingale brings several huge changes to how songbird is used and how it performs.
The largest change by far is a complete overhaul of all code relating to audio decoding, mixing, and loading from different locations, driven by Symphonia.
Broadly, this means that we handle every part of the audio pipeline in-process and ffmpeg is entirely removed, saving significant memory and CPU and letting you scale to more voice calls on one box.
Another boon is that reading in-memory audio now Just Works: if you can treat it as a &[u8], then you're good to go!
Having this level of control also lets us expand our list of file-formats supporting direct Opus passthrough to include Ogg Opus and WebM/MKV, as well as the DCA format.
Given that many sites will serve WebM, this is a significant saving on CPU time for many playback use cases.
Additionally, we now handle HTTP reconnection logic internally, offering more reliable behaviour than certain downloader -> ffmpeg process chains would provide.
Symphonia format support is significant, and you can enable and disable exactly the codecs and containers you need at compile-time.
Voice receive has been given its own fair share of improvements.
Most importantly, all receive sessions now make use of per-user jitter buffers – songbird will now delay decoding of all users to correctly reorder audio packets, smooth out network latency jitter, and to help synchronize playback of several speakers.
Receive functionality is now feature-gated and disabled by default, and so won't affect compile-time or runtime performance if you don't want to make use of it.
Finally, songbird now includes a new deadline-aware audio scheduler, which will pack as many concurrent Calls as possible onto a single thread.
Compared to the previous model we now reduce thread counts, CPU use, and context switching – for context, up to 660 live Opus-passthrough-enabled calls can run on a single thread on a Ryzen 5700X.
This is also helped by how we now park all Calls without any active Tracks onto a single shared event handling async task.
All in all, we're really excited to see what you build with these new tools and performance improvements.
Thanks to the following for their contributions:
Upgrade Pathway
Inputs:
ytdletc. are removed and replaced with new lazy initialisers – read the docs on how to create sources from a URL or local path.- All inputs are now lazy by default, so
Restartableis no longer needed. - Inputs can no longer directly output raw audio, as symphonia must always parse a container/codec pair. We've included a custom
RawReadercontainer format and theRawAdaptertransform to support this. - Metadata is now split according to what you can learn when creating a source (
AuxMetadata, e.g. info learned from a web scrape) and what metadata is encoded in a track itself (Metadata).Metadatacan only be read once a track is fully initialised and parsed. - Songbird can now better encode an audio source's lifecycle from uninitialised, to readable, to having its headers fully parsed. Read the examples on how they can be manipulated, particularly if you want to make use of metadata.
- Songbird's audio systems have undergone the most change in this release, so this list is non-exhaustive.
Tracks:
TrackHandle::actionnow gives temporary access to aViewobject – a set of current track state and extracted metadata – which can be used to fire more complex commands like seeking or pre-loading aTrackby returning anAction.TrackHandles are now created only fromDriver::play/play_inputand related methods.tracks::create_playeris removed in favour of the above methods onDriver.
Voice Receive:
- Users of voice receive will now need to enable the
"receive"feature. CoreEvent::VoicePackethas now split into two events:RtpPacketandVoiceTick.
RtpPacketcorresponds to raw RTP packets received from each user and does not decode audio, whileVoiceTickfires every 20ms and includes the reordered (and decoded, if so configured) audio for every user, synchronised and ready to use.- Per-user jitter buffer sizes can be configured using
Config::playout_buffer_lengthand::playout_spike_length.
Added
- [driver] Driver: Implement audio scheduler (#179) (@FelixMcFelix) c:3daf11f
- [gateway] Gateway: Add
Songbird::iter(#166) (@fee1-dead) c:5bc8430 - [driver] Driver/receive: Implement audio reorder/jitter buffer (#156) (@FelixMcFelix) c:c60c454
- [driver] Driver: Split receive into its own feature (#141) (@FelixMcFelix) c:2277595
- [driver] Driver: Add toggle for softclip (#137) (@FelixMcFelix) c:13946b4
- [driver] Support simd_json (#105) (@vicky5124) c:cb0a74f
- [driver] Driver/Input: Migrate audio backend to Symphonia (#89) (@FelixMcFelix) c:8cc7a22
Changed
- [clippy] Chore: Cleanup clippy lints (@FelixMcFelix) c:91640f6
- [deps] Chore: Upgrade serenity to 0.12.0-rc (@FelixMcFelix) c:1487da1
- [deps] Chore: Bump DiscoRTP version (@FelixMcFelix) c:0ef0e4f
- [clippy] Fix clippy pedantic warnings (#204) (@GnomedDev) c:3d307aa
- [deps] Update simd-json to 0.13 (#203) (@GnomedDev) c:63d48ee
- [deps] Chore: Update Rubato -> 0.14.1 (@FelixMcFelix) c:67b3b3e
- [deps] Chore: Update (most) dependencies (@FelixMcFelix) c:4220c1f
- [clippy] Chore: Rust 1.72.0 Clippy lints, adjust MSRV (@FelixMcFelix) c:6f80156
- [deps] Driver: Replace
xsalsa20poly1305withcrypto_secretbox(#198) (@Sebbl0508) c:77a9b46 - [ci] Chore(ci): Update rust, cargo and cache actions (#177) (@jontze) c:5ddc8f4
- [ci] chore(docs): Update rust setup action and cache (#176) (@jontze) c:4eadeb6
- [ci] chore(workflows): Update checkout action to v3 (#175) (@jontze) c:841224e
- [driver] Driver: Retune threadpool keepalive time (@FelixMcFelix) c:9ab5be8
- [driver] Driver: Downgrade failed scheduler message delivery to info (@FelixMcFelix) c:02c9812
- [clippy] Chore: Clippy fixes to match new MSRV. (@FelixMcFelix) c:9fa063f
- [deps] Chore: Update dependencies, MSRV. (@FelixMcFelix) c:1bf17d1
- [deps] Chore: Update dependencies. (@FelixMcFelix) c:a5f7d3f
- [ci] Repo: Update issue templates (@FelixMcFelix) c:6cd3097
- [deps] Gateway: Twilight 0.15 support (#171) (@Erk-) c:b2507f3
- [clippy] Chore: Fix clippy warnings (#167) (@fee1-dead) c:6e6d8e7
- [ci] CI: Disable Windows, MacOS Testing (@FelixMcFelix) c:2de071f
- [input] Input: Clarify
YoutubeDlerror if command missing (#160) (@FelixMcFelix) c:53ebc3c - [deps] Deps: Move to published
symphoniav0.5.2 from git (@FelixMcFelix) c:fdd0d83 - [gateway] Gateway: Simplify return value of
join/join_gateway(#157) (@FelixMcFelix) c:f2fbbfe - [deps] Chore: Update tokio-tungstenite, typemap_rev (@FelixMcFelix) c:5d06a42
- [deps] Chore: Apply latest nightly clippy lints (@FelixMcFelix) c:125c803
- [driver] Driver: remove copy to receive &mut for softclip (#143) (@FelixMcFelix) c:ab18f9e
- [deps] Deps: Move symphonia back to mainline repo. (@FelixMcFelix) c:b7e40ab
- [deps] Deps: Update dev-dependencies (@FelixMcFelix) c:f72175b
- [deps] Deps: Update Ringbuf, Serde-Aux, Simd-Json, Typemap (@FelixMcFelix) c:6a38fc8
- [clippy] Chore: Fix new(er) Clippy lints (@FelixMcFelix) c:662debd
- [deps] Deps: Update Twilight -> v0.14 (@FelixMcFelix) c:646190e
- [deps] Deps: Update twilight to 0.13 (#147) (@Erk-) c:372156e
- [deps] Chore: Update
xsalsa20poly1305-> 0.9 (@FelixMcFelix) c:48db45f - [deps] Chore: Rework crate features (#139) (@FelixMcFelix) c:d8061d5
- [driver] Driver: Migrate to
tokio_tungstenite(#138) (@FelixMcFelix) c:76c9851 - [input] Input: lazy_static -> once_cell::sync::Lazy (#136) (@GnomedDev) c:0beb0f0
Fixed
- [gateway] Fix compiling with latest serenity (#199) (@GnomedDev) c:509743f
- [driver] Driver: Correct buffer instantiation for Rubato (@FelixMcFelix) c:935171d
- [tests] Chore: Update test URL for playlist. (@FelixMcFelix) c:c55a313
- [driver] Driver: Don't trim recv_buffer on MacOS (@FelixMcFelix) c:019ac27
- [driver] Driver: Fix scheduler crash after task closure (@FelixMcFelix) c:77e3916
- [input] Input: Add HTTP Status Code Checks (#190) (@maxall41) c:c976d50
- [driver] Fix: Move WS error handling (#174) (@Erk-) c:500d679
- [gateway] Gateway: Fix serenity breaking changes (#173) (@tazz4843) c:4d0c1c0
- [driver] fix(ws): Songbird would fail if it could not deserialize ws payload. (#170) (@Erk-) c:c73f498
- [repo] Chore: Fix README.md CI badge (#161) (@FelixMcFelix) c:50dbc62
- [input] Input: Pass
--no-playlistforYoutubeDl(#168) (@fee1-dead) c:296f0e5 - [docs] Docs: Fix a link in constant docstring (#169) (@fee1-dead) c:3f6114c
- [input] Input: Fix high CPU use when initialising long files over HTTP (#163) (@FelixMcFelix) c:50fa17f
- [deps] Docs: Correct version for symphonia codec support (@FelixMcFelix) c:ed4be7c
- [driver] Avoid spawning a disposal thread per driver (#151) (@GnomedDev) c:be3a4e9
- [input] Input: Fix audio stream selection for video files. (#150) (@FelixMcFelix) c:03b0803
- [driver] Driver: Prune
SsrcStateafter timeout/disconnect (#145) (@FelixMcFelix) c:893dbaa - [docs] Events: Fix typo in docs for VoiceData (#142) (@tazz4843) c:6769131
- [docs] Docs: Fix module docs for
songbird::tracks. (@FelixMcFelix) c:c1d93f7