feat: browser-only screen mirroring prototype

A FastAPI server with two pages and one WebSocket. /mirror captures a
window, screen or tab through the OS-native getDisplayMedia picker; /watch
shows every live mirror as a wall and takes one fullscreen on click. Any
number of sharers and watchers, at the same time.

Media never touches the server: each watcher gets its own RTCPeerConnection
to the sharer, and the Python process only relays JSON. The roster lives in
registry.py, which is transport-free by design -- every operation returns
the envelopes to deliver, so admission, fan-out and teardown policy are all
unit-testable without a socket.

Registry rules worth stating: a signal frame is relayed only along an
existing subscription in either direction; viewer-to-peer traffic is
refused; and teardown is broadcast to every viewer rather than only the
subscribers, because a tile is drawn on stream_added and a viewer that has
not yet subscribed still has a stale tile to clear.

Frontend is hand-written ES modules with no build step and no external
asset. Chromium scales a monitor capture to the capturing window and
requires a secure context, so /mirror detects an insecure origin and prints
the three ways out rather than failing on a button click.

LLM-Generated: true
This commit is contained in:
2026-11-01 16:54:03 -05:00
commit 555fc1c3b4
20 changed files with 3882 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
# mirror — browser-only screen mirroring.
#
# podman build -t mirror .
# podman run --rm -p 8055:8055 mirror
#
# The image serves the app; it does not capture anything. Capture happens in the
# viewer's and sharer's own browsers, so there is no display, D-Bus, or PipeWire
# socket to pass in.
FROM docker.io/library/python:3.13-slim AS builder
ENV PIP_DISABLE_PIP_VERSION_CHECK=1 UV_LINK_MODE=copy
RUN pip install --no-cache-dir uv
WORKDIR /app
COPY pyproject.toml README.md ./
COPY src ./src
RUN uv venv /opt/venv \
&& uv pip install --python /opt/venv/bin/python --no-cache .
FROM docker.io/library/python:3.13-slim
LABEL org.opencontainers.image.title="mirror" \
org.opencontainers.image.description="Browser-only screen mirroring for the local network" \
org.opencontainers.image.source="https://example.invalid/mirror"
# curl is for the HEALTHCHECK only; nothing else in the runtime image reaches out.
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:${PATH}" \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
MIRROR_HOST=0.0.0.0 \
MIRROR_PORT=8055
# Never run the web process as root.
RUN useradd --create-home --shell /usr/sbin/nologin mirror
USER mirror
WORKDIR /home/mirror
EXPOSE 8055
HEALTHCHECK --interval=20s --timeout=3s --start-period=5s --retries=3 \
CMD curl -fsS http://127.0.0.1:8055/healthz || exit 1
ENTRYPOINT ["mirror"]
CMD ["serve"]