MANIFESTO · № 01 · rev 2026-07-09
§ 00 — PREAMBLE

WE CAN'T SEE YOU.
NEITHER CAN THEY.

Twiga is the wire under what you already pay for. Your IPTV provider on one end, you on the other, a relay between them that forwards the stream byte for byte and never decodes it. Not a policy on a page. The server has no decoder and no FFmpeg, so there is nothing on it that can read what you watch.

The web player is the first surface, and it's live: a stream you already pay for, playing in a browser tab with no install. Android TV & Google TV are in beta. Same relay, same invariants, on every surface.

§ 01 — IN PLAIN WORDS

The whole thing, end to end.

You already pay an IPTV provider for live channels. Today your TV box, or the app on your TV, talks to that provider directly. The provider sees your home IP. The app on your TV sees the unencrypted stream. Whoever runs the network in between sees the shape of both.

Twiga puts a relay in the middle. You talk to the relay. The relay talks to your provider. Bytes pass through; the relay does not decode them, does not log their contents, does not hold a key to read them. The provider sees the relay's exit address, not yours. You see your channel. That is the whole product.

FIG. 0 — End to end, in four steps
YOU   — browser tab, signed in
  │
  │  ① you ask for a channelTWIGA RELAY   — forwards the stream, never decodes it
  │
  │  ② relay opens an upstream connection for you, from a VPN exitYOUR IPTV PROVIDER   — sees the exit IP, not you
  │
  │  ③ provider sends the live stream back through the relayTWIGA RELAY   — byte-for-byte forward · 0 bytes decoded · no content logged
  │
  │  ④ stream lands in your tabYOU   — the browser decodes it and plays it
  1. Bring your own provider. You hold the subscription. We are not a content service.
  2. The relay forwards bytes. A small Go service with no decoder and no FFmpeg — 0 bytes decoded server-side.
  3. Your IPTV provider sees the relay, never you. The upstream connection leaves from a VPN exit; your home IP is not on it.
  4. The browser decodes it in your tab. H.264 everywhere, HEVC where the browser supports it. When 'playing' shows, it's a real frame — never a black card pretending to load.

Same channels. Same provider. Same bill. Different shape of who can see what.

§ 02 — THE CELL

The cell that stayed empty.

Three crafts have to meet in one place for this to exist: privacy built into the wire, a player that runs in a browser, and live IPTV that actually plays. Each is its own discipline, with its own people. The overlap stayed empty — not because it was impossible, but because building it asks for all three at once.

Twiga sits in that overlap: a blind byte relay for the privacy floor, a browser engine that drives the platform's own decoder for the player, and your own IPTV subscription for the content.

Privacy and good engineering were never the tradeoff. The tradeoff was who would bother.

§ 03 — THESES

Five things we hold to be true.

  1. I.

    PRIVACY IS A PROPERTY OF THE WIRE.

    Not a policy on a page. The relay has no decoder and no FFmpeg; it forwards the stream without reading it — 0 bytes decoded server-side. The behaviour is testable on the wire, with tcpdump.

  2. II.

    THE BROWSER IS THE RIGHT SURFACE.

    Native-app mandates on TV shut out anyone who would rather not install a signed binary on their main screen to watch football. The browser stays the neutral surface — no install, no app-store gatekeeper deciding what plays. The web player is live today.

  3. III.

    THE BROWSER IS THE DECODER.

    The engine demuxes the relayed stream, remuxes it, and hands it to the browser's own hardware decoder through Media Source Extensions. No custom GPU pipeline to drift out of spec — the same decode path the browser uses for everything else, driven correctly.

  4. IV.

    A FAILURE IS HONEST, NEVER SILENT.

    A stall, a gap, a re-tune — they recover without a card. 'Playing' is only ever set on a real, decoded frame read from the platform, so it can't lie over a black screen. And a codec the browser genuinely can't decode says so plainly, instead of spinning forever.

  5. V.

    YOU BRING THE STREAM. WE'RE THE WIRE.

    One source per account, the subscription you already pay for. We don't sell channels, bundle a catalog, or curate a lineup. Your credentials are sealed with a key only you hold, the stream routes through a VPN exit, and we stay out of the picture. You pay us the same way we keep you private: in Monero, from your own wallet — no card, no ID, and nothing on file tying the payment to your account.

§ 04 — THE VAULT

The login only your key opens.

To relay your channels, the relay has to reach your provider — which means your provider login has to exist somewhere. The lazy version keeps it in plaintext, or under a key we hold. Those are the same thing: a key we hold is a key that can be leaked, subpoenaed, or turned. So we arranged not to hold one.

When you add a source, the sealing happens in your browser. Your login is encrypted right there, under a key derived from a secret that never leaves your device. What reaches us is the sealed blob and a public key that lets us confirm it's really you — and nothing that lets us open it. To start a stream, your browser unseals the login just long enough to hand the relay one live connection; the cleartext is never written down, on your side or ours.

FIG. 1 — Where the seal is made, and what we keep
YOU   — your browser, adding a source
  │
  │  your provider login, typed onceTHE SEAL   — happens in your browser, not on our servers
  ├─ a key is derived from a secret only you hold
  ├─ your login is encrypted locally         AES-256-GCM
  └─ that secret never leaves your device
  │
  │  what actually reaches usTWIGA   — stores it, cannot open it
  ├─ the sealed blob      ciphertext · no key here to read it
  └─ a public key         checks it's you · never decrypts

  ◆ a lock we can't pick   ◆ a signature we can only verify

This is the part people are right to be suspicious of, so we'll be exact about the trade: the convenience of a login you never re-enter costs you nothing in custody, because the copy we hold is ciphertext we cannot read. Lose the secret and no one — including us — can open the vault; that is the honest price of us not being able to. What we store is a lock we can't pick and a signature we can only check.

§ 05 — THE PLAYER ENGINE

A media engine for the browser.

The browser ships <video>, Media Source Extensions, and on iOS ManagedMediaSource. None of these is a player. They are surfaces a player has to drive.

The engine relays the live MPEG-TS stream into a worker, demuxes it, and remuxes it into fragmented MP4, which it hands to the browser through MSE. From there the browser's own hardware decoder takes over — decode, A/V sync, present. There is no custom video decoder, no canvas, and no GPU pipeline on the path. The engine's job is to feed the platform correctly and get out of the way.

FIG. 2 — Where the engine sits in the page
BROWSER TAB
  │
  │  persistent HTTP GET · relayed MPEG-TS bytesmpegts.js   — in a Web Worker
  ├─ demux                        PAT, PMT, PES
  ├─ audio plan                   passthrough · transcode · strip
  └─ remux → fragmented MP4
  │
  ▼
MSE / ManagedMediaSource
  │
  │  the browser hardware-decodes, A/V-syncs, presents<video>

The audio problem

Video is the easy half — H.264 plays everywhere, HEVC where the browser supports it. Audio is where IPTV gets awkward: a lot of channels ship AC-3, E-AC-3, or MP2, which most browsers won't decode. The two industry workarounds are dropping the audio entirely, or routing the stream through a server-side transcoder.

Twiga does neither. When the browser can't decode the audio, the engine decodes it in the tab in WebAssembly, re-encodes it to AAC, and muxes the new audio and the original video into one fragmented MP4 on a single clock. The server still never touches the stream. When no decoder is available at all, it keeps the video and drops the audio — never a silent black screen.

FIG. 3 — The audio plan, per channel
AUDIO CODEC   from the demuxed stream
  │
  ▼
audio-plan( )
  ├─ AAC — or AC-3 / E-AC-3 where the platform decodes it
  │      →  PASSTHROUGH   the browser decodes it natively
  ├─ AC-3 · E-AC-3 · MP2 elsewhere
  │      →  TRANSCODE     WASM-decode → AAC → muxed into the same MP4, one clock
  └─ no decoder for itSTRIP         keep the video, drop the audio — never a silent black

Video: H.264 everywhere; HEVC where the browser decodes it.
A codec the browser can't decode fails honestly — it never loops.

The plan is decided once per channel and remembered, so a known-transcode channel skips the doomed native attempt on the next zap — which matters when a provider allows only one upstream connection at a time.

How to check the numbers

The engine is its own truth source: it reports playing only on a real decoded frame, sampled from the platform itself, so it can't claim a picture that isn't there. The live numbers — which exits are up, the Tor path, relay health — are on the status page, read straight from the relay, not cached or polished. The cold-zap target is ≤1.2 s at the 95th percentile; the floor is provider-side, since one upstream connection has to release before the next can open.

§ 06 — THE BLIND RELAY

The wire that cannot read itself.

The relay is the other half. The player is browser-side; the relay is server-side; everything between them is bytes in motion that nobody on the path can interpret.

FIG. 4 — The relay path
YOU   — browser, signed in
  │
  │  request a channelTWIGA RELAY   — Go, single service
  ├─ no decoder · no FFmpeg
  ├─ reads 6 framing bytes per TS packet   sync · PID · adaptation flag · RAI
  ├─ payload never parsed, never decoded
  └─ no stream content in the access log
  │
  │  opaque bytes · whatever shape the provider speaksUPSTREAM PROVIDER   — sees the VPN exit IP, never you

  ◆ never decoded   ◆ never inspected   ◆ no content logged
  • Relayone Go service · no decoder · no FFmpeg
  • Server-side decodenone · 0 bytes decoded
  • Frame inspectionsix framing bytes per MPEG-TS packet · payload never parsed
  • Credentialssealed in your browser with a key only you hold · we store ciphertext we can't open
  • Provider seesthe VPN exit IP, never your home IP
  • Logging on the byte pathnone · access log is timestamp + token, not content
§ 07 — VPN EXITS & TOR

Two paths out. Neither leads back.

A relay that forwards blind still has to reach the outside world twice: once for the live stream, and once for the housekeeping — keeping your channel list fresh, pulling the guide. Both are chances to leave a trail. We route them apart, on purpose.

The stream leaves from a VPN exit. Your provider sees that exit address and nothing behind it — never your home IP. The housekeeping goes out over Tor, so the request that keeps your list current can't be tied back to you, or lined up against anyone else's. The door that carries your video and the door that carries the data about your video never share a return address.

FIG. 5 — Two paths out of the relay
TWIGA RELAY
  │
  ├─ live stream   ──▶  VPN EXIT  ──▶  YOUR PROVIDERthe provider sees the exit IP, never your home IP
  │
  └─ metadata     ──▶  TOR      ──▶  PROVIDER / GUIDE
           playlist refresh · guide data
           no path back · nothing to line up against you

Two doors on purpose: the video and the data about it
never share a return address.

Three things Twiga refuses to see.

— Your key

Your provider login and each stream URL, sealed in your browser under a key only you hold — we keep the locked box, and can't open it.

at-rest →
— The wire

The provider sees Twiga's exit address, never your home IP.

vpn-exit →
— The guide

The guide (EPG) is fetched over Tor; schedule lookups don't trace back to you.

tor →

It is a deliberately boring arrangement. The interesting privacy work already happened one section up, in a relay that can't read what it forwards; this is just making sure the envelope and the postmark don't quietly undo it.

§ 08 — WHAT'S NOT DONE

The parts we haven't finished.

A manifesto that only lists what works is just marketing. Here is what doesn't, yet — said plainly, because you'd find it anyway.

  • Some codecs only play where the browser can decode them. H.264 plays everywhere; HEVC plays where the browser supports it. A browser with no hardware decoder for HEVC, MPEG-2, or AV1 gets an honest error, not a picture — we don't yet ship a software decoder for those in the web player. It's the largest unfinished piece, and we'd rather say so than card the channel and pretend.
  • There's no Apple TV or iPhone app, and we won't pretend one is around the corner. The web player runs today; Android TV & Google TV are in beta. That's the list.
  • It doesn't play your movies or series — Twiga is a live-TV player; the VOD half of your line stays in your provider's app.
  • We check that audio is decoding, not how loud it is. A channel that comes through too quiet or too hot won't be caught automatically yet — loudness measurement isn't in the engine.
  • One connection per source is enforced by a counter, not yet by the structural gate we built for it. Under a rare race the count can slip, and you'd get a short maintenance clip instead of your channel. The fix is written; it isn't switched on.
§ 09 — RECEIPTS

How to check.

your provider login — sealed · not readable by Twiga
live infrastructure/uptime
privacy & data handling/privacy
terms — relay, not provider/terms
changelog — the honest version/journal
support & security[email protected]
counting since2026-03-15