Save a seat

دفتر غرفة العرض

Booth notes

What Leyla does between your files and your screens, for whoever sets it up. Numbers are measured on our own machines; where something isn’t built yet, it says so.

The server

One server, written in Rust, in one container. Its database is PostgreSQL 18, packed inside the server, unpacked into your data folder on the first start, and reached only through a socket in that folder: there is no database port to open, guard or forget. The PostgreSQL build carries its own ICU, so titles sort the way a person expects (“Æon Flux”, “Élite”, “iCarly”, “über”) and the order never shifts under you when the host system updates.

Upgrades of the database go through a verified backup, never in place. Scheduled backups are a folder you name: a database dump, your plugins and a manifest with a checksum for every file.

At rest 0.95 wake-ups a second, 0.000 % of a CPU core, 0.15 database transactions a second, on our test server with nobody watching. It used to be 186 wake-ups and 32 transactions; a box in a cupboard should be quiet.

How a film reaches a screen

Every time a screen presses play, it sends Leyla what it can actually decode: containers, codecs and their profiles and levels, bit depth, audio formats, which HDR signals the display shows, subtitle formats. Leyla plans from that, not from a list of device names, and keeps the exact report with the decision, so a choice it made last month can still be explained.

Play
The file as it is, read in ranges. Nothing runs on the server.
Copy
The picture goes untouched; only the wrapping changes (to HLS with fragmented MP4), and the sound is converted only if the screen can’t play it.
Convert
Only what the screen can’t play is re-encoded, at the quality the connection carries, stepping down and back up as it changes.

New devices are tried with a few tiny clips when they’re idle, and Leyla remembers what each one really plays: a TV that claims a format but fails to play it stops being sent it.

Picture and sound

Sound and picture are checked against each other on every delivery path, every time the way Leyla cuts or restarts a stream changes: fifteen paths, from a plain copy to a resumed conversion with copied surround sound. They are checked both by the timestamps players read and with edit lists applied, because players disagree about edit lists.

Measured the first picture at 0.0 ms from where the source has it on every path, and sound within −0.2 to +0.3 ms of picture.

HDR10, HLG and Dolby Vision go to screens that show them as they are. For a screen that can’t, Leyla tone-maps on the server, so a dark scene stays readable instead of grey. Loudness is measured to EBU R128 and levelled between titles, so one film isn’t a whisper and the next a shout; any device can turn that off.

Hardware and ffmpeg

Leyla uses NVIDIA (NVENC), Intel Quick Sync and VAAPI encoders, but only after testing each one on your own machine, for the shapes of video it will actually be asked to encode. An encoder that fails its test is never used, and Leyla records why; the CPU takes over.

The ffmpeg inside is Leyla’s own build of Jellyfin’s recipe (8.1.3): without the one library that can’t legally ship beside the GPL encoders, without network protocols (it reads files and pipes, and nothing else, so a crafted file can’t make it fetch anything), and compiled with a hardened toolchain. Every ffmpeg runs as a separate, supervised process with a clean environment.

Subtitles

Text subtitles become WebVTT for every screen. Styled ones (ASS/SSA) are drawn in the browser with their own fonts, positions and effects. Picture subtitles from discs (PGS, VobSub) are read into text the first time they’re needed and labelled “recognised text”; a track read with low confidence is held back rather than shown wrong. Nothing is burned into the picture.

The library

A first scan works in the order you’d want: titles show up first, then they become playable, then posters arrive, then everything else. Details, posters and artwork come from plugins: WebAssembly modules that run sealed off from your files, with a budget of instructions, memory and time for every call, installed from a signed index. TMDB, TVmaze, fanart.tv and OMDb work without a key of your own, through Leyla’s gateway.

Intros are found by listening: the passage a season’s episodes share is where the intro is, and a button offers to skip it. Chapters, scrub thumbnails and “up next” are there too. Home learns what your house actually plays from it, and uses that only when it does better than the plain defaults.

From outside the house

There is no Leyla cloud between you and your films. Choose one of three ways out: Leyla opens the door itself (UPnP or NAT-PMP on your router, with its own HTTPS), you reach home over your VPN, or you put it behind a proxy or tunnel you already run. Each app is given every address it might use (home network first, then VPN, then public) and takes the first that answers.

Ten wrong passwords for one account lock that account’s sign-in for fifteen minutes, doubling up to four hours, whichever addresses the guesses come from. A device that has signed in before is judged by its own record, so a stranger guessing can’t lock you out.

A shared house

A TV the household shares asks “Who’s watching?”, with an optional four-digit PIN per person. Signing a TV in means typing a code on your phone, not a password on a remote. Watching together takes a six-digit code: everyone stays on the same second. Coming from Plex, Emby or Jellyfin, accounts, watch history, favourites and playlists come across in one step.

Where it runs

WhereHowWhen
Linux with Docker (Intel/AMD or ARM)One container, amd64 and arm64Now
Synology, QNAP, unRAID, TrueNAS, OpenMediaVault, TerraMasterThe same container, with a guide for eachDuring the beta
Raspberry Pi 4 or 564-bit OS, the arm64 containerDuring the beta
Debian, Ubuntu, Fedora, RHEL.deb and .rpm with a system serviceDuring the beta
Windows, Mac (server)Installer and serviceDuring the beta
Any browserThe web app, served by your LeylaNow
Android phones, Android TVAppNow
Chromecast, Google TVCast from the app or the browserNow
Fire TV, LG, Samsung, Roku, KodiAppsDuring the beta
iPhone, iPad, Mac, Windows, LinuxAppsDuring the beta
Apple TVAppAfter launch

Leyla needs a 64-bit machine; 32-bit ARM isn’t supported. Put its data folder on an SSD if you have one: the database lives there.

Save a seat for the first screening