Skip to Content
Why VioraManifesto

Why we built Viora

The itch

Every mainstream video-calling product is a funnel into someone else’s infrastructure. Your call is transcoded on their SFU, your presence is a row in their database, and the “free” tier is free because the metadata is the product. Even the privacy-forward options route media through relays you don’t control and ship as monolithic apps you can’t fully inspect.

We wanted the opposite defaults:

  • The media path is nobody’s business but the two people talking. No SFU, no MCU, no “we don’t look at your calls, promise” - just SRTP between two phones.
  • The backend fits in your head. One Rust file of room bookkeeping, no storage, no accounts. If you can scp a binary you can host it.
  • The app tells you the truth. When the encoder falls back to software, when the radio can’t sustain the bitrate, when the SoC is thermally throttling - that should be visible, not hidden behind a spinning “reconnecting…” toast.

Viora started as a way to make a genuinely private 1:1 call between two specific phones and grew into a testbed for how good a hand-built WebRTC client can get on real Android hardware.

What we optimised for

Privacy through topology, not policy

A mesh / peer-to-peer call has an unavoidable property: the bytes go straight from one endpoint to the other. There is no server-side decrypt point because there is no server in the media path. The signaling server only ever sees:

  • room codes (arbitrary strings the users pick),
  • display names,
  • the SDP and ICE payloads needed to establish the connection,
  • chat messages (relayed, not stored).

It never sees a decoded frame, and it holds nothing after the WebSocket closes - rooms are an in-memory HashMap that is dropped when the last peer leaves.

Self-hosting as a first-class mode

The server is axum + tokio, compiles to a single static binary, and needs exactly two environment variables (HOST, PORT). There is no database to provision, no migration to run, no secret to rotate. The deployment guide is essentially “copy the binary, run it behind a TLS terminator.”

Doing the WebRTC work properly

Most of the engineering in this repo is in the seams that tutorials skip:

  • Codec negotiation and SDP munging so H.265 can actually run at 4K instead of the 720p level the SDK advertises, and so Opus runs in stereo with FEC.
  • A real audio pipeline: three capture modes, a native RNNoise post-processor, a user gain stage, echo-cancellation trade-offs made explicit, and a hardware audio stack that rebuilds itself between calls when the mode needs a different capture profile.
  • Camera adaptation and recovery: the capturer that survives the app being backgrounded, another app grabbing the camera, or a device that can’t sustain the requested format.
  • Crash and stall resilience: ICE restart on a dropped route, lifecycle-correct capture pausing, a shared OkHttp client so a call can’t leak a thread pool, and @Synchronized teardown so a fast hang-up-and-redial can’t race.

Being kind to old phones

The reference devices are a Galaxy S9+ (2018) and a Pixel (2025). That spread forces good behaviour: the S9+ has a strict hardware HEVC encoder that starves 4K unless the bandwidth estimator is seeded; the Pixel’s front camera can’t actually capture the 4K its rear camera advertises. Both cases are handled rather than wished away.

What Viora is not

Deliberate non-goals

  • It is not a meetings product. Today a call is exactly two people. A mesh multi-party design is planned (hard cap of 5), but Viora will never grow an SFU - past a handful of people, a mesh is the wrong tool and so is this app.
  • It is not turn-key hosted SaaS. There is no sign-up, no billing, no account recovery. You bring your own server.
  • It is not a security product with a threat model and an audit. The privacy story is structural (P2P media, no persistence) but the app uses Google’s public STUN servers, has no TURN fallback, and has not been formally reviewed. Treat it as a well-built hobby client, not Signal.
  • It is not cross-platform. There is a minimal 2-person web client in server/public/ for testing, but the product is the Android app.

Where it goes next

The roadmap is short and honest: finish mesh multi-party (3–5 people, demand-driven video), then a TURN fallback for symmetric-NAT networks. Everything else is polish.

Continue to How Viora compares →