HandBrake Web 0.8.1 介绍与选型指南

HandBrake Web 0.8.1 自托管分布式视频转码平台介绍:Web 队列 + 多 worker 用 HandBrakeCLI 批量转码,含架构、特性、快速开始及与 HandBrake GUI、Tdarr、Unmanic、CLI 脚本的选型对比。

HandBrake WebHandBrake视频转码Node.jsFFmpeg2026/10/27

HandBrake Web 0.8.1 介绍与选型指南

目标:用一篇文章讲清 HandBrake Web 是什么、由哪些进程组成、能解决哪些批量转码问题,以及它在 HandBrake GUI、Tdarr、Unmanic 和自写 CLI 脚本之间该怎么选。文中的版本、发布日期、许可证与仓库信息均于 2026-10-27 联网核实,运行参数取自 v0.8.1 源码与官方镜像。

环境信息

  • 操作系统:Ubuntu 22.04 LTS(x86_64),本文命令在该版本验证;同版本源码亦可在 Debian 12、Rocky Linux 9 上构建
  • 实测容器运行时:Docker 29.9.2、Docker Compose v5.6.1
  • HandBrake Web 版本:v0.8.1(2025-12-10 发布,当前最新稳定版)
  • 镜像标签:ghcr.io/thenickoftime/handbrake-web-server:0.8.1、ghcr.io/thenickoftime/handbrake-web-worker:0.8.1
  • 服务端默认端口:9999(v0.8.1 在源码中固定监听,不能通过环境变量修改)
  • 服务端数据目录:/data(内含 config.yaml、handbrake.db、log/)
  • 媒体目录:/video(server 与所有 worker 必须看到完全一致的路径结构)
  • 页面入口:http://<服务器IP>:9999/
  • 演示账号:HandBrake Web v0.8.1 尚无登录体系,页面无需账号即可访问(这也是生产部署必须加反向代理鉴权的原因,见第五章)

一、软件定位与项目来源核实

1.1 一句话定位

HandBrake Web 是一个自托管(self-hosted)的批量视频转码 Web 前端 + 分布式 worker 调度器。它把命令行版 HandBrakeCLI 包在浏览器界面后面:server 负责任务队列、文件浏览、预设管理和 worker 协调,worker 负责真正吃 CPU/GPU 的转码。它不重新实现编码器,转码质量与参数完全由 HandBrake 预设决定。

项目对自己的描述是:"A self-hosted platform to use HandBrake on your headless devices via a bespoke web interface. Harness the processing power of multiple devices to work on a single queue."(在无头设备上通过 Web 界面使用 HandBrake,把多台设备的算力汇聚到一个队列)。

1.2 来源核实(任务书线索纠正)

开工前对项目线索做了联网核对,发现任务书中给出的仓库归属与实际情况不符,实际信息如下:

核对项任务书线索实测结果(2026-10-27)
GitHub 仓库TheCatLady/handbrake-webTheNickOfTime/handbrake-web(TheCatLady/handbrake-web 不存在,GitHub API 返回 404)
最新版本未给出v0.8.1,发布于 2025-12-10 20:08 UTC
维护方未给出个人开发者 TheNickOfTime 维护,不是 HandBrake 官方项目
许可证未给出AGPL-3.0
主语言未给出TypeScript(前端 React 19,后端 Node.js)

项目 README 顶部有明确免责声明:"This project is not related to or part of the official HandBrake development. It simply uses the CLI component of HandBrake under the hood." 也就是说,遇到转码参数、画质、编码器问题时,最终依据仍应是 HandBrake 官方文档,而不是本项目。

1.3 版本节奏与社区活跃度

GitHub Releases 接口返回的最近发布记录如下(只列正式版,prerelease=false):

版本发布日期说明
v0.8.12025-12-10当前最新稳定版,本文实测版本
v0.8.02025-12-090.8 系列首个正式版
v0.7.32024-11-270.7 系列维护版
v0.7.22024-11-15功能修复
v0.7.12024-09-10功能修复

社区数据(GitHub API 实时值):star 806、fork 20、开放 issue 35、默认分支 main,仓库创建于 2024-05-21。发布节奏并不密集,0.7.3 到 0.8.0 间隔约一年;这意味着它适合“够用即可”的自建场景,不适合追求每周新特性的团队。

⚠️ 注意:README 明确写着 "This application is still under heavy development, use at your own risk"。v0.8.1 仍属于功能可用但边界明显的阶段,生产使用前务必先小批量验证,并保留原始视频。

二、核心架构

2.1 组件构成

HandBrake Web 由三个可独立部署的部分组成,官方镜像把前两者打进同一个 server 镜像、把 worker 单独打成另一个镜像:

组件技术栈职责资源特征
Web 客户端React 19 + TanStack Router + Vite + SCSS + Socket.IO Client队列、任务创建、预设、目录监控、worker、设置等页面纯浏览器静态资源,由 server 托管
serverNode.js + Express 5 + Socket.IO + better-sqlite3 + Kysely + chokidar + ffprobe-static任务队列、SQLite 持久化、目录监听、worker 协调、静态页面托管计算量很小,低功耗设备即可
workerNode.js + Socket.IO Client + HandBrakeCLI领取任务、扫描源文件、调用 HandBrakeCLI 转码、回传进度计算密集,建议一台机器只跑一个 worker

server 与 worker 之间不是 REST 调用,而是通过 Socket.IO 长连接通信:server 暴露 /worker 命名空间供 worker 注册,暴露 /client 命名空间供浏览器订阅队列与配置变化。worker 启动时用 WORKER_ID 作为身份注册,server 随后通过 get-properties 反向询问它的 HandBrake 版本和硬件编码能力。

2.2 数据流

一次典型转码任务的生命周期如下:

  1. 在页面 “Queue” 中选择输入文件(只能浏览 server 侧 /video 下已有文件,v0.8.1 不支持上传)与输出路径;
  2. 选择已上传的 HandBrake 预设,提交任务,server 写入 handbrake.db 的队列表;
  3. 有空闲 worker 时,server 通过 Socket.IO 下发任务数据;
  4. worker 用 HandBrakeCLI 扫描源文件并开始转码,期间持续上报百分比、FPS、ETA;
  5. 转码完成后 worker 写文件到 /video 下的输出路径,并回传完成状态;
  6. server 更新队列状态,浏览器实时刷新。

2.3 持久化文件

server 的 /data 目录是唯一需要备份的位置:

文件/目录作用说明
/data/config.yaml应用配置首次启动自动生成,包含路径、预设显示、队列启动行为等
/data/handbrake.dbSQLite 数据库使用 WAL 模式,任务、watcher、worker 属性都在这里
/data/log/日志server 日志与各 worker 回传的任务日志
/data/presets/用户上传的预设从 HandBrake GUI 导出的 .json 预设
/video媒体目录输入与输出都在这里,server 与 worker 的挂载必须一致

💡 技术拓展:分布式任务队列的常见载体不止本文所用的 SQLite。常见方案对比——

方案原理/特点适用场景/取舍
SQLite(本地文件)单文件、零运维、事务可靠单机或小规模分布式,写入并发有限;本文即用此方案
Redis List/Stream内存队列、支持阻塞弹出与消费组高吞吐、需要跨机共享状态,需额外运维
RabbitMQAMQP、路由与确认机制完善多消费者、复杂路由、需可靠投递
Kafka分区日志、可重放大吞吐流水线、事件溯源,延迟偏高

HandBrake Web 选择 SQLite 是因为任务量以“人提交的视频”计,server 只做协调,单文件足够且部署最简单;代价是 server 与 worker 不能各自持有独立数据库,队列状态始终集中在 server。

2.4 硬件编码能力

worker 启动时会解析 HandBrakeCLI --version 的 stderr 输出,自动识别并上报 cpu、qsv、nvenc 三种能力(vcn 字段在 v0.8.1 中恒为 false)。这意味着:

  • Intel 核显/独显的 QSV 可用;
  • NVIDIA 独显的 NVENC 可用;
  • AMD VCN 在 v0.8.1 尚未实现(README 的 Planned Features 中列出);
  • ARM 架构会跳过硬件能力检测,只上报 CPU。

💡 技术拓展:视频硬件编码并非只有一种接口。常见硬件编码后端对比——

后端厂商/平台HandBrake Web v0.8.1 支持特点
QSVIntel支持核显即可用,低功耗,画质略逊于软件 x264/x265
NVENCNVIDIA支持独显编码快、占用低,需驱动与设备直通
VCN/AMFAMD不支持(规划中)AMD 显卡编码,需 Mesa 与 VAAPI 路径
VAAPIIntel/AMD 通用不直接识别Linux 通用接口,本项目未单独探测
VideoToolboxApple不适用macOS 专用
软件 x264/x265CPU始终可用画质/体积最好,速度最慢

本文实际使用软件 x264 完成基线验证;如需硬件编码,优先选 Intel QSV 或 NVIDIA NVENC 的机器,并确认 worker 日志里对应 capability 为 true。

三、核心特性与边界

3.1 已实现的能力

能力说明实测/来源
Web 界面浏览器访问队列、任务、预设、watcher、worker、设置官方截图与源码路由
任务队列创建、暂停、继续、停止、重置、删除、拖拽排序/client 命名空间的 add-job、stop-job、reorder-job 等事件
批量创建对同一目录下多个视频一次性建任务页面 “Bulk Add” 逻辑
预设管理上传、重命名、删除 HandBrake 预设预设来自 HandBrake GUI 导出的 JSON
目录监控创建 watcher,按规则自动建任务chokidar 监听 + watcher 规则表
分布式转码多 worker 并行消费同一队列/worker 命名空间注册与任务下发
硬件加速Intel QSV、NVIDIA NVENCworker 启动能力探测
任务日志每个任务可下载日志HTTP GET /logs/jobs?id=<job_id>

3.2 明确没有的能力(选型时必须知道)

缺失项影响规避方式
用户登录/权限任何能访问 9999 端口的人都能建任务、改配置、删预设必须放在带鉴权的反向代理后,或仅监听内网
网页上传视频只能操作 server 已挂载的 /video 内文件通过 SMB/NFS/rsync 先把文件放进媒体目录
网页创建预设预设必须在 HandBrake GUI 里调好并导出 JSON桌面端 HandBrake 制作预设
AMD VCN 硬件编码AMD 显卡只能用软件编码换 Intel/NVIDIA 机器,或等后续版本
通知/回调没有邮件、Webhook、API 回调外部脚本轮询数据库或日志
REST APIv0.8.1 只有 Socket.IO 与一个日志下载端点自动化需走 Socket.IO 客户端

⚠️ 注意:“没有登录”不是配置项问题,而是 v0.8.1 的功能缺口(README 的 Planned Features 中列有 User Sessions)。不要把 9999 直接暴露到公网。

四、快速开始(最小可用双进程)

4.1 准备媒体与数据目录

server 与 worker 必须看到同样的 /video 结构,否则 worker 会找不到 server 建任务时引用的文件。先在宿主机准备目录:

sudo mkdir -p /opt/handbrake-web/data
sudo mkdir -p /srv/handbrake-web/video/input
sudo mkdir -p /srv/handbrake-web/video/output
sudo chown -R 1000:1000 /opt/handbrake-web/data /srv/handbrake-web/video

/opt/handbrake-web/data 存配置与数据库,/srv/handbrake-web/video 存媒体;1000:1000 换成实际拥有媒体文件的用户,官方镜像默认以该 UID/GID 运行。

4.2 编写最小 compose 文件

在 /opt/handbrake-web 下创建 compose.yaml:

name: handbrake-web-0.8.1-stack

services:
  handbrake-server:
    image: ghcr.io/thenickoftime/handbrake-web-server:0.8.1
    container_name: handbrake-web-0.8.1-server
    user: 1000:1000
    ports:
      - 8128:9999
    volumes:
      - /opt/handbrake-web/data:/data
      - /srv/handbrake-web/video:/video
    restart: unless-stopped

  handbrake-worker:
    image: ghcr.io/thenickoftime/handbrake-web-worker:0.8.1
    container_name: handbrake-web-0.8.1-worker
    user: 1000:1000
    environment:
      - WORKER_ID=worker-01
      - SERVER_URL=handbrake-server
      - SERVER_PORT=9999
    volumes:
      - /srv/handbrake-web/video:/video
    depends_on:
      - handbrake-server
    restart: unless-stopped

关键项说明:

  • image 标签是 0.8.1,不是 v0.8.1(GHCR 上不存在带 v 的标签,实测会报 not found);
  • 宿主端口用 8128,容器内仍是固定的 9999;
  • WORKER_ID 是 worker 的唯一身份,多 worker 必须各不相同;
  • SERVER_URL 在 compose 网络里填服务名,SERVER_PORT 填容器内端口;
  • 两个服务挂载的 /video 宿主机路径必须完全一致。

4.3 启动与验证

cd /opt/handbrake-web
docker compose up -d

预期看到两个容器进入 running:

[+] Running 3/3
 ✔ Network handbrake-web-0.8.1-stack_default     Created
 ✔ Container handbrake-web-0.8.1-server          Started
 ✔ Container handbrake-web-0.8.1-worker          Started

查看 server 启动日志:

docker logs handbrake-web-0.8.1-server 2>&1 | tail -12

预期关键行:

[server] [config] Created the config file at '/data/config.yaml' with recommended defaults.
[server] [config] The config file at '/data/config.yaml' has been loaded.
[server] [database] The database is ready!
[server] Available at 'http://localhost:9999'.

查看 worker 注册日志:

docker logs handbrake-web-0.8.1-worker 2>&1 | tail -12

预期能看到 HandBrake 版本、能力探测和连接成功:

[properties] HandBrake Web Application Version = 0.8.1
[properties] HandBrake Version = 1.9.2
[properties] Capability 'cpu' support = true
[properties] Capability 'qsv' support = false
[properties] Capability 'nvenc' support = false
[properties] Capability 'vcn' support = false
The worker process has started.

最后验证页面可访问:

curl -I http://127.0.0.1:8128/

预期返回 HTTP/1.1 200 OK 与 Content-Type: text/html,浏览器打开 http://<服务器IP>:8128/ 即可看到队列页面。

4.4 导入预设并跑第一个任务

  1. 在桌面版 HandBrake 中调好参数,菜单 Presets → Export → Export Selected Preset,得到 .json 文件;
  2. 在 Web 页面 “Presets” 页上传该 JSON;
  3. 在 “Queue” 页点 “Add Job”,输入文件选 /video/input/ 下的视频,输出选 /video/output/ 下的目标文件名,预设选刚上传的项;
  4. 点队列的 “Start”,worker 日志出现 HandBrakeCLI 调用与进度,页面进度条开始走动;
  5. 完成后到 /srv/handbrake-web/video/output 检查产物:
ls -lh /srv/handbrake-web/video/output/

预期能看到与任务同名的 .mkv 或 .mp4 文件,大小非零。

💡 说明:v0.8.1 的完整裸机安装、systemd 托管、Compose 细节、配置项与命令行参数分别见本专栏后续篇目,本文只保留“能跑起来”的最短路径。

五、适用与不适用场景

5.1 适合

  • 家里有闲置多台机器:旧笔记本、NAS、小主机都能当 worker,server 放低功耗设备即可;
  • 媒体库在 NAS 上:文件已经在 /video 里,不需要上传,只要挂载一致;
  • 想用 HandBrake 的原生预设:不需要学 Tdarr 的插件语法,桌面端调好导出即可;
  • Intel 核显或 NVIDIA 显卡:QSV/NVENC 可直接加速;
  • 需要目录自动转码:watcher 能在文件落入目录时自动建任务;
  • 能接受“无登录、无通知”:内网使用,或自行加反向代理鉴权。

5.2 不适合

  • 公网直接暴露:没有认证,必须自行加鉴权层;
  • 需要网页上传素材:v0.8.1 不支持上传,只能预先放文件;
  • 需要复杂自动化/回调:没有 REST API 和 Webhook,只能写 Socket.IO 客户端或轮询数据库;
  • AMD 显卡硬件编码:VCN 尚未实现;
  • 需要成熟商业支持与 SLA:个人项目,AGPL-3.0,issue 响应无保证;
  • 超大团队多租户:没有用户、配额、审计。

六、同类方案选型对比

6.1 横向对比

维度HandBrake Web 0.8.1HandBrake GUITdarrUnmanic自写 CLI 脚本
形态Web 队列 + 分布式 worker桌面 GUIServer + Node,Web UI单机 Web UI + 插件Shell/Python 脚本
分布式多机支持,多 worker 共享队列不支持支持,多节点单机为主需自己实现
预设来源HandBrake 桌面导出的 JSON内置/自建插件与转码参数插件直接写 HandBrakeCLI 参数
硬件加速QSV、NVENC取决于本机 HandBrakeQSV/NVENC/VAAPI 等取决于 ffmpeg/HandBrake取决于本机
目录监控有 watcher 规则无有有需自己写 inotify
网页上传无不适用无(依赖库目录)无不适用
登录/权限无本机有有无
通知无无有(Discord 等)有自己写
插件生态无无丰富丰富无
许可证AGPL-3.0GPLv2免费但非开源GPLv3自定
上手成本低最低中高中高(要会写脚本)

关键差异解读:

  • HandBrake GUI 画质控制最直接,但必须开着桌面、不能批量排队跨机器;适合“偶尔转几个文件”。
  • Tdarr 功能最全、插件与通知成熟,但概念多、资源占用高,且核心不开源;适合把转码当长期基础设施的玩家。
  • Unmanic 开源、单机 Web UI 友好,插件体系比 HandBrake Web 丰富,但原生分布式能力弱。
  • 自写 CLI 脚本 最灵活,能精确控制 HandBrakeCLI 每个参数,但队列、重试、进度、并发都要自己实现。
  • HandBrake Web 处在中间:比 GUI 多了队列与多机,比 Tdarr/Unmanic 轻、概念少,代价是功能边界明显(无登录、无上传、无 API)。

6.2 选型建议

  • 只有一台机器、偶尔转码 → HandBrake GUI;
  • 多台机器、文件都在 NAS、想用原生 HandBrake 预设、能接受无登录 → HandBrake Web;
  • 需要插件、通知、复杂流转、长期媒体库治理 → Tdarr 或 Unmanic;
  • 有特殊参数组合、需要嵌进现有流水线 → 自写 HandBrakeCLI 脚本。

⚠️ 注意:如果选 HandBrake Web,请先确认三件事——媒体目录能否在所有机器上以同一路径挂载、是否有 Intel/NVIDIA 硬件可用于加速、是否能接受“无认证”并准备好反向代理。

七、参考链接