Skip to content

[Bug]: voice path fails in four places on a headless host (hostless audio backends) #114

Description

@pxlninja

MeshChatX version

4.9.1

Release channel

Stable

Platform

Headless server (Docker / pip / uv)

Operating system

Linux

OS details (if Other)

Debian 13, x86_64, no PulseAudio or PipeWire

How did you install MeshChatX?

pip / uv / PyPI

What happened?

On a host with no audio server, MeshChatX installs its hostless backends and
logs WebAudioBridge: installed hostless LXST audio backends (no PulseAudio).
Voice calls then fail in four separate places. Each fault hides the next, so
they only appear one at a time, in this order. Tested on 4.9.1 with LXST 0.5.3
and RNS 1.5.4, with a Sideband client calling in.

1. Incoming calls never ring. HostlessAudioSink
(src/backend/web_audio_bridge.py) writes its own __init__ and subclasses
LocalSink, which in LXST is an empty class, so it never gets the attributes
LineSink.__init__ sets. LXST's Telephony.__update_output_buffer_targets
reads and writes buffer_max_height, autostart_min, streaming and calls
wait_for_frames(). The first incoming call raises inside the
remote-identified callback and the call dies before ringing.

2. Saved voicemails raise no notification.
voicemail_manager.stop_recording calls
on_new_voicemail_callback(hash, name, duration) with three arguments.
identity_context.setup assigns lambda vm: self.app.on_new_voicemail_received(vm, context=self),
which takes one — while the app's own handler is
on_new_voicemail_received(remote_hash, remote_name, duration, context=None).
The recording is written first, so the audio survives, but the notification is
lost and the failure is logged as "Error stopping recording".

3. The voicemail greeting is inaudible. voicemail_manager builds
OpusFileSource(greeting_path, target_frame_ms=60), and LXST's timed
argument defaults to False, so an 8-second greeting is pushed into the
transmit mixer as fast as the mixer will accept it. The trailing partial frame
(1,325 samples, 27.6 ms) is not a legal Opus frame duration and the mixer
rejects it. Passing timed=True makes the greeting play in real time.

4. The receive path dies mid-call. Tee
(src/backend/telephone_manager.py) is declared as a plain class, so
Pipeline.__init__'s issubclass(type(sink), Sink) check rejects it, and
because it is also assigned to telephone.audio_output, teardown raises
'Tee' object has no attribute 'stop' while processing incoming packets.

Upstream, not yours, but it surfaces here: LXST's LinkSource defines no
samplerate, and LXST/Sinks.py reads source.samplerate on the first frame
it accepts, so every incoming call packet raises AttributeError and
voicemail recordings come out as digital silence (measured: peak amplitude
0.0003 across four recordings, against 0.49 after patching). LXST has issues
disabled on GitHub, so I am flagging it where it shows up.

What did you expect?

A call from an LXST client to a headless MeshChatX should ring, play the
greeting audibly, record the caller, and notify.

Steps to reproduce

  1. Install MeshChatX 4.9.1 from PyPI on a Linux host with no PulseAudio or
    PipeWire. Run headless with --no-https --host 0.0.0.0 --port 8001.
  2. Enable voicemail and telephone announce, and record a greeting.
  3. Call it from another LXST client (Sideband 2.1.0 here) over a Reticulum TCP
    link.
  4. Watch the service log. Each fault above appears in turn once the previous
    one is worked around.

Logs or error output

[Error] Error while executing remote identified callback from <…>. The contained exception
        was: 'HostlessAudioSink' object has no attribute 'buffer_max_height'
[Error] Error stopping recording: IdentityContext.setup.<locals>.<lambda>() takes 1
        positional argument but 3 were given
[Error] Error while mixing frame on <LXST.Mixer.Mixer object>: The effective frame
        duration (27.6 ms) was not one of the acceptable values.
[Error] WebAudioBridge: failed to tee receive path: Audio pipeline initialised with
        invalid sink
[Error] <lxst.telephony/…> could not process incoming packet: 'Tee' object has no
        attribute 'stop'
[Error] <LXST.Network.LinkSource object> could not process incoming packet:
        'LinkSource' object has no attribute 'samplerate'


All four MeshChatX faults are patched locally and voice now works end to end
(call connects, greeting plays, caller is recorded at a normal level). Happy to
open a PR if the shapes below look right:

- `HostlessAudioSink`: set `buffer_max_height = 3`, `autostart_min = 1`,
  `streaming = False` and add a no-op `wait_for_frames()`.
- `identity_context`: `lambda remote_hash, remote_name, duration: self.app.on_new_voicemail_received(remote_hash, remote_name, duration, context=self)`.
- `voicemail_manager`: `OpusFileSource(greeting_path, target_frame_ms=60, timed=True)`.
- `Tee`: subclass `LXST.Sinks.Sink`, forward `start`/`stop`/`release` to its
  sinks, and carry the same buffer attributes as the hostless sink.

Checklist

  • I searched existing issues to avoid duplicates
  • I included my MeshChatX version, channel, operating system, and install method
  • I can reproduce the issue with the steps above

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions