|
|
há 3 semanas atrás | |
|---|---|---|
| README.md | há 3 semanas atrás | |
| app.py | há 3 semanas atrás | |
| gitignore | há 4 semanas atrás | |
| index.html | há 3 semanas atrás | |
| install.sh | há 3 semanas atrás | |
| update.sh | há 3 semanas atrás |
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
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:
pveversion exists).python3, py3-flask, handbrake (community repo, with edge fallback), and VA-API userspace drivers.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.token.json locally — secrets are created on your box, never fetched from nor committed to the repo (it's .gitignored).rc-service webrake start, enabled at boot).Custom port: WEBRAKE_PORT=9000 wget -qO- .../install.sh | ash
/opt/webrake/update.sh
Pulls the newest app.py and index.html directly from the repo (same master→main 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.
--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.HandBrakeCLI --preset-list is loaded into a categorized dropdown; custom preset JSON works via --preset-import-file in the raw flags box./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.HandBrakeCLI --scan --json and lists titles, resolutions, and audio/subtitle track counts.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.jsonCreated 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>" }
}
.gitignore, generated locally, and the updater never overwrites it."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
| 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.
| 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 |
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.