暂无描述

ArtyomV2X 5480e0890a Resolve update failures on existing installs 3 周之前
README.md 5480e0890a Resolve update failures on existing installs 3 周之前
app.py 5480e0890a Resolve update failures on existing installs 3 周之前
gitignore ab1e2d77a1 Initial Commit 4 周之前
index.html a6bff263b4 Resolve load queue status failures 3 周之前
install.sh 5480e0890a Resolve update failures on existing installs 3 周之前
update.sh 5480e0890a Resolve update failures on existing installs 3 周之前

README.md

☕ WeBrake

HandBrake, poured over the web. A self-hosted web UI for HandBrake CLI, built to live inside an Alpine Linux LXC on Proxmox. Upload media from any PC on your network, remux or re-encode it with the entire HandBrake flag surface, watch live progress bars, and download the result — GPU-accelerated when the container has passthru.

Repo: https://gogs.av2x.dev/av2x/WeBrake


One-liner install

Run this inside your existing Alpine LXC (as root). It refuses to run on a Proxmox host by design — nothing is ever installed from the host:

wget -qO- https://gogs.av2x.dev/av2x/WeBrake/raw/master/install.sh | ash

Then open http://<container-ip>:8090.

The installer:

  1. Verifies it's running on Alpine (and not on a Proxmox host — it aborts if pveversion exists).
  2. Installs python3, py3-flask, handbrake (community repo, with edge fallback), and VA-API userspace drivers.
  3. Pulls app.py, static/index.html, and update.sh from this repo — trying branches master then main, accepting index.html at the repo root as a fallback, and validating every download so a Gogs error/login page can never be installed as the app.
  4. Generates a fresh token.json locally — secrets are created on your box, never fetched from nor committed to the repo (it's .gitignored).
  5. Installs and starts an OpenRC service (rc-service webrake start, enabled at boot).

Custom port: WEBRAKE_PORT=9000 wget -qO- .../install.sh | ash

Updating

/opt/webrake/update.sh

Pulls the newest app.py and index.html directly from the repo (same mastermain branch and path fallbacks as the installer), validates the downloads, backs up the old files to /opt/webrake/.backup/, restarts the service — and never touches token.json.


Features

  • Full HandBrake flag coverage — structured controls for General/Container, Source (titles, chapters, angles, start/stop), Video (all detected encoders, presets/tune/profile/level, CQ/bitrate, 2-pass, framerate modes, --encopts), Audio (tracks, encoders, copy masks, mixdown, DRC, gain…), Subtitles (incl. SRT/SSA import, burn-in, forced), Picture (crop, scale, anamorphic, color matrix), and Filters (deinterlace, decomb, detelecine, denoise, sharpen, deblock, rotate, pad, colorspace, grayscale) — plus a raw flags box in Advanced that passes anything else verbatim to HandBrakeCLI, so every current and future flag is reachable.
  • Presets — the container's HandBrakeCLI --preset-list is loaded into a categorized dropdown; custom preset JSON works via --preset-import-file in the raw flags box.
  • Upload → track → download — drag-and-drop upload with a live progress bar, a job queue with per-job status bars (scan %, encode %, fps, ETA, pass number, tail of the encode log), cancel/delete controls, and one-click download of finished files back to the uploading PC.
  • GPU passthru aware — the backend probes /dev/dri + /dev/nvidia* and asks HandBrake which hardware encoders (QSV / NVENC / AMD VCE / VAAPI) actually work; those show up with a ⚡ badge and hardware decoding can be toggled on.
  • Source scanning — one click runs HandBrakeCLI --scan --json and lists titles, resolutions, and audio/subtitle track counts.
  • Modern UI — cream primary with gold accents; dark mode steeps everything in a dark-roast coffee palette with the same gold. Responsive, keyboard-accessible, reduced-motion friendly.

GPU passthru (host configuration — done once, manually)

WeBrake never installs anything on the Proxmox host, but the host must lend the GPU to the container. On the host, edit /etc/pve/lxc/<CTID>.conf:

Intel / AMD (VA-API & QuickSync):

lxc.cgroup2.devices.allow: c 226:* rwm
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir

NVIDIA (NVENC) — host needs the NVIDIA driver; then:

lxc.cgroup2.devices.allow: c 195:* rwm
lxc.cgroup2.devices.allow: c 509:* rwm
lxc.mount.entry: /dev/nvidia0 dev/nvidia0 none bind,optional,create=file
lxc.mount.entry: /dev/nvidiactl dev/nvidiactl none bind,optional,create=file
lxc.mount.entry: /dev/nvidia-uvm dev/nvidia-uvm none bind,optional,create=file

Restart the container. The header of the UI will show ⚡ chips for whatever hardware paths HandBrake can actually use. (Note: Alpine's handbrake package supports QSV/VAAPI paths depending on build; NVENC requires a HandBrake build with NVENC enabled.)

token.json

Created at /opt/webrake/token.json during install, mode 0600:

{
  "api_token": "<generated>",
  "secret_key": "<generated>",
  "require_auth": false,
  "bots": { "my-bot": "<add-your-own-bot-token>" }
}
  • Never in the repo — it's listed in .gitignore, generated locally, and the updater never overwrites it.
  • Set "require_auth": true and restart (rc-service webrake restart) to require a token for all API access. The web UI detects this and highlights the key button in the header — paste the token there, or simply upload your token.json into the panel (it's parsed locally in the browser and only ever leaves as the X-API-Token request header). The token is remembered per-browser.
  • Bots/automation authenticate with header X-API-Token: <token> (any value from api_token or the bots map), e.g.:

    curl -H "X-API-Token: $TOKEN" -F file=@movie.mkv http://ct:8090/api/upload
    curl -H "X-API-Token: $TOKEN" -H 'Content-Type: application/json' \
     -d '{"upload_id":"<id>","options":{"format":"av_mkv","aencoder":"copy","extra_args":"--all-audio --all-subtitles"}}' \
     http://ct:8090/api/jobs
    

API overview

Method Path Purpose
POST /api/upload multipart upload (file)
GET /api/uploads list sources
DELETE /api/uploads/<id> remove a source
GET /api/scan/<id> HandBrake JSON title scan
GET /api/presets preset list from the CLI
GET /api/capabilities encoders + GPU device probe
POST /api/jobs queue an encode (upload_id, options)
GET /api/jobs / /api/jobs/<id> queue & live progress
GET /api/jobs/<id>/log encode log tail
POST /api/jobs/<id>/cancel cancel
DELETE /api/jobs/<id> delete job + output
GET /api/download/<id> download finished file

options keys mirror HandBrake flags (encoder, quality, two_pass, hqdn3d, …) and extra_args is appended verbatim — see FLAG_MAP in app.py.

Paths

Path What
/opt/webrake/ app, UI, updater, token.json
/var/lib/webrake/uploads uploaded sources
/var/lib/webrake/output finished encodes
/var/lib/webrake/jobs job state (survives restarts)
/var/log/webrake.log service log

Remux quick-tip

For a pure remux (no re-encode), set Container to your target, put copy in the audio encoder, and add --all-audio --all-subtitles in Advanced — HandBrake passes streams through where the container allows.


Not affiliated with the HandBrake project. HandBrake is © the HandBrake Team, GPLv2.