feat(tts): transcode WAV → Ogg/Opus + emit real waveform #91
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
jlxq0/matrix-mcp!91
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/tts-transcode-to-ogg-opus"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Element only treats
m.audioas a voice-memo bubble when the audio is Ogg/Opus —audio/wavfalls back to the generic file-attachment UI regardless of the MSC3245 voice flag. Sosend_tts_voice_messagewas technically working but the bubble was dead in Element.This PR transcodes Chatterbox's WAV output to Ogg/Opus in-process, in pure Rust:
parse_wav_mono_16bitextracts PCM samples (mono / 16-bit / 8 · 12 · 16 · 24 · 48 kHz only, which covers Chatterbox).compute_waveformproduces 40 peak-amplitude buckets in 0..=1024 — Element actually draws the bars now instead of a flat line.transcode_wav_to_ogg_opusruns the PCM through libopus (24 kbps Voip mode, 20 ms frames) and packs the packets into an RFC 7845 OggOpus container (OpusHead + OpusTags + audio pages, granule positions tracked at 48 kHz).send_tts_voice_message_inneruploads the Ogg bytes asaudio/ogginstead ofaudio/wav, includes the waveform in the MSC1767 audio block.New crates:
opus(libopus bindings) +ogg(container).opusbuilds libopus statically via cc-rs, so the distroless runtime image still needs no system libraries.Test plan
cargo fmtcargo clippy --all-targets -- -D warningscargo test(162 passed, +1 net: dropped 2 wav-duration tests, added 3 transcoder tests including a sine-wave roundtrip that asserts the output is a valid Ogg stream with ≥3 pages and a non-flat waveform)🤖 Generated with Claude Code
Element only renders m.audio as a voice-memo bubble when the audio is Ogg/Opus, regardless of the MSC3245 voice flag. WAV-mimetype voice messages drop back to the generic file-attachment UI with no play button or waveform bars, which is what users were seeing. send_tts_voice_message now: - Takes Chatterbox's WAV bytes and decodes the mono 16-bit PCM samples in-process (no extra HTTP roundtrip, no ffmpeg). - Computes a 40-bucket peak waveform (0..=1024 per MSC1767) off those samples so Element draws real bars rather than a flat line. - Encodes the PCM through libopus at 24 kbps Voip mode and packs the resulting Opus packets into an RFC 7845 OggOpus container (OpusHead + OpusTags + audio pages, granule positions tracked at 48 kHz). - Uploads the Ogg bytes as audio/ogg. Pulls two new crates (`opus`, `ogg`). `opus` builds libopus statically from C source via opusic-sys/cc-rs, so the distroless runtime image still needs no system libraries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>