7.8 KiB
every.channel
A global, disaggregated mesh of relays that turns local ATSC antennas into a coherent, worldwide stream. The stack is Rust-first, MoQ-native, and designed for deterministic chunking so identical broadcasts yield identical data.
Goals
- Free, global access to broadcast TV through user-run relays.
- Deterministic encoding and chunking to make availability a coordination problem.
- Clean layering: capture -> transcode -> MoQ publish -> relay -> client playback.
- Cross-platform clients: Tauri app, CLI, and a static web UI.
Repository layout
crates/ec-core: shared types and determinism profiles.crates/ec-hdhomerun: HDHomeRun discovery and lineup scaffolding.crates/ec-linux-iptv: Linux DVB ingest scaffolding.crates/ec-iroh: iroh transport scaffolding.crates/ec-crypto: stream key derivation helpers.crates/ec-eth: Ethereum-compatible protocol representations and commitments.crates/ec-ts: MPEG-TS timing and table parsing.crates/ec-chopper: deterministic ffmpeg chunking scaffolding.crates/ec-moq: MoQ data model and relay scaffolding.crates/ec-node: node runner (ingest + publish).crates/ec-cli: CLI for discovery and node control.apps/tauri: desktop client shell.apps/tauri/ui: Dioxus web frontend embedded in the Tauri app.docs/USAGE.md: runbook for viewer and ingest pipelines.docs/IROH_EXAMPLES.md: summary of iroh repos/examples used for design.docs/: architecture, roadmap, and MoQ notes.contracts/: Solidity contracts for compact private-chain settlement rails.
Development
Nix:
nix develop
Rust:
cargo build
Runbook:
cat docs/USAGE.md
Git hosting topology:
cat docs/GIT_HOSTING.md
Sovereign forge deploy:
cat docs/DEPLOY_ECP_FORGE.md
OP Stack ecp-forge runbook:
cat docs/OP_STACK_ECP_FORGE.md
NUC PXE rollout (UniFi-only or ProxyDHCP):
cat docs/NUC_UNIFI_NETBOOT.md
WebTransport Watch (MoQ)
Publish (node -> Cloudflare relay):
cargo run -p ec-node -- wt-publish \
--url https://cdn.moq.dev/anon \
--name la-nbc \
--input http://<hdhr-host>/auto/v4.1 \
--control-announce \
--control-endpoint-addr-out /tmp/la-nbc-control-endpoint.json
wt-publish defaults to --passthrough=true so relay and archive retain exact CMAF fragment bytes.
Watch (web):
https://every.channel/watch?url=https%3A%2F%2Fcdn.moq.dev%2Fanon&name=la-nbc
Archive (relay -> CAS objects + JSONL manifests):
cargo run -p ec-node -- wt-archive \
--url https://cdn.moq.dev/anon \
--name la-nbc \
--output-dir /tank/every-channel/archive \
--manifest-dir /var/lib/every-channel/manifests
Replay server (archive -> HLS DVR endpoints):
cargo run -p ec-node -- wt-archive-serve \
--output-dir /tank/every-channel/archive \
--manifest-dir /var/lib/every-channel/manifests \
--listen 0.0.0.0:7788
Control protocol (iroh gossip, relay + direct transport discovery):
# Listener (on node A)
cargo run -p ec-node -- control-listen --gossip-peer <node-b-endpoint-addr-json>
# Announcer (on node B)
cargo run -p ec-node -- control-announce \
--stream-id la-nbc \
--relay-url https://cdn.moq.dev/anon \
--relay-broadcast la-nbc \
--gossip-peer <node-a-endpoint-addr-json>
# Resolver (consumer picks best announced path)
cargo run -p ec-node -- control-resolve \
--stream-id la-nbc \
--prefer direct-first \
--gossip-peer <node-a-endpoint-addr-json>
# Bridge iroh control announcements to every.channel public web list
EVERY_CHANNEL_WEB_UPSERT_TOKEN=<token> \
cargo run -p ec-node -- control-bridge-web \
--directory-url https://every.channel \
--gossip-peer <node-a-endpoint-addr-json>
wt-publish, control-announce, control-listen, control-resolve, and control-bridge-web print both
control endpoint id and control endpoint addr on startup. Use the endpoint addr JSON for
--gossip-peer when bootstrapping.
Default discovery identity:
- If you pass
--stream-id, that exact value is announced. - If you do not pass
--stream-id,ec-nodenow prefers a broadcast-scoped ID when the selected channel exposes usable broadcast metadata. HDHomeRun sources also probe early TS packets to fill missingtsid/program_number, and raw TS inputs can derive identity directly from PAT data. - ATSC PSIP parsing now covers
MGT,TVCT/CVCT,STT,RRT,EIT, andETT.EITandETTare accepted on the PIDs advertised byMGT, not only on the base PSIP PID0x1FFB. - Discovery identity currently consumes
PATplusVCTdata.RRT,EIT,ETT, and fullSTTparsing are available for inspection and future policy, but they do not currently change the default dedupe key beyond the existing broadcast identity fields. - PAT-derived promotion is intentionally conservative: only single-program streams are promoted. If
the probe sees multiple non-zero programs,
ec-nodedoes not guess and keeps the stream source-scoped. - Sources without usable broadcast metadata still fall back to source-scoped IDs.
Ethereum rails:
ec-nodekeeps BLAKE3manifest_ids andmerkle+blake3object proofs on the wire, and also emits Ethereum-compatible ABI commitments for settlement.- Manifests can now carry both local Ed25519 signatures and optional secp256k1 EIP-712 signatures
over
ManifestBody. SetEVERY_CHANNEL_MANIFEST_SIGNING_KEYfor the local signer andEVERY_CHANNEL_ETH_MANIFEST_SIGNING_KEYfor the Ethereum-native signer. - Stream descriptors and iroh control announcements now carry Keccak commitments so broadcast identity, discovery, and manifest settlement share one vocabulary.
- The new
contracts/EveryChannelRail.solcontract is intentionally storage-light: it stores only latest commitment pointers, while full manifests and media stay off-chain on iroh/relays/archive. - Observation consensus now has dedicated Solidity surfaces:
contracts/EveryChannelWitnessRegistry.solandcontracts/EveryChannelObservationLedger.sol. scripts/op-stack/anvil-reality-smoke.shvalidates the observation rail against real archive data pulled fromecp-forge, not only synthetic fixtures.nix/modules/ec-op-stack.nixanddocs/OP_STACK_ECP_FORGE.mddefine the repo-owned OP Stack operator path forecp-forge.- The dev shell now includes
forge,cast,anvil, andsolc, and the repo ships a top-levelfoundry.toml.
Real-capture PSIP checks:
git clone --depth 1 https://github.com/tsduck/tsduck-test /tmp/tsduck-test
EC_REAL_ATSC_SAMPLE=/tmp/tsduck-test/input/test-040.ts \
cargo test -p ec-ts real_atsc_sample_matches_known_psip_shape -- --ignored --nocapture
EC_REAL_RRT_SAMPLE=/tmp/tsduck-test/input/test-052.ts \
cargo test -p ec-ts real_rrt_sample_matches_known_reference -- --ignored --nocapture
Ethereum commitment checks:
cargo test -p ec-eth -p ec-node -- --nocapture
nix develop -c bash -lc 'which forge cast anvil solc && solc --bin contracts/EveryChannelRail.sol >/dev/null'
Observation rail / OP Stack checks:
nix shell .#foundry .#solc -c forge test -vv
nix shell .#foundry .#solc nixpkgs#jq nixpkgs#openssh nixpkgs#curl -c ./scripts/op-stack/anvil-reality-smoke.sh
Coverage:
./scripts/coverage.sh
Build static web:
./scripts/build-web.sh
Deploy to Cloudflare Workers (static site):
./scripts/deploy-workers.sh
Remote website E2E (local publisher -> deployed every.channel web):
./scripts/e2e-remote-website-direct.sh
Remote website E2E (public list/signaling -> website selects stream automatically):
./scripts/e2e-remote-website-directory.sh
Tauri viewer (Dioxus + Trunk):
cd apps/tauri/ui
trunk serve --port 1420 --public-url /
cd ../
cargo run
Status
This repository is intentionally minimal. It captures the initial architecture and scaffold for a MoQ-first network and will expand as proposals are accepted.