Files
Rene KievitsandClaude Opus 5 7529a60650 Audio capture and streaming app for webOS 5/6
Captures the TV's audio and sends it out over several transports. The
primary one is HyperHDR: RTP/L16 to a host-side loopback device, since
HyperHDR has no network audio input of its own. A second route renders
the spectrum on the TV and sends FlatBuffers images to port 19400
instead, for setups where touching the host's sound config is not an
option.

  native/       the service: capture backends (PulseAudio, ALSA, exec,
                test tone, all dlopen-based), DSP, and one file per sink
  frontend/     D-pad driven UI at a fixed 1920x1080
  servicefiles/ native service manifest plus the boot script
  host/         RTP receiver and the loopback installer for the HyperHDR
                machine
  tools/        build/package, asset generation, Homebrew Channel
                manifest, on-TV probe
  test/         host-side suites: FlatBuffers and RTP verified against
                real decoders, the engine end to end, the page in jsdom

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 10:21:00 +02:00

5.2 KiB

When it does not work

Work down the chain: does the service run, does it capture, does the audio leave the TV, does it arrive, does HyperHDR see it.

The app says "No service"

The service did not start. Reinstall the app, then check from a shell on the TV:

luna-send -n 1 -f luna://org.webosbrew.audiocap.service/isRunning '{}'
ls -l /media/developer/apps/usr/palm/services/org.webosbrew.audiocap.service/

The binary must be there and executable. If luna-send reports Service does not exist, the service failed to register on the bus — usually a missing services.json or a binary built for the wrong architecture. Check with file audiocap-service: it should say ARM, EABI5.

"The service is running as uid …" instead of as root

It has not been elevated. Press System → Grant root access, or run:

/media/developer/apps/usr/palm/services/org.webosbrew.hbchannel.service/elevate-service \
  org.webosbrew.audiocap.service

Then restart the service (quit on the bus, or just relaunch the app). Without root the audio devices are unreadable and the settings file falls back to /tmp.

Nothing is captured

Capture → Backend on Automatic and the meter stays flat.

  1. System → Run diagnostics. Look at libraries and pulseSockets. If libpulse.so.0 and libasound.so.2 are both null, no backend can work as built and you need the exec backend with whatever binary the TV does have.

  2. Run the probe for the fuller picture:

    ssh -p 9922 root@TV-IP 'sh -s' < tools/tv-probe.sh
    
  3. Prove the rest of the chain first. Set the backend to Test tone and start. If the tone reaches HyperHDR, the problem is only the capture end.

Common outcomes by firmware:

What the probe shows What to do
a PulseAudio socket and pactl lists a .monitor source backend pulse, device = that source name (or blank)
/proc/asound with a capture PCM backend alsa, device hw:X,Y from arecord -l
only arecord or gst-launch-1.0 backend exec, e.g. arecord -D hw:0,0 -f S16_LE -r 48000 -c 2 -t raw
nothing at all the audio path is inside the closed audio daemon; only the test tone will run

The meter moves but the lights do not

Audio is being captured, so it is the transport or HyperHDR.

Is it leaving the TV? Enable the HTTP output and open http://TV-IP:4012/audio.wav in VLC. If you hear the TV, the TV's side is fine.

Is it arriving? On the HyperHDR machine:

./host/lgtv-audiocap-receiver.py --port 5004 --output - | \
    aplay -f S16_LE -r 48000 -c 2 -

Nothing? Check the firewall (sudo ufw allow 5004/udp) and that the receiver address on the TV is right. Watch the sink's own counters in Status → Outputs: sendErrors climbing means the TV cannot even send.

Is HyperHDR listening to the right device? The loopback has two ends and they are easy to swap. The receiver plays into hw:Loopback,0,0; HyperHDR must capture hw:Loopback,1,0.

Is something else holding the loopback? PulseAudio grabs cards it finds. install-loopback.sh writes a udev rule to keep it away; if you set the card up by hand, add it yourself:

/etc/udev/rules.d/89-lgtv-audiocap-loopback.rules
ATTRS{id}=="Loopback", ENV{PULSE_IGNORE}="1", ENV{ACP_IGNORE}="1"

The audio crackles or drops out

The receiver prints loss statistics every 30 seconds. Read those first.

Symptom Cause Fix
steady loss on Wi-Fi the TV's radio Ethernet, or the visualiser output instead
loss in bursts buffer too small for the jitter --latency-ms 150 --prebuffer-ms 120
clicks with no reported loss the loopback and the stream disagree about the rate make the TV's rate, the receiver's --rate and HyperHDR's device all 48000
audio slowly drifts out of sync free-running clocks, unavoidable in a one-way stream it is a few ms per hour; restart the receiver if it ever matters

The lights react to the wrong thing

HyperHDR is showing another source at a higher priority. The visualiser sink sends at priority 150 by default; a screen grabber usually sits at 240 and a static colour at 100. Lower numbers win. Set the visualiser's priority below whatever is currently on screen.

Settings do not survive a reboot

System → Settings file says Temporary (/tmp). The service is not root, so it cannot write /var/lib/webosbrew/audiocap/. Grant root access; the next save lands in the persistent path.

It does not start with the TV

System → Start on boot installs a symlink in /var/lib/webosbrew/init.d/, which the Homebrew Channel runs at boot. Check it:

ls -l /var/lib/webosbrew/init.d/audiocapautostart

If it is missing, the Homebrew Channel's exec refused the call — its "root access" toggle has to be on. If it is there and nothing happens at boot, check that autoStart is also on: the script only wakes the service, and the service decides for itself whether to start capturing.

Reading the log

luna-send -n 1 -f luna://org.webosbrew.audiocap.service/getLogs '{}'

or System → Show log in the app. Set Log level to Debug first if you are chasing something specific — it is the last 200 lines only, and at Debug they go by quickly.