Releases: hendrikvh/ESPHome-RTSP-Audio
Releases · hendrikvh/ESPHome-RTSP-Audio
Release list
v0.2.0
Fixed
- INMP441 I²S aliasing when
bits_per_sample: 16bitis set
(#7).
Settingbits_per_sample: 16biton themicrophone:block causes
the I²S peripheral to misalign the 24-bit INMP441 data word, halving
the effective sample rate and aliasing all energy above 8 kHz back
onto the lower half of the spectrum. The fix is to use
bits_per_sample: 32bit— the 32-bit frame keeps the word correctly
aligned; the 8 LSBs are padding zeros and the driver handles them
correctly.
Added
- DC blocker. A dedicated 1-pole high-pass at a fixed 5 Hz now
sits upstream of every other DSP stage and runs by default on every
packet — its only job is to kill the DC offset MEMS capsules
(INMP441 and friends) ship with, before it eats headroom in any of
the downstream stages. Separates concerns cleanly: the DC
blocker is hygiene; the user-tunable low-cut is tone shaping. One
MAC per sample, sub-audible cutoff. Note: the default install
is no longer bit-identical to v0.1 — the DC blocker runs by
default. The audible change is the removal of MEMS DC bias, which
is desirable on every device the component targets. - Low-cut bypass at 0 Hz. The low-cut slider now ranges from
0 Hz to 500 Hz, with anything below the existing active
minimum (20 Hz) disabling the stage entirely — mirroring how
16 kHz (Nyquist) already disables the high-cut. Dragging the
slider to 0 is the natural "off" position. The always-on DC
blocker keeps running in either case, so disabling the audible
low-cut never re-introduces DC bias downstream.
Changed
- Cut filters upgraded to 2nd-order Butterworth. Both the low-cut
and high-cut stages now use a 2nd-order Butterworth (biquad) shape
instead of the previous 1-pole IIR, doubling the rolloff from
−6 dB/oct to −12 dB/oct. At the default 100 Hz low-cut, 50 Hz
rumble is now ~12 dB rejected (vs ~6 dB), so HVAC and handling noise
drop noticeably more without moving the cutoff up into the voice
band. The Butterworth's defining feature — a maximally-flat
passband — also means voice timbre is preserved cleanly instead
of being gently tilted by the 1-pole's roll-in starting an octave
above the cutoff. The −3 dB cutoff frequency convention is unchanged,
so any persisted Home Assistant slider value keeps the same audible
meaning; the slope at the cutoff is the only thing that changes.
Implementation uses single-precision float in a direct-form-I
biquad — the same audio cost lands on every supported MCU
(ESP32-S3 uses its FPU, S2 and C3 use software float) rather than
depending on FPU-only fixed-point math that would have to choose one
target. User-facing config (cutoff ranges, defaults,
bypass-at-Nyquist behaviour) is unchanged. See
docs/images/filter-response.png
for a side-by-side magnitude plot, regenerable via
scripts/plot_filter_response.py.
v0.1.0
Changed
- Audio sample rate raised from 16 kHz to 32 kHz. The mic source, RTP
payload (L16/32000/1), filter coefficients, and high-cut bounds
(now capped at the new 16 kHz Nyquist) all move together. Bit depth
stays at 16-bit mono. The MEMS capsules this targets (e.g. INMP441)
can't faithfully capture much above 16 kHz, so 32 kHz is the balance
point — voice plus the ambient detail (footsteps, doors, bird calls)
in the 8–16 kHz octave, without spending CPU and Wi-Fi bandwidth on
content the mic can't reproduce. On an ESP32-S3 the audio path still
sits well under the comfort budget reported bycpu_use_pct. RTP
packets roughly double in size (~1.3 KB at 20 ms), still well under
MTU. See the README's "Audio format" section. - Ring buffer reduced from 2 s to 1 s of jitter slack so the
component fits on bare ESP32 boards without PSRAM. At 32 kHz the
2 s buffer was 128 KB, which routinely fails to allocate as a
contiguous chunk onWROOM/ RISC-V parts that only have ~320 KB
internal SRAM total. 1 s (~64 KB) keeps the same byte budget as the
previous 16 kHz / 2 s buffer; the RTSP client's own jitter buffer
brings end-to-end resilience back to ~1.5–2 s. See the README's
"Sized to fit ESP32 internal SRAM" section for the rationale and a
note on possible PSRAM-aware sizing in future.
Added
- High-cut filter, tunable from Home Assistant. Opt-in
number:on
platform: rtsp_audioexposing a high-cut frequency slider
(high_cut_frequency_hz, default 20000 Hz / off, 1000–20000 Hz
range) that rolls off energy above the cutoff — useful for taming
mic hiss, wind noise, and out-of-band content downstream consumers
don't need (narrow-band voice models, NVR storage). At the maximum
the stage is skipped and the audio path is bit-identical to a build
without it. See
docs/configuration.md. - Low-cut filter, tunable from Home Assistant. Opt-in
number:on
platform: rtsp_audioexposing a low-cut frequency slider
(low_cut_frequency_hz, default 100 Hz, 20–500 Hz range) that
strips MEMS-mic DC bias and sub-100 Hz rumble (HVAC, handling, wind)
before the audio leaves the device, so downstream consumers get a
cleaner signal with more usable dynamic range. See
docs/configuration.md. - RTSP session inactivity timeout to better handle silent client disconnects.
A client that disappears without sendingTEARDOWN(ue to crash,
sleep, Wi-Fi drop) is now reaped after 60 s instead of blocking the
single client slot for minutes until the OS-level TCP timeout fires. - Peak-level diagnostic sensor (
peak_level_dbfs). Opt-insensor:
onplatform: rtsp_audioreporting peak audio level in dBFS
(0 dBFS = clipping) over the last 5 s window. Designed as the
missing feedback channel for thegain_dbslider — previously the
user had to guess the right gain by listening to the receiving
client. See
docs/configuration.md. - CPU-use diagnostic sensor (
cpu_use_pct). Opt-insensor:on
platform: rtsp_audioreporting what fraction of wall-clock the
RTSP audio path consumes, so you can tell whether the chip has
headroom for the current sample rate, DSP settings, and enabled
features — and decide whether to upgrade or back off. See
docs/configuration.md. - Audio gain in dB, tunable from Home Assistant. Opt-in
number:
onplatform: rtsp_audioexposing a software audio gain slider
(gain_db, -20 to +40 dB, 1 dB step, default 0 dB, persisted) so a
quiet mic can be lifted without re-flashing. 0 dB is bit-identical
to a no-gain build; overflow is saturating-clamped, never wrapped.
See docs/configuration.md. - Diagnostic sensors for Home Assistant. Opt-in
client_connected
(binary_sensor),client_ip(text_sensor), andbytes_sent(sensor)
so an HA dashboard can see in real time whether a client is pulling
audio, who it is, and at what bitrate without watching serial logs.
See
docs/configuration.md.
Fixed
- Use-after-free on session teardown
(#5).
deallocate_stream_buffers_()could free the ring buffer while a
trailing I²S DMA callback on the mic's own FreeRTOS task was still
writing into it, occasionally crashing the node onTEARDOWN/
Wi-Fi drop / peer close. Deallocation is now deferred until
mic_source_->is_stopped()confirms the mic task has actually
exited, so the writer is guaranteed gone before the buffer goes
away.
v0.0.1
First semi-stable release. Working nicely with BirdNET-Go so my wife is happy!
Added
- Single-viewer RTSP/1.0 server on ESP32 + ESP-IDF, exposing one
microphone as a stream. - TCP and UDP RTP transports, both supported. Transport is
negotiated per client atSETUP: UDP (RTP/AVP) works with VLC
and most players; TCP-interleaved (RTP/AVP/TCP) works with
FFmpeg, BirdNET-Go, Frigate, and most NVRs. No YAML toggle. - Tests covering ESP32-S2 + ESP-IDF and ESP32-S3 + ESP-IDF,
run on every PR (S3 only) and on push tomain(both) via GitHub
Actions. - Local Dockerised development workflow:
make config,
make compile,make lint. Only Docker required on the host.
Fixed
- Crash on no-PSRAM boards.
tx_buffer_is now reserved up front so
the RTP send path no longer triggers OOM at runtime.