jozamudi e3ef51d141 Stop spamming upstream: drop video download from probe, kill re-rolls
- CDN probe no longer downloads 64KB of video (or even a variant
  playlist): one small master-playlist fetch proves reachability.
  State stays OK/DEGRADED, kbps is no longer measured, and the pill/
  panel only show a rate when one exists.
- hianime: 5x getSourcesNew re-roll -> 1 attempt. The enc payload is
  deterministic per data-id (observed identical across calls), so
  re-rolling only hammered the provider.
- anikoto: 2x re-roll -> 1 attempt per server, same reason.

Kept: idle-gated + 30-min degraded backoff from the previous commit,
the single _get retry (protects real user playback from CF blips),
and the origin page check (the 'down' signal). Net upstream traffic is
now what an actual viewer would generate, nothing more.
2026-09-29 17:33:54 +00:00

ani-web

Web front-end for anime streaming: search, browse, and stream anime in the browser (hianime.at primary; anidb.app and anikototv.to as fallbacks). Multi-user, with per-user watch history and HLS playback proxied through the backend. Tuned for phone as much as desktop.

login

Quick start

uv venv .venv
uv pip install --python .venv/bin/python -r requirements.txt
.venv/bin/python -m server.users add <you>   # create your account (one-time)
./run.sh

Open it through your HTTPS proxy (or http://localhost:8321 from the host itself — browsers treat localhost as trusted). run.sh restarts cleanly if the server is already running; logs go to server.log.

Accounts are CLI-created only (no self-signup):

.venv/bin/python -m server.users add <name>    # add user (prompted password)
.venv/bin/python -m server.users rm <name>     # remove user + their history
.venv/bin/python -m server.users list          # list users

Passwords are PBKDF2-SHA256 in server/data/aniweb.db (SQLite, 0600); sessions are signed 30-day HttpOnly SameSite=Lax cookies, Secure via run.sh, so remote plain-HTTP can't hold a session — the HTTPS proxy is the way in. See SPEC.md for the rest.

Features

  • History — server-side and per-user: a new device picks up your exact watch state after login. Entries show poster, progress, and a per-entry delete.

    history

  • Home — continue-watching hero (poster, position, Resume) plus a recently-played grid with progress bars.

    home

  • Search — poster-grid results from the active source; your last 8 searches (per user) in a live-filtering dropdown. Results open the detail view (synopsis, season tabs, filler badges).

    search

  • Player — resume at the saved position, skip intro (MAL timings), dub/sub toggle, playback speed, hide fillers, auto-next with a 5-second countdown, ✓ on completed episodes. Playback goes through a backend HLS proxy (the CDN sends no CORS headers); segments are pulled across parallel byte-range lanes so a slow connection doesn't stall.

    detail

  • Status — the header pill shows one consolidated state — up / slow (KB/s) / down — as a single dot; tap opens a panel with the per-host breakdown, the ~1h CDN trend (dashed slow-threshold line), and origin up/down history. A failure overlay names the CDN when it's the likely culprit.

  • Stats — ?stats: watch minutes, episodes, streaks, sub/dub split, weekday/per-day heatmaps, top-10 shows, top searches (30–365 day windows).

Layout

server/   FastAPI app (app.py), source providers (providers/: hianime,
          anidb, anikoto) over shared HTTP + dispatch (upstream.py)
static/   front-end: index.html, login.html, app.js, hls.min.js (vendored)
tests/    pytest suite: hermetic default, live browser e2e opt-in
docs/img/  README screenshots
run.sh    launch/restart the server (sets ANIWEB_SECURE=1)
SPEC.md   design, verified anidb.app data flow, security + runbook notes

Dev

  • .venv/bin/pytest tests/ -q — hermetic suite against a throwaway server (never touches real data). Live-upstream browser e2e is opt-in: ANIWEB_LIVE_TESTS=1 .venv/bin/pytest tests/ -q (needs playwright chromium).
  • ANI_SOURCE=anidb .venv/bin/python -m server.upstream — live self-check of the anidb fetchers (must be the -m form; plain script execution breaks the providers' relative imports).
  • Everything else (Cloudflare/impersonation, HLS proxy, CDN probe, auth hardening, cache-busting): SPEC.md.
S
Description
No description provided
Readme
8 MiB
0 Stars 1 Watchers 0 Forks
Languages
Python 65.2%
JavaScript 25.9%
CSS 5.9%
HTML 2.1%
Shell 0.9%