Homepage 集成 Unmanic 文件处理监控 Widget:完整配置与源码级原理解析
本指南讲解如何在 Homepage 项目(一个支持 Docker 与多种服务 API 集成的可高度定制主页/导航页/应用仪表盘)中配置 Unmanic Widget,实时展示媒体文件处理任务队列的工作进程数与待处理任务数。读完本文,你将掌握该 Widget 的 YAML 配置方式、三个核心展示字段的含义与取值来源,以及从前端组件到后端代理的完整数据请求链路。
Unmanic Widget 是什么
Unmanic 是一款开源的媒体文件自动处理工具,常用于批量转码、修正音视频元数据等场景。Homepage 为其提供了专门的 Widget 类型 unmanic,可以在主页服务卡片上直接展示 Unmanic 实例的运行状态,无需单独打开 Unmanic 的 Web 界面。
该 Widget 展示三个指标:
| 字段 | 显示含义 | 数据来源 |
|---|---|---|
active_workers |
当前活跃的处理进程数 | Unmanic API workers/status,过滤掉空闲 worker |
total_workers |
worker 总数量 | Unmanic API workers/status 返回数组长度 |
records_total |
待处理任务队列长度 | Unmanic API pending/tasks 返回的 recordsTotal 字段 |
这三个字段的显示文案在 public/locales/en/common.json 中定义:active_workers 显示为 "Active Workers",total_workers 显示为 "Total Workers",records_total 显示为 "Queue Length"。
基础配置
在原文档 docs/widgets/services/unmanic.md 中,Unmanic Widget 的最小配置如下:
widget:
type: unmanic
url: http://unmanic.host.or.ip:port
将该配置块放入服务定义(即 services.yaml 的某个服务条目下)即可生效,例如参考骨架配置文件 src/skeleton/services.yaml 的组织方式:
- My First Group:
- Unmanic:
href: http://unmanic.host.or.ip:port
widget:
type: unmanic
url: http://unmanic.host.or.ip:port
配置要点:
type: unmanic是必需的,声明该 Widget 使用 Unmanic 集成类型;url填写 Unmanic 实例的访问地址(含端口),Homepage 会通过该地址调用 Unmanic 的 API v2 接口;- Widget 允许的字段集合为
["active_workers", "total_workers", "records_total"],即卡片上最多可展示这三个指标。
数据请求链路与源码实现
后端代理与 API 映射
Unmanic Widget 在 src/widgets/unmanic/widget.js 中声明了两组 API 映射:
const widget = {
api: "{url}/unmanic/api/v2/{endpoint}",
proxyHandler: genericProxyHandler,
mappings: {
workers: {
endpoint: "workers/status",
map: (data) => ({
total_workers: asJson(data).workers_status.length,
active_workers: asJson(data).workers_status.filter((worker) => !worker.idle).length,
}),
},
pending: {
method: "POST",
body: "{}",
endpoint: "pending/tasks",
validate: ["recordsTotal"],
},
},
};
从源码可以看出:
- 所有请求都经由统一的
genericProxyHandler(实现在 src/utils/proxy/handlers/generic.js)转发到 Unmanic 的 API v2; workers端点对应 GET{url}/unmanic/api/v2/workers/status,返回数据中的workers_status数组长度即为total_workers,其中idle为 false 的 worker 数量即为active_workers;pending端点对应 POST{url}/unmanic/api/v2/pending/tasks,请求体为空对象{},并通过validate: ["recordsTotal"]校验响应必须包含recordsTotal字段;- URL 模板中的
{url}占位符由 Homepage 的formatApiCall函数替换为配置的url值,且会自动去除末尾的斜杠,见 src/utils/proxy/api-helpers.js。
通用代理处理器
genericProxyHandler 是 Homepage 众多 Widget 共用的后端转发逻辑(src/utils/proxy/handlers/generic.js),对 Unmanic 请求的处理过程如下:
- 根据请求参数中的
group、service、index定位到具体的 Widget 配置; - 从
widgets注册表中取出 Unmanic 的api模板,用formatApiCall填充{url}与{endpoint}生成目标 URL; - 若配置了
username与password,自动附加 Basic Auth 认证头(见 src/utils/proxy/handlers/generic.js),因此对于启用认证的 Unmanic 实例,可在 Widget 配置中补充username/password字段; - 请求方法取自映射定义(Unmanic 的
pending端点为 POST),请求体优先使用映射中声明的body; - 对 HTTP 200 响应执行
validateWidgetData校验,再执行映射函数map完成数据整形(见 src/utils/proxy/handlers/generic.js)。
前端组件渲染
前端组件 src/widgets/unmanic/component.jsx 负责数据获取与展示:
- 通过
useWidgetAPI(widget, "workers")请求 worker 数据(走代理); - 通过
useEffect内直接fetch代理地址/api/services/proxy?endpoint=pending(POST 方法)获取待处理队列数据; - 加载完成前渲染三个占位块(标签分别为
unmanic.active_workers、unmanic.total_workers、unmanic.records_total); - 数据就绪后渲染
active_workers、total_workers与pendingData.recordsTotal三个数值; - 若 worker 请求出错,则展示错误状态容器。
测试用例验证
仓库为 Unmanic Widget 提供了完整的单元测试,用于印证上述行为:
- src/widgets/unmanic/widget.test.js 校验
widget配置对象结构合法; - src/widgets/unmanic/component.test.jsx 模拟返回
{ active_workers: 1, total_workers: 2 }与{ recordsTotal: 7 },断言组件先渲染占位块、随后正确展示三个数值,覆盖了加载态与数据态两种场景。
进阶配置与常见问题
启用认证的 Unmanic 实例
如果 Unmanic 开启了登录认证,可以在 Widget 配置中附加凭据,代理层会自动生成 Basic Auth 请求头:
widget:
type: unmanic
url: http://unmanic.host.or.ip:port
username: admin
password: yourpassword
网络连通性要求
Unmanic Widget 依赖 Homepage 后端服务能够直接访问 url 指向的 Unmanic API v2 接口(路径前缀固定为 /unmanic/api/v2)。请确保:
url中的主机/端口可从 Homepage 部署环境(Docker 容器或 K8s Pod)内访问;- 若使用域名,需保证 DNS 解析可达;若 Unmanic 暴露在局域网,请勿使用
localhost(除非两者运行在同一网络命名空间)。
常见排查思路
- 卡片显示错误而非数据:先确认 Unmanic API 可访问,可尝试在浏览器直接打开
http://unmanic.host.or.ip:port/unmanic/api/v2/workers/status验证; - 待处理队列显示 0:
pending端点通过 POST 请求获取,且依赖响应的recordsTotal字段,若 Unmanic 版本接口结构不一致,数据将无法通过validateWidgetData校验(响应会被标记为 "Invalid data"); - worker 数异常:
active_workers依据worker.idle布尔字段判定,空闲 worker 不计入活跃数。
小结
Unmanic Widget 是 Homepage 服务集成体系中一个典型的"代理转发 + 数据整形 + 组件渲染"三层结构的示例:后端通过 src/widgets/unmanic/widget.js 声明 API 映射与数据转换,由 genericProxyHandler 统一执行转发与校验,前端 component.jsx 负责拉取与展示。只需一段简单的 YAML 配置,即可在主页上将 Unmanic 的处理状态一览无余。若需了解更多 Widget 的通用配置规范,可参阅 docs/widgets/services/index.md 及服务配置文档 docs/configs/services.md。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust4.21 K636- DDeepSeek-V4.1-FlashDeepSeek-V4.1-Flash 是一个多模态混合专家(MoE)模型,拥有 5520 亿骨干参数,并支持最多一百万 token 的上下文长度。该模型原生支持图像和文本输入,并以自回归方式生成文本Python80
jforgamejforgame是一个一站式游戏服务器开发框架。包含游戏服务器开发所需要的各种组件,比如网关,socket服务端与客户端,自定义高效消息编解码,游戏热更新,游戏通用工具等等。包含游戏服,跨服,匹配服,后台管理系统等实现,同时提供大量业务案例以供学习。亦可用于其他socket应用,例如及时聊天等。Java201
fizz-gateway-nodeAn Aggregation API Gateway in Java . FizzGate 是一个基于 Java开发的微服务聚合网关,是拥有自主知识产权的应用网关国产化替代方案,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。Java110
certd开源SSL证书管理工具;全自动证书申请、更新、续期;通配符证书,泛域名证书申请;证书自动化部署到阿里云、腾讯云、主机、群晖、宝塔;https证书,pfx证书,der证书,TLS证书,nginx证书自动续签自动部署JavaScript120
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python300