ArtyomV2X 1 mesiac pred
rodič
commit
470015504e
1 zmenil súbory, kde vykonal 146 pridanie a 94 odobranie
  1. 146 94
      README.md

+ 146 - 94
README.md

@@ -1,86 +1,103 @@
 # YAAR — YouTube Auto-Archiver and Retagger
 
-Self-hosted YouTube archival system designed for Proxmox LXC (Alpine Linux).
-Archives YouTube videos as H.264/AAC MKVs with embedded metadata, written
-directly into a Jellyfin-compatible folder structure.
+Self-hosted YouTube archival system for Proxmox LXC (Alpine Linux). Downloads
+YouTube content as H.264/AAC MKV video or audio-only files with embedded
+metadata, written directly into a Jellyfin-compatible folder structure.
+
+Repository: https://gogs.av2x.dev/av2x/yaar
 
 ---
 
 ## What it does
 
-- Web UI for submitting YouTube URLs with one click
-- **Probes** the URL first to pre-fill title, author, and upload date
-- Archives as one of three Jellyfin-native types:
-  - **YouTube video** → `/media/yaar/YouTube/<Channel>/<Title>.mkv`
-  - **TV series episode** → `/media/yaar/Shows/<Series>/Season NN/SNNENN - <Title>.mkv`
-  - **Movie** → `/media/yaar/Movies/<Title> (Year)/<Title> (Year).mkv`
-- Downloads best quality with **H.264 video + AAC audio** (Jellyfin-safe, no transcoding needed)
-- Remuxes to **MKV** with:
-  - Embedded metadata: title, artist/channel, date, original URL, description
-  - Embedded thumbnail
-  - Chapter markers (if available)
-- Writes **NFO sidecar files** for Jellyfin scraping (series and movies)
-- Real-time job queue with progress bars and error reporting
-- Jobs persist across restarts (JSON files in `/opt/yaar/jobs/`)
-- Weekly **auto-update** of yt-dlp via cron
+- Web UI with a job queue — paste a URL and it auto-fetches title, channel, and upload date
+- Archives as one of three types:
+  - **TV series episode** → `Shows/<Series>/Season NN/SNNENN - <Episode>.mkv`
+  - **Movie** → `Movies/<Title> (Year).mkv` *(flat — no per-movie folder)*
+  - **Music** → `Music/<Artist>/<Album>/<Track>.<ext>` *(album optional)*
+- Video downloads prefer **H.264 + AAC** for Jellyfin direct-play (no transcoding), falling back to best available if only VP9/AV1 exists, then remuxing to MKV
+- Music downloads to a selectable audio format (m4a, opus, mp3, flac, aac, wav)
+- Embeds metadata (title, channel/artist, date, URL, thumbnail, chapters) and writes **NFO sidecars** for Jellyfin scraping of series and movies
+- Live job queue with progress bars, speed/ETA, retry, and error reporting
+- Jobs persist across restarts; queue survives service and container reboots
+- Discrete per-event logging (boot, mount checks, per-job archive logs)
+- Weekly automatic yt-dlp update via cron, plus a one-command app updater
 
 ---
 
 ## Requirements
 
-- Proxmox VE 7+ (any version with LXC support)
-- Alpine Linux 3.20 LXC template
-- A storage volume or directory on the host for media (bind-mounted into the container)
+- Proxmox VE 7+ with LXC support
+- An Alpine Linux 3.20 LXC container
+- A media directory on the host (your Jellyfin library) to bind-mount into the container at `/nas/jellyfin`, containing `Movies/`, `Shows/`, and `Music/`
 
 ---
 
 ## Quick start
 
-YAAR installs entirely from **inside your existing Alpine LXC container**.
-The only thing done on the Proxmox host is attaching the Jellyfin bind-mount.
-
-### Step 1 — Attach the bind-mount in Proxmox (one-time, host only)
+YAAR installs entirely **inside your Alpine LXC container**. The only host-side
+step is attaching the Jellyfin bind-mount.
 
-See `proxmox-mount.md` for the full guide. In short:
+### Step 1 — Attach the media bind-mount (Proxmox host, one-time)
 
-**Web UI:** Container → Resources → Add → Mount Point
-- Host path: `/mnt/nas/jellyfin` (your NAS location on the host)
-- Container path: `/nas/jellyfin`
-- Read-only: No
+See `proxmox-mount.md` for the full guide. In short, on the Proxmox host shell:
 
-**Or via the Proxmox host shell:**
 ```sh
 pct set <CTID> -mp0 /mnt/nas/jellyfin,mp=/nas/jellyfin
 pct restart <CTID>
 ```
 
-### Step 2 — Get YAAR into the container
+Replace `/mnt/nas/jellyfin` with wherever your media lives on the host. The
+`mp=/nas/jellyfin` target must stay exactly as-is — YAAR expects that path.
+
+Or via the web UI: Container → Resources → Add → Mount Point, host path
+`/mnt/nas/jellyfin`, container path `/nas/jellyfin`, read-only off.
+
+### Step 2 — Install (inside the container)
+
+One line, run as root inside the container:
 
 ```sh
-# From the Proxmox host:
-pct push <CTID> yaar.tar.gz /root/yaar.tar.gz
+curl -fsSL https://gogs.av2x.dev/av2x/yaar/raw/master/setup.sh | sh
+```
 
-# Or via scp from any machine:
-scp yaar.tar.gz root@<container-ip>:/root/
+Or trigger it from the Proxmox host without entering the container:
+
+```sh
+pct exec <CTID> -- sh -c 'curl -fsSL https://gogs.av2x.dev/av2x/yaar/raw/master/setup.sh | sh'
 ```
 
-### Step 3 — Run setup inside the container
+`setup.sh` installs Python, ffmpeg, yt-dlp, Flask and Gunicorn, the app files,
+an OpenRC service, the weekly yt-dlp auto-update cron, and the `yaar-update`
+command. It refuses to run on the Proxmox host and fetches any files it needs
+directly from the repo.
+
+When it finishes, open `http://<container-ip>:7474`.
+
+---
+
+## Updating
+
+Pull the latest code, redeploy, and restart — with automatic backup and
+rollback if the new code fails to start:
 
 ```sh
-pct enter <CTID>          # enter the container, or ssh into it
-tar xzf /root/yaar.tar.gz -C /root/
-sh /root/yaar/setup.sh
+yaar-update              # update app + restart service
+yaar-update --deps       # also upgrade yt-dlp / Flask / Gunicorn
+yaar-update --reboot     # reboot the whole container after updating
 ```
 
-`setup.sh` detects if it's accidentally run on the Proxmox host and exits
-immediately — it will not proceed unless it's running inside a container.
+Or the self-contained one-liner (always fetches the newest update logic too):
+
+```sh
+curl -fsSL https://gogs.av2x.dev/av2x/yaar/raw/master/update.sh | sh
+```
 
-The script installs:
-- Python 3, pip, venv
-- ffmpeg
-- yt-dlp (latest), Flask, Gunicorn
-- OpenRC init script (`/etc/init.d/yaar`)
-- Weekly yt-dlp auto-update cron
+The updater downloads both app files to a temp location and only deploys if
+both succeed, backs up the previous versions to `/opt/yaar/backups/` (keeping
+the last 5), and restarts the service. If the service fails its health check on
+the new code, it automatically restores the previous version so YAAR is never
+left down.
 
 ---
 
@@ -93,108 +110,143 @@ rc-service yaar restart
 rc-service yaar status
 ```
 
-Logs:
-```sh
-tail -f /opt/yaar/logs/yaar.log       # Application log
-tail -f /opt/yaar/logs/gunicorn.log   # Web server log
-```
-
 ---
 
 ## Jellyfin integration
 
-Point Jellyfin at the three library roots:
+Point Jellyfin at the library roots inside your mounted media directory:
 
 | Library type | Path |
 |---|---|
-| Movies | `/media/yaar/Movies` |
-| Shows | `/media/yaar/Shows` |
-| Other (YouTube) | `/media/yaar/YouTube` |
+| Movies | `/nas/jellyfin/Movies` |
+| Shows | `/nas/jellyfin/Shows` |
+| Music | `/nas/jellyfin/Music` |
 
 For the **Shows** library, enable NFO metadata reading so episode details from
-yt-dlp populate correctly. For YouTube videos, the library type "Other Videos"
-or "Shows" both work — choose based on preference.
+yt-dlp populate correctly. Movies use a flat layout (`Movies/<Title> (Year).mkv`
+with a matching `.nfo` sidecar), which Jellyfin scrapes by filename.
 
 ---
 
 ## Format choices
 
+**Video (series / movie):**
+
 | Setting | Value | Why |
 |---|---|---|
 | Video codec | H.264 (avc1) | Universal Jellyfin direct-play, no transcoding |
 | Audio codec | AAC (mp4a) | Universal, no transcoding on any client |
 | Container | MKV | Supports metadata, chapters, thumbnails |
-| Quality | Best available H.264 | yt-dlp format selector: `bestvideo[vcodec^=avc1]+bestaudio[acodec^=mp4a]` |
+| Selector | `bestvideo[vcodec^=avc1]+bestaudio[acodec^=mp4a]/…/best` | H.264+AAC first, graceful fallback |
+
+If a video is only offered as VP9/AV1, yt-dlp falls back to the best available
+stream and still remuxes to MKV. Jellyfin may transcode those on weaker clients
+— a YouTube-side limitation, not a YAAR bug.
 
-If a video is only available as VP9/AV1 (e.g. high-res YouTube uploads), yt-dlp
-falls back to the best available VP9 + audio, then remuxes to MKV. The web UI
-shows whatever was actually used.
+**Music:** selectable per job — `m4a` (AAC, default), `opus`, `mp3`, `flac`,
+`aac`, or `wav`. Note that YouTube source audio is itself lossy (AAC/Opus), so
+`flac`/`wav` won't add quality, only file size.
 
 ---
 
-## File structure
+## File & folder layout
 
 ```
 /opt/yaar/
   web/
-    app.py           ← Flask application
-    templates/
-      index.html     ← Web UI
-  venv/              ← Python virtualenv
+    app.py                ← Flask application
+    templates/index.html  ← Web UI
+  venv/                   ← Python virtualenv
+  jobs/                   ← Persisted job JSON (queue survives restarts)
+  backups/                ← Previous app versions kept by yaar-update
+  update.sh               ← Update script (also runs as `yaar-update`)
   logs/
-    yaar.log
-    gunicorn.log
-    access.log
-  jobs/              ← Persisted job JSON files
-
-/media/yaar/
+    yaar.log              ← Unified log (everything)
+    gunicorn.log          ← Web server log
+    access.log            ← HTTP access log
+    log_boot/<ts>.log     ← One file per service start
+    log_mount/<ts>.log    ← One file per mount check
+    log_archive/<id>.log  ← One file per archive job (named by video id)
+
+/nas/jellyfin/            ← Your bind-mounted media (mp0)
   Movies/
-    Fantastic Voyage (1966)/
-      Fantastic Voyage (1966).mkv
-      Fantastic Voyage (1966).nfo
+    Fantastic Voyage (1966).mkv
+    Fantastic Voyage (1966).nfo
   Shows/
     Kurzgesagt/
       Season 01/
         S01E01 - The Egg.mkv
         S01E01 - The Egg.nfo
-  YouTube/
-    Veritasium/
-      Does Planet 9 Exist.mkv
+  Music/
+    Nujabes/
+      Modal Soul/
+        03 - Luv(sic) Part 3.m4a
 ```
 
 ---
 
 ## Configuration
 
-Environment variables (set in `/etc/yaar.env`):
+Environment variables (in `/etc/yaar.env`):
 
 | Variable | Default | Description |
 |---|---|---|
-| `YAAR_BASE` | `/opt/yaar` | App, logs, jobs directory |
-| `YAAR_MEDIA` | `/media/yaar` | Root media output directory |
+| `YAAR_BASE` | `/opt/yaar` | App, logs, jobs, backups directory |
+| `YAAR_MEDIA` | `/nas/jellyfin` | Root media output directory (the mp0 mount) |
 | `YAAR_PORT` | `7474` | Web UI port |
 
+After changing any of these, restart: `rc-service yaar restart`.
+
 ---
 
-## Updating yt-dlp manually
+## Logs
 
 ```sh
-/opt/yaar/venv/bin/pip install --upgrade yt-dlp
-rc-service yaar restart
+tail -f /opt/yaar/logs/yaar.log                 # everything, live
+ls /opt/yaar/logs/log_archive/                  # per-job archive logs
+cat /opt/yaar/logs/log_archive/<videoid>__*.log # a specific job's full trace
 ```
 
+Archive logs are named by YouTube video id, so you can find a job's log by URL
+without knowing its internal id.
+
 ---
 
 ## Troubleshooting
 
-**Download fails with "Sign in to confirm your age"**
-YouTube sometimes requires cookies for age-restricted content. Export cookies from a logged-in browser and pass them to yt-dlp via `--cookies` in `build_ydl_opts()` in `app.py`.
+**Queue is frozen / blank, console shows a SyntaxError**
+The served `index.html` is out of date. Run `yaar-update` and hard-refresh the
+browser (Ctrl+Shift+R) to clear the cached script.
 
-**H.264 format not available / falls back to VP9**
-Some YouTube videos are only available in VP9. YAAR will still download and remux, but Jellyfin may transcode on lower-powered clients. This is a YouTube limitation, not a YAAR bug.
+**Mount banner is red / downloads fail immediately**
+`/nas/jellyfin` isn't mounted or isn't writable. Confirm the mp0 bind-mount is
+attached and the container was restarted after adding it:
+```sh
+ls /nas/jellyfin        # should list Movies/ Shows/ Music/
+```
+For unprivileged containers with permission issues, map the mount UID/GID:
+`pct set <CTID> -mp0 /mnt/nas/jellyfin,mp=/nas/jellyfin,uid=0,gid=0`.
+
+**Download fails with "Sign in to confirm your age"**
+Age-restricted videos need cookies. Export cookies from a logged-in browser and
+add a `--cookies` reference in `build_ydl_opts()` in `app.py`.
 
-**Container can't write to media directory**
-Ensure the bind mount path exists on the host and the container has write permission. For unprivileged containers, the UID/GID mapping may need adjustment: `pct set <CT_ID> --mp0 /host/path,mp=/media/yaar,uid=0,gid=0`.
+**Falls back to VP9 instead of H.264**
+Some videos are only published in VP9/AV1. YAAR still downloads and remuxes;
+Jellyfin may transcode on weaker clients. YouTube-side limitation.
 
 **Port already in use**
-Edit `YAAR_PORT` in `/etc/yaar.env` and restart the service.
+Change `YAAR_PORT` in `/etc/yaar.env` and restart the service.
+
+---
+
+## Manual yt-dlp update
+
+The weekly cron handles this automatically, but to force it:
+
+```sh
+/opt/yaar/venv/bin/pip install --upgrade yt-dlp
+rc-service yaar restart
+```
+
+Or just `yaar-update --deps`, which upgrades yt-dlp, Flask, and Gunicorn together.