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>
116 lines
5.2 KiB
Markdown
116 lines
5.2 KiB
Markdown
# LG TV Audio Cap
|
|
|
|
Captures the audio playing on an LG webOS 5 or 6 TV and streams it off the set.
|
|
The reason it exists is HyperHDR: ambient lighting that reacts to what the TV is
|
|
actually playing, without a microphone in the room or an audio splitter behind
|
|
the telly.
|
|
|
|
It installs through the [Homebrew Channel](https://github.com/webosbrew/webos-homebrew-channel)
|
|
and runs as a native background service with a remote-friendly UI in front of
|
|
it.
|
|
|
|
```
|
|
┌────────────────────── LG webOS TV ──────────────────────┐
|
|
│ PulseAudio / ALSA / a command │
|
|
│ │ │
|
|
│ capture ─► level + 16-band analysis │
|
|
│ │ │
|
|
│ ├─► RTP/L16 ──────────────► HyperHDR host │ ← the main path
|
|
│ ├─► Flatbuffers images ───► HyperHDR │
|
|
│ ├─► raw PCM over UDP │
|
|
│ ├─► raw PCM over TCP │
|
|
│ └─► WAV over HTTP │
|
|
└─────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Why it works this way
|
|
|
|
HyperHDR has **no network audio input**. Its sound-reactive effects read a
|
|
*local* capture device. So the main path here does not try to talk to HyperHDR
|
|
at all: it sends the TV's audio to the HyperHDR machine as RTP/L16, and a small
|
|
receiver there turns it into a normal sound device that HyperHDR can select.
|
|
That is [`host/lgtv-audiocap-receiver.py`](host/lgtv-audiocap-receiver.py), and
|
|
[`host/install-loopback.sh`](host/install-loopback.sh) sets up the loopback for
|
|
it.
|
|
|
|
If you would rather not run anything on the HyperHDR machine, there is a second
|
|
path: the TV does the frequency analysis itself and sends finished images to
|
|
HyperHDR's Flatbuffers port. Fewer moving parts, but the lights react to the
|
|
TV's idea of the spectrum rather than to real audio.
|
|
|
|
See [docs/hyperhdr.md](docs/hyperhdr.md) for both, step by step.
|
|
|
|
## Requirements
|
|
|
|
- An LG TV on webOS 5 or 6, rooted, with the Homebrew Channel installed.
|
|
- Root for the service. The TV's audio devices are not readable otherwise; the
|
|
app has a **Grant root access** button that calls the Homebrew Channel's
|
|
`elevate-service` for you.
|
|
- For the main HyperHDR path: a Linux machine running HyperHDR with either
|
|
`snd-aloop` or PulseAudio/PipeWire available.
|
|
|
|
## Installing
|
|
|
|
**From the Homebrew Channel.** Open the Homebrew Channel on the TV, find
|
|
*Audio Cap*, install, launch.
|
|
|
|
**From an ipk.** Copy the ipk to the TV and install it with the Homebrew
|
|
Channel's *Install from file*, or from a workstation:
|
|
|
|
```sh
|
|
ares-install --device tv out/org.webosbrew.audiocap_1.0.0_all.ipk
|
|
```
|
|
|
|
**From source.** See [docs/development.md](docs/development.md).
|
|
|
|
## First run
|
|
|
|
1. Launch **Audio Cap** on the TV.
|
|
2. **System → Root access**: press *Grant root access* if it says the service is
|
|
not root. It restarts itself.
|
|
3. **Capture → Backend**: leave it on *Automatic* to begin with. If nothing is
|
|
captured, run [`tools/tv-probe.sh`](tools/tv-probe.sh) on the TV to see what
|
|
your firmware actually offers, then pick a backend by hand.
|
|
4. **Outputs → HyperHDR audio (RTP/L16)**: turn it on and enter the address of
|
|
the machine running HyperHDR.
|
|
5. On that machine: `sudo ./host/install-loopback.sh --install-service`, then
|
|
point HyperHDR's sound capture at the device it prints.
|
|
6. Press **Start** on the TV. The level meter should move.
|
|
|
|
Nothing captured, no idea why? [docs/troubleshooting.md](docs/troubleshooting.md).
|
|
|
|
## The other outputs
|
|
|
|
Each can run at the same time as the others.
|
|
|
|
| Output | What it is | Use it for |
|
|
| --- | --- | --- |
|
|
| **HyperHDR audio** | RTP/L16, port 5004 | the main path; also readable by PulseAudio's `module-rtp-recv` with no custom software |
|
|
| **HyperHDR visualiser** | Flatbuffers images, port 19400 | HyperHDR with nothing installed on the host |
|
|
| **Raw PCM over UDP** | S16LE datagrams, port 4010 | your own scripts; lowest latency |
|
|
| **Raw PCM over TCP** | S16LE stream, port 4011 | anything that would rather connect than listen |
|
|
| **HTTP WAV** | `http://tv:4012/audio.wav` | opening the TV's audio in VLC |
|
|
|
|
## Layout
|
|
|
|
```
|
|
native/ the webOS service: capture, DSP, sinks, Luna API (C)
|
|
frontend/ the on-TV app (plain HTML/CSS/JS, no framework)
|
|
servicefiles/ services.json, package.json and the boot script
|
|
host/ the receiver and loopback setup for the HyperHDR machine
|
|
tools/ build, packaging, asset generation, on-TV probe
|
|
test/ host-side tests: wire formats, the capture pipeline, the UI
|
|
docs/ the longer explanations
|
|
```
|
|
|
|
## Documentation
|
|
|
|
- [docs/hyperhdr.md](docs/hyperhdr.md) — connecting it to HyperHDR, both ways
|
|
- [docs/configuration.md](docs/configuration.md) — every setting, and the Luna API
|
|
- [docs/development.md](docs/development.md) — building, testing, packaging, publishing
|
|
- [docs/troubleshooting.md](docs/troubleshooting.md) — when it does not work
|
|
|
|
## License
|
|
|
|
MIT.
|