- app.py + upstream.py -> server/ (relative import, __init__.py) - static/ resolved relative to repo root, works from any CWD - watch history migrated to server/data/history.json - README.md: quick start, features, layout, dev notes - SPEC.md: marked implemented, updated endpoints/run/deviations - ignore *.tar.gz (local curl-impersonate download at repo root)
1.8 KiB
1.8 KiB
ani-web
Web front-end for the ani-cli workflow: search, browse, and stream anime in the browser via anidb.app.
Quick start
uv venv .venv
uv pip install --python .venv/bin/python -r requirements.txt
./run.sh
Open http://localhost:8321. run.sh restarts cleanly if the server
is already running; logs go to server.log.
Features
- Search with poster grid, detail view with synopsis + season tabs
- HLS playback (vendored hls.js), browser ABR across 1080/720/360p
- Dub/sub toggle
- Autoplays the first episode (or resumes the last watched one); if the browser blocks autoplay, a "click to play" overlay appears
- Server-persisted watch history (
server/data/history.json): watch position saved every ~10s, resume where you left off, top-5 "recently played" on the home page — shared across browsers and devices
Layout
server/ FastAPI app (app.py) + anidb.app fetchers (upstream.py)
upstream.py is the ONLY Cloudflare-facing code
static/ front-end: index.html, app.js, style.css, hls.min.js (vendored)
run.sh launch/restart the server
SPEC.md design + the verified anidb.app data flow
Dev notes
- anidb.app is behind Cloudflare; all upstream requests use
curl_cffiChrome TLS impersonation. If that ever stops working, everything is isolated inserver/upstream.py. - The video CDN sends no CORS headers, so playback goes through the
backend HLS proxy (
/stream/{token}), which rewrites playlist URIs. python server/upstream.pyruns a self-check of the fetchers (search → details → episodes → dub stream for Chainsaw Man).- Episode titles are not available: anidb's episode API only returns
{id, number, number2, filler}. Adding titles needs a free MyAnimeList API key.