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>
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
# 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:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
/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:
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```sh
|
||||
./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:
|
||||
|
||||
```text
|
||||
/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:
|
||||
|
||||
```sh
|
||||
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
|
||||
|
||||
```sh
|
||||
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.
|
||||
Reference in New Issue
Block a user