ares-install needs a working ssh into the TV, and this TV only has root
access (no Developer Mode, no ssh currently reachable). The Homebrew
Channel's own "Add repository" dialog accepts any URL that returns
{"packages": [...]}, which is the same schema its own gen-manifest.js
uses per app — confirmed by reading the app's source directly rather
than guessing at the format.
make-manifest.py now also writes out/repo.json, the existing manifest
wrapped in that shape, so publishing is: build the ipk, run the script
with --base-url pointing at wherever the release assets will live,
attach ipk + icon + repo.json there, then paste the repo.json URL into
the TV once. No ares, no ssh, no review queue.
Root elevation afterwards is unaffected either way: "Grant root access"
in the app calls elevate-service over the Luna bus from inside the
running app, which was already ssh-independent.
Corrected two inaccuracies in the process: webosbrew/repo doesn't exist
(the real project is webosbrew/apps-repo), and the Homebrew Channel has
no "install from file" UI — Browse-and-install or the /install Luna
service are the only ways in, both of which need a URL, not a local
path.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
134 lines
6.3 KiB
Markdown
134 lines
6.3 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
|
|
|
|
This app is not in the official Homebrew Channel repository (that needs a
|
|
review submission — see [docs/development.md](docs/development.md)). Two ways
|
|
to get it onto the TV instead, neither needing SSH or Developer Mode:
|
|
|
|
**Add it as a custom repository (recommended).** The Homebrew Channel can
|
|
browse-and-install from any repository URL you give it, not just the official
|
|
one. Build the ipk, publish it plus a generated repo index, then add that URL
|
|
on the TV:
|
|
|
|
```sh
|
|
npm install # ares-cli, only needed for step 2
|
|
./tools/docker-build.sh # cross-compile; Linux: ./tools/build.sh native
|
|
./tools/build.sh package # -> out/*.ipk
|
|
python3 tools/make-manifest.py --base-url <where you'll host the release assets>
|
|
# -> out/repo.json, out/manifest.json
|
|
```
|
|
|
|
Attach the ipk, `frontend/assets/icon.png` and `out/repo.json` to a release at
|
|
that URL, then on the TV: **Homebrew Channel → ⚙ → Add repository** → paste the
|
|
`repo.json` URL → back to Browse → *Audio Cap* → Install. Full walkthrough,
|
|
including why the URLs have to match exactly, in
|
|
[docs/development.md](docs/development.md#publishing-to-the-homebrew-channel).
|
|
|
|
**Install the ipk directly**, if you do have ares-cli talking to the TV (e.g.
|
|
LG Developer Mode's ssh on port 9922, or a root SSH server you've enabled):
|
|
|
|
```sh
|
|
ares-install --device tv out/org.webosbrew.audiocap_1.0.0_all.ipk
|
|
```
|
|
|
|
## 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.
|