[ 录制系统控制台 ] - ADMINISTRATOR MODEREAD-ONLY DISPLAYPUBLIC DISPLAY
_ [ ] X
控制开关:

[ 系统控制菜单 ]

>> {{ isDownloadMode ? '请输入磁力链接 / 投稿视频 / 播放列表 / UP 投稿页:' : '请输入直播数据源地址:' }}

TOTAL: {{ tasks.filter(t => t.taskKind === 'record' && !t.pipelineQueueMode).length }}

锁定 任务名称 (ID) 运行节点 任务类型 运行状态 运行指标 任务操作
{{ task.locked ? '🔒' : '🔓' }}
{{ task.id }}
{{ task.nodeLabel }} {{ task.typeLabel }} 队列中QUEUE 工作中WORK 已暂停PAUSE 处理中WORK 已完成READY 失败FAILED 待命中WAIT 任务结束END 空闲IDLE
>> 暂无录制任务...

TASKS: {{ pipelineTasksInDisplayOrder().length }} · WORKER: {{ pipelineQueueStatus.workersBusy }}/{{ pipelineQueueStatus.workersMax }}

锁定 任务名称 (ID) 抓流与蓄水池 任务编码参数 编码状态 运行指标 任务操作
>> 全局队列空闲,暂无协作编码任务...

TOTAL: {{ tasks.filter(t => t.taskKind === 'transcode').length }}

锁定 源文件名称 处理节点 任务类型 处理状态 运行指标 任务操作
{{ task.locked ? '🔒' : '🔓' }}
{{ task.id }}
{{ task.nodeLabel }} {{ task.typeLabel }} 队列中QUEUE 压制中WORK 已暂停PAUSE 已完成DONE 失败FAILED 空闲IDLE
产出: {{ task.size }}
录制: {{ task.recordedLabel }}
速度: {{ task.speedLabel }}
>> 队列空闲,暂无离线处理任务...

TOTAL: {{ tasks.filter(t => t.taskKind === 'download').length }}

锁定 下载任务名称 运行节点 任务类型 下载状态 运行指标 任务操作
{{ task.locked ? '🔒' : '🔓' }}
{{ task.id }}
{{ task.nodeLabel }} {{ task.typeLabel }} 队列中QUEUE 工作中WORK 处理中WORK 已暂停PAUSE 已完成READY 失败FAILED 空闲IDLE
🎞️ 转码 {{ task.transcodeCurrentIndex }} / {{ task.transcodeTotalFiles }}
速度:{{ task.transcodeSpeed }} · {{ task.transcodeFps }} fps
当前产出:{{ task.transcodeCurrentOutput }} / 总文件:{{ task.transcodeTotalSize }}
已编码: {{ task.encodedSize || task.size }}
待编码: {{ task.sourceCacheSize || '0 B' }}
>> 队列空闲,暂无下载任务...

TOTAL: {{ backupNodes.length }}

锁定 节点名称 存储空间 备份目录 工作状态 操作
{{ isStorageNodeLocked(node) ? '🔒' : '🔓' }}
{{ node.name || node.nodeId }}
{{ node.nodeId }} · {{ node.mode === 'auto' ? '🤖 自动备份' : (node.mode === 'directory' ? '🗂️ 按目录备份' : '🖐️ 手动备份') }}
{{ node.storage || '-' }}
归档文件: {{ node.archiveFileCount || 0 }} · 待处理: {{ node.pending || 0 }}
{{ backupDirectorySummary(node) }} 离线OFFLINE 校验 SHA-256VERIFY 拉取中PULL 待命IDLE
>> 尚未注册边缘备份存储节点...
SYSTEM ONLINE... MESH: ACTIVE
[ 系统日志 ] - 运行状态与调度日志
_ [ ] X
{{ log }}
[ 轻量 Docker 录制任务打包向导 ]
导出普通硬盘录制容器;不包含 K3s、Caddy、Sing-box、Cookies、下载任务、内存推流或录后转码队列。
1. 基础配置与目标

交付方式:

目标边缘节点:

解析引擎 (Engine):

任务名称 (ID):

画质 (Quality):

直播地址:

文件名模板 (Filename Template):

2. 运行与资源限制

工作类型:

断流重试间隔 (秒):

录像封装:

容器内存上限:

3. 编码配置

编码流程:

进程优先级:

视频编码器:

线程数:

质量参数 (CRF):

速度预设:

CPU 上限:

[ {{ editingTask ? (isDownloadMode ? '下载任务参数编辑器' : '任务参数编辑器') : '任务配置向导' }} ]
1. 基础配置与目标

{{ isDownloadMode ? '下载器 (Engine):' : '解析引擎 (Engine):' }}

{{ config.engine.toUpperCase() }}

选择 Pod 工作类型:

任务标识 (ID):

画质 (Quality):

文件名模板 (Filename Template):

Caddy 外部 Nginx HLS 中继

输入 URL 将作为上游 HLS 地址,由集群内全局 Caddy 拉取并转交给录制 Pod。

上游播放列表建议使用相对切片地址;绝对 CDN 地址会由 FFmpeg 按播放列表原地址直接访问。

上游连接协议:

H3 要求 HTTPS 上游,兼容性取决于源服务器。

TLS 证书校验:

HLS 切片时长:

选择内存 HLS 输出时生效。

信任证书域名 / TLS SNI:

仅用于 TLS SNI 和证书身份校验;HTTP Host 仍使用输入 URL 的域名。

警告:跳过证书验证会失去上游身份校验,可能遭受中间人攻击。

上游 Basic Auth 用户名:

上游 Basic Auth 密码:

🔁 Go 远端协作车头

上方“直播地址”只用于服务端绑定一级任务;全局客户端连接保存在“跨地域协作车头”面板。Watcher 收到服务端已创建二级任务 archive.m3u8 的通知后才会拉起 Go 车头。

每组 TS 切片数:

默认 3;用于传输账本和回执分组,编码批次仍由本地队列决定。

客户端最高下载速度:

默认 4M;支持 512K / 4M / 8M。

登录 Cookies

选择 Cookies 配置:

可用于录制、yt-dlp 下载和 rclone 下载;离线转码任务不会使用。

Sing-box 任务出站

选择已登录节点:

仅本任务 Pod 使用该节点;其他任务可同时选择不同出站。单文件离线转码不使用 Sing-box。

当前部署节点没有可用 Sing-box 节点,请先在对应节点保存配置。

代理工作模式:

2. 下载运行模式

编辑下载任务会保留原下载源、下载器和输出目录;保存后立即重启,适合切换 Sing-box 节点或微调运行参数。

硬盘输出路径为 /data/k3s/recordings/downloadings/任务名;内存 HLS 输出路径为 /data/k3s/shm-recordings/downloadings/任务名。

📼 yt-dlp 会先下载并合并视频,再按下方模式输出;内存 HLS 可用和推流相同的分享 URL 观看。
☁️ 输入框可填写 HTTP/HTTPS 文件或目录地址,例如 http://192.168.50.167:10200/video/;也支持 rclone remote:path,后者读取宿主机 /data/k3s/rclone/rclone.conf

目录推荐使用“边下边批量转码”,会逐个视频输出为 原文件名_ed,保留子目录结构;一下载一转码仅适合单个远端视频文件。

HLS 分段时长 (秒):

硬盘视频格式:

源文件缓存位置:

▶ Rclone 与 FFmpeg 参数

Rclone transfers:

Rclone checkers:

视频编码器:

输出格式:

CRF:

Preset:

线程:

转移动作:

目标路径:

推荐填写 /k3s-data/archive-output/子目录;实际由 K3s 映射到 /data/k3s/archive-output,并挂载进 Pod 的 /archive-output。

这些编码参数只作用于 rclone 下载任务,不影响录制任务和离线转码队列。选择 HD630 后,下载 Pod 会独占挂载 VAAPI 设备进行 H.264 硬件编码;“仅复制”模式不会使用 GPU。

选择 Cookies 配置:

默认允许播放列表,可用于一次性下载某个 UP 的公开投稿;系统会写入 download-archive 防重复。未启用自动识别时沿用当前默认 B 站兼容请求头。

代理 Host IP:

代理端口:

2. 任务运行模式

双路模式只支持 STREAMLINK / YTDLP 持续循环监控;HLS 分支使用 COPY,硬盘分支使用下方录像编码设置。

每个任务独立设置 TS 分片、保留时长和 H.264/H.265 编码参数;编码池并发与蓄水池容量由全局 ⚙️ 管理。

🗄️ 协作队列原始分片工作模式(三选一)

⚡ Go 远端协作车头固定使用内存盘全流程:车头将服务端 TS 写入本地内存盘,再由既有协作编码 Worker 认领处理。磁盘镜像编码不适用于此模式。
🌐 服务端源站固定使用内存盘:只维护原始 HLS 与 archive.m3u8,不封批、不认领,也不在本机进行编码。

当本地 upload/ 实际保留的完整批次数达到此阈值时,下一新批次会上传 OCI;后续批次继续按当时的 upload/ 数量独立判断。默认 7;仅对新建的远端对象存储任务生效。

首次引用档案(或更换密钥后)时,Watcher 会上传并下载一段短文本验证对象存储可用性,结果写入 Watcher 日志;密钥不会写入任务配置。

公开直播 URL 始终读取内存盘;会话管家先封存带编号的完整批次,转存 Pod 再原子写入 recordings/pipeline-ts/<任务ID>/<录制段>/ready/,仅 SQLite 标为 READY 的批次才允许 Worker 编码。CMAF 会话级 init.mp4 只镜像一份,每批仅携带 m4s、m3u8 与校验清单。

创建后先观察 Watcher 的 [OBJECT_STORAGE] 探针结果。会话管家按当前 upload/ 批次数逐批决定直通或上传 OCI,并维持按编号连续的两个 ready/ 批次;云端批次校验后才提升到 ready/ 供 Worker 认领。CMAF 的 init.mp4 按录制段仅上传一份;验证或传输失败时不会删除本地原始分片。

原始 TS 不镜像到磁盘;Worker 直接从内存盘读取,待整段编码、合并完成后再按原有规则清理。

{{ config.pipelineRemoteSourceOnly ? '(服务端仅保留这段时间内的原始 TS;客户端断线恢复需在该窗口内追赶)' : (config.taskMode === 'queue_collab' ? '(录制和编码期间整场保留,全部完成后才清理过期切片)' : '(决定切片在内存中的保留时间窗口)') }}

🛡️ 原始 TS 在录制、编码和最终合并期间不会释放;全流程完成后由 Watcher 统一清理过期文件。

3. 录像与编码参数设定

{{ config.taskMode === 'queue_collab' ? '编码池输出方式:' : '编码流程 (Workflow):' }}

抓流 COPY / 编码池按批次转码

进程优先级 (Nice):

{{ config.taskMode === 'queue_collab' ? '编码参数仅作用于该任务;实际并发由全局编码池控制' : '注意: 实时转码将产生较高的宿主机 CPU 负载' }}

视频编码器:

CPU 线程分配 (Threads):

容器 CPU 限制 (Limits):

遵循 K8s 规范: 500m=0.5核;关闭开关即为 none(无限制)

质量参数 ({{ config.taskMode === 'queue_collab' && config.pipelinePrimaryWorkerClass === 'igpu' ? 'QP' : 'CRF' }}):

速度预设 (Preset):

二级编码预览格式:

COPY 免压制不能保证每批从 IDR 关键帧开始,CMAF DVR 已禁用;请选择 H.264/H.265 编码后再启用。

两种格式互斥:CMAF DVR 统一使用 publisher_v4。录制端先写 fMP4;任一编码 Worker 生成私有视频/AAC 分片,由发布器按批次校验、对齐并公开。最终合成遵从“录制音频流”开关。

核显模式只使用单核显 Worker 轮询,待编码达到 2 批才接活;CPU Worker 不参与编码。

仅作用于协作编码队列;核显 Worker 默认强制开启。CPU Worker 开启后会尝试 VAAPI 硬解,再把画面交给 CPU 编码。

每个活跃协作任务会尽量保留 1 个站岗 Worker;自动帮忙与救火 Worker 由全局编码池统一调度。

▶ 离线转码任务配置

目标编码器:

压制分配线程 (Threads):

容器 CPU 限制 (Limits):

关闭开关即为 none(无限制)

质量参数 (CRF):

输出文件名追加后缀:

防止文件名冲突,默认: _ed

队列调度模式:

最大并发数:

断流重试间隔(秒):

封装格式:

关闭“直播推流音频(HLS)”后,录制音频流会自动禁用;开启时两者可分别控制预览和最终成片。

🌐 远端协作源站模式已启用:本机不提供录像与编码参数,也不会写入本地编码成片。仅保留服务端 HLS、会话 archive.m3u8 与远端协作账本。
4. 成片自动归档选项

选择已收录的边缘备份节点:

尚未收录可用边缘备份节点,请先在“备份归档节点管理器”登记节点。

文件名后缀筛选:

视频格式筛选:

两个筛选同时生效;均留空时,备份该任务成片目录中的所有支持视频格式。

备份方式:

所有模式只扫描 <任务ID>/downloadings/ 成片目录;协作编码队列的会话目录和编码批次碎片不会进入备份范围。

🧊 将使用“系统控制 → OCI 归档视频库”内已经绑定的存储桶。Watcher 仅扫描该任务 downloadings/ 中的最终视频;OCI 返回上传成功后,会再次确认本地文件未变化,再删除本机副本。上传失败时会保留本机文件并写入 Watcher 日志,稍后自动重试。
[ 派生录制任务向导 ]
1. 基本参数

任务名称 (ID):

命名模板 (Filename):

提取流媒体 URL (只读):

2. Caddy 内部拉流

该任务通过 ClusterIP 访问全局 Caddy;Watcher 确认 HLS 持续推进后立即启动,并从最早可用切片开始录制。

3. 编码与存储设定

编码流程 (Workflow):

进程优先级 (Nice):

注意: 此操作将产生较高的系统 CPU 负载

视频编码器:

CPU 线程分配 (Threads):

容器 CPU 限制 (Limits):

关闭开关即为 none(无限制)

质量参数 (CRF):

速度预设 (Preset):

输出文件名追加后缀:

例如源文件 name.mkv,后缀 _ed 将输出 name_ed.mkv。

任务持续性:

断流重试间隔(秒):

封装格式:

4. Sing-box 任务出站

选择已登录节点:

该设置仅作用于这个派生录制 Pod。

[ Caddy 网关控制台 ] - 局域网分发与全局接管
1. 当前网关状态 {{ caddyEnabled ? 'CADDY ENABLED' : 'CADDY DISABLED' }}
内部网关
{{ caddyConfig.enabled ? 'ON' : 'OFF' }}
关联 {{ caddyUsageCount }} 个任务
局域网 HTTP
{{ caddyConfig.lanModeEnabled ? caddyConfig.lanHttpPort : '-' }}
/live /recordings /gif
HTTPS 入口
{{ caddyConfig.lanHttpsEnabled ? caddyConfig.lanHttpsPort : '-' }}
证书 / TLS
HTTPS-2 入口
{{ caddyConfig.secondaryHttpsEnabled ? caddyConfig.secondaryHttpsPort : '-' }}
{{ caddyConfig.secondaryHttpsEnabled ? (caddyConfig.secondaryCertificateDomain || '待填域名') : '未启用' }}
HTTP/3
{{ caddyConfig.lanHttp3Enabled ? 'H3' : '-' }}
QUIC / UDP
全局接管
{{ caddyConfig.globalTakeover ? 'ON' : 'OFF' }}
剩余路径转发到 WebUI
2. 网关模式

不开启局域网分发时,Caddy 只作为 K3s 集群内部桥梁,用于派生录制、内部 HLS 路由或拉取远端 HLS 源。

勾选后才暴露 /recordings、/live、/gif 与可选 WebUI 接管入口;不勾选则主界面不显示 Caddy 分发区。

🔗 与文件链接会优先打印 HTTP 地址,绕开 VLC 对自签 HTTPS 证书的校验问题;仅建议在可信局域网使用。

需要宿主机、云防火墙和 docker-compose 同时放行 HTTPS 端口的 UDP,例如 18443/udp。

第二入口复用主入口的路由、认证和证书文件;域名/端口由你填写,Watcher 会同步 Caddy Pod 的 hostPort,但宿主机 Nginx/Cloudflare 转发、云防火墙放行及证书 SAN 仍需随后手动配置。第二端口不能与主 HTTPS 端口相同。

填入已申请证书的域名后,🔗 与文件下载弹窗会优先打印 Caddy 域名 URL;证书申请仍请在宿主机 manager 脚本中完成。

3. 当前 Caddyfile 预览
[ 备份归档节点管理器 ] - Pull Archive Agent

>> 归档节点只主动拉取主节点确认完成的视频并保存,不参与录制、转码、HLS 或下载任务。

🗄️ 注册远程归档节点

节点名称:

节点 ID(可选):

仅允许小写字母、数字、短横线和下划线。

Agent 安装路径(远程宿主机):

视频会自动保存到 {{ backupNodeArchivePath() }}

拉取限速:

SHA-256 读取 I/O 限速:

仅限制校验阶段对边缘硬盘的顺序读取;仍保留完整 SHA-256 校验。

边缘下载网关公网 IP(可选):

用于生成 HTTP 直连下载 URL;网关默认关闭,可在主界面用 🌐 开启。

边缘下载网关端口:

⚡ 一键安装命令

主节点签发随机一次性 Token 后显示;远程服务器复制执行后,Agent 会自动用此凭证向主节点回报心跳。

⚠️ 此命令包含只显示一次的注册 Token;复制到远程服务器执行后,首次注册会自动兑换为可撤销凭证。

主节点随机生成 Token,仅保存哈希;签发成功后这里会显示可直接执行的命令。

归档节点 状态 存储 / 拉取状态 操作
{{ node.name || node.nodeId }}
{{ node.nodeId }}
磁盘: {{ node.storage || '-' }}
队列: {{ node.pending || 0 }} · 拉取: {{ node.transfer || '待命' }}
通信: {{ node.transportMode === 'http' ? 'HTTP 内网' : 'HTTPS' }}
{{ backupNodeScheduleLabel(node) }} · {{ node.timezoneName || '等待节点上报时区' }}
Agent: v{{ node.agentVersion }} {{ node.agentUpdateRequired ? `→ 需更新 v${node.latestAgentVersion}` : '✓ 已最新' }}
最后心跳: {{ formatEdgeNodeTime(node.lastSeenAt) }}
>> 尚未注册归档节点;安装后将在这里显示在线、磁盘和拉取进度。
① 主节点登记
仅登记已完成且已校验的视频
② 节点主动拉取
wget 续传到 .part,按限速下载
③ 校验并回报
大小 / SHA-256 成功后确认归档
[ 归档节点标识色 ] - {{ backupNodeColorNode?.name || backupNodeColorNode?.nodeId }}

此颜色会显示在节点在线状态,并用于标记“本机已删除、仅由该归档节点保存”的视频文件。

在线 · {{ backupNodeColorValue }}
[ 归档节点工作时段 ] - {{ backupNodeScheduleNode?.name || backupNodeScheduleNode?.nodeId }}

时段以边缘备份节点自身时区计算:{{ backupNodeScheduleNode?.timezoneName || '等待节点首次上报' }}

支持跨日,例如 22:00 至 06:00。开始与结束相同无效;需要全天通信请关闭定时。

非工作时段,空闲节点不发送心跳、不领取新任务;已经在工作时段领取的长下载可继续跨时段下载、校验并回报,完成后才进入静默。每次从静默进入工作时段,第一条通信都会先同步主节点当前时段设置。
[ 自动备份规则 ] - {{ backupRuleNode?.name || backupRuleNode?.nodeId }}

🤖 保存后会立即扫描所有历史已完成视频;后续完成的视频也会每分钟补扫一次。

文件名尾缀(可留空)

视频格式(可留空)

例:尾缀 _ed、格式 mkv 会匹配所有 *_ed.mkv;两项均留空即备份全部已完成视频。

[ 按目录备份 ] - {{ directoryBackupNode?.name || directoryBackupNode?.nodeId }}

🗂️ 勾选目录会备份其中所有已完成视频;勾选单个视频只备份该文件。已勾选状态会保存到此归档节点,下次打开仍会显示。

一个归档节点可同时备份多个不同路径;取消备份只移除尚未开始的任务,不会中断已在拉取或校验的文件。

📂 {{ directoryBackupPath }} 已选择 {{ directoryBackupSelections.length }} 项
选择 主节点文件路径 大小 操作
{{ item.typeIcon }} {{ item.name }}
{{ item.relativePath }}
{{ item.isDir ? '全部视频' : formatDirectoryBackupSize(item.sizeBytes) }}
>> 正在读取主节点目录...
>> 此目录下没有可备份的视频或子目录。
[ 手动归档 ] - 选择备份节点

📼 {{ manualBackupFile.relativePath }}

手动任务优先于自动扫描任务;仅可选在线且可用磁盘不少于 15% 的节点。完成大小与 SHA-256 双向校验后,文件名才会标为紫色。

尚未注册归档节点。

[ 边缘待命节点管理器 ] - Agent 注册中心

>> 节点注册后使用安装脚本进入待命;删除注册不会远程删除边缘服务器上的容器或录像文件。

🛰️ 新增边缘待命节点

节点名称:

节点 ID(可选):

只允许小写字母、数字、短横线和下划线。

⚠️ Token 只显示这一次,请立即保存

节点 ID

访问 Token

边缘服务器安装命令

节点 状态 运行信息 操作
{{ node.name || node.nodeId }}
{{ node.nodeId }}
{{ node.revoked ? '已撤销' : (node.online ? '🟢 在线' : '⚪ 离线') }}
主机: {{ (node.status && node.status.hostname) || '-' }}
任务: {{ (node.status && node.status.runningTasks) || 0 }} · 待处理: {{ (node.commands && node.commands.pending) || 0 }}
最后心跳: {{ formatEdgeNodeTime(node.lastSeenAt) }}
{{ edgeNodesLoading ? '正在读取...' : '>> 还没有注册边缘待命节点...' }}
[ 跨地域协作车头 ] - 服务端控制与客户端连接
[ 远端直播探测管理器 ] - 宿主机 systemd
🔭 宿主机独立探测服务

只负责调用 yt-dlp / streamlink 判断直播 URL 的 active、offline、unknown;Watcher 仍负责任务调度。远端断联三次后自动回退本地探测,需人工重启 Watcher 才重联。

状态:{{ sourceProbeTestState.status }} {{ sourceProbeTestState.message }} 当前探测 {{ sourceProbeTestState.activeProbes }} 个
[ Cookies 管理器 ] - 登录凭证档案

>> 保存路径: /data/k3s/shared-data/cookies;任务列表只显示注释,不显示 Cookies 内容。

📜 {{ cookieForm.id ? '编辑 Cookies 配置' : '新增 Cookies 配置' }}

注释 / 站点说明:

Cookies 内容:

注释 状态 操作
{{ profile.comment }}
{{ profile.id }}
{{ profile.hasFile ? '可用' : '文件缺失' }}
>> 还没有保存 Cookies 配置...
[ OCI 对象存储管理器 ] - S3 兼容凭证档案
☁️ 当前档案:{{ objectStorageConfigured ? '已完整配置' : '尚未完整配置' }} 🧪 探针已通过 🧪 探针失败 🧪 待首次任务验证

此处保存 Oracle Cloud Object Storage 的 S3 兼容连接信息。Access Key 仅显示尾号,Secret Key 保存后不回显,也不会进入任务列表或日志。

档案 ID: {{ objectStorageConfig.profileId }} · 后续转存任务直接选择该档案。

📊 当前存储桶用量 · {{ objectStorageConfig.bucket || '未选择存储桶' }}

对象数:{{ objectStorageConfig.usage.objectCount || 0 }}
已用容量:{{ formatDirectoryBackupSize(objectStorageConfig.usage.bytes) }}
统计时间:{{ objectStorageConfig.usage.checkedAt ? new Date(objectStorageConfig.usage.checkedAt * 1000).toLocaleString() : '—' }}

⚠️ 用量查询失败:{{ objectStorageConfig.usage.error || '请查看 Watcher 日志' }}

⏳ Watcher 正在查询对象数与容量;刷新面板后显示结果。

🧨 正在清空存储桶全部对象;完成前请不要创建新的对象存储任务。

✅ 最近一次清空操作已完成,正在刷新桶用量。

统计范围是整个 Bucket,而非仅当前 Prefix;不会显示 Access Key 或 Secret Key。

💳 OCI 本月已出账账本 · 租户级

本月合计:{{ Number(objectStorageConfig.cost.totalCost || 0).toFixed(4) }} {{ objectStorageConfig.cost.currency || '—' }}

{{ ociBillingChineseLabel(item.service) }}:{{ Number(item.cost || 0).toFixed(4) }} {{ objectStorageConfig.cost.currency || '' }}

📡 网络计费用量

本月暂未返回可单列的入站 / 出站计费 SKU。

🖥️ Ampere A1 计费资源量

本月暂未返回 Ampere A1 的 OCPU / 内存计费 SKU。

🪣 对象存储计费条目

本月暂未返回对象存储服务的可单列计费 SKU。

⚠️ {{ warning }}

查询时间:{{ objectStorageConfig.cost.checkedAt ? new Date(objectStorageConfig.cost.checkedAt * 1000).toLocaleString() : '—' }}。OCI 成本数据可能延迟最多约 48 小时。

⚠️ 成本查询失败:{{ objectStorageConfig.cost.error || '请查看 Watcher 日志' }}

⏳ Watcher 正在通过 VPS 动态组身份查询 OCI Usage API…

点击按钮后查询本月 OCI 已出账账单:保留服务总账,并列出网络、A1 与对象存储的计费用量。不读取 S3 密钥,也不会产生或修改云端资源。

>> 正在读取对象存储档案...

1. OCI 存储桶定位

2. S3 兼容连接凭证

🔒 凭证存放在共享数据目录的仅限服务进程读取文件中(0600)。页面刷新后 Secret Key 会自动清空。

🧪 创建首个引用此档案的任务时,Watcher 会上传、下载并比对一段短文本;正式 TS 转存链路启用前,不会上传、下载或删除录制 TS。

最近探针错误:{{ objectStorageConfig.probeError || '请查看 Watcher 日志' }}

[ OCI 归档视频库 ] - {{ archiveLibraryConfig.bucket || '未配置存储桶' }}

🧊 Archive 成片库 · Watcher 通过 OCI 动态组身份管理

归档对象需先解冻才可下载。🧊 解冻、🔗 限时下载链接、📅 定时删除、🗑️ 删除均由 Watcher 执行;浏览器不会接触 OCI 密钥。

{{ archiveLibraryNotice }}

⚠️ {{ archiveLibraryState.error }}

归档对象

{{ archiveLibraryState.objectCount || 0 }} 个

存储桶占用

{{ formatDirectoryBackupSize(archiveLibraryState.bytes) }}

当前 Prefix:{{ archiveLibraryConfig.prefix || '整个桶' }}

最后同步

{{ archiveLibraryState.checkedAt ? new Date(archiveLibraryState.checkedAt * 1000).toLocaleString() : '等待 Watcher' }}

状态:{{ archiveLibraryState.state || 'UNCONFIGURED' }}

⚙️ 归档存储桶设置
类型 归档文件路径 大小 归档状态 / 倒计时 上传时间 操作
🎞️
{{ item.name }}

⚠️ {{ item.lastError }}

🔗 链接有效 {{ formatArchiveCountdown(item.downloadUrlExpiresAt, archiveNowTick) }} 打开
📥 本机下载:{{ archiveLocalDownloadLabel(item) }} · {{ item.localDownloadError }}
{{ formatDirectoryBackupSize(item.size) }}

{{ archiveObjectStatusLabel(item) }}

解冻剩余:{{ formatArchiveCountdown(item.restoreExpiresAt, archiveNowTick) }}

删除倒计时:{{ formatArchiveCountdown(item.deleteAt, archiveNowTick) }}

{{ item.createdAt ? new Date(item.createdAt * 1000).toLocaleString() : '—' }}
{{ archiveLibraryLoading ? '正在读取归档存储桶...' : '>> 暂无归档对象;保存配置后点击 🔄 刷新对象。' }}
共 {{ archiveLibraryState.objects.length }} 个对象 · 每页 100 个 · 第 {{ archiveLibraryPage }} / {{ archiveLibraryPageCount }} 页

最近归档事件

{{ event.at ? new Date(event.at * 1000).toLocaleString() : '—' }} · {{ event.message }}

[ 归档对象定时删除 ]

🎞️ {{ archiveDeleteTarget?.name }}

⚠️ Archive 对象未满 90 天删除可能产生提前删除费用。

[ Sing-box 节点管理器 ] - 出站档案

>> 托管配置写入 /data/k3s/sing-box/managed-nodes.json;原有 JSON 配置仍会同时读取。

🧭 {{ singBoxNodeForm.id ? '编辑托管节点' : '新增托管节点' }}

节点注释:

JSON 配置:

点击 ✏️ 会回填当前实际生效的 outbound JSON;保存时会保留托管节点 tag。

节点 状态 操作
{{ node.comment || node.tag }}
{{ node.type }} · {{ node.file }}
{{ formatSingBoxLatency(node) }}
{{ singBoxLoading ? '正在读取...' : (singBoxError || '>> 还没有可用出站节点...') }}
[ 文件管理器 ] - {{ currentStreamerNode.startsWith('storage:') ? '边缘归档存储' : '录像文件管理' }}: {{ currentStreamerId === '.' ? '根目录 (ROOT)' : currentStreamerId }} · {{ currentStreamerNode === 'local' ? '本地节点' : currentStreamerNode }}

>> 文件管理器已加载目录: {{ currentStreamerNode.startsWith('storage:') ? 'universal-recorder-storage-edge/archive/' + (currentStreamerId === '.' ? '' : currentStreamerId) : (currentStreamerNode.startsWith('edge:') ? '边缘录像网关 / ' + currentStreamerId : (currentStreamerId === '.' ? '/downloads (物理挂载点根目录)' : '/downloads/' + currentStreamerId.toLowerCase())) }} ...

已选 {{ selectedBatchFiles.length }} 个
锁定 选择 类型 文件名称 文件大小 修改时间 操作
{{ file.locked ? '🔒' : '🔓' }} {{ file.typeIcon }} {{ file.typeIcon }}
{{ file.name }}
{{ file.size }} {{ file.time }}
>> 当前目录下无文件或录制内容...
[ 🎵 CMAF 单个音轨修复 ]

{{ cmafAudioRepairFile?.name || '-' }}

请选择只针对这一条音轨的处理方式;同一 `.cmaf-staging` 目录中的其他音轨不会被修改。

[ 归档文件下载 ] - {{ storageEdgeDownload.nodeName }}

📼 {{ storageEdgeDownload.relativePath }}

⚠️ {{ storageEdgeDownload.error }}

① 默认:边缘节点网关直连

浏览器直接连接边缘服务器的专用 HTTP 网关;随机路径无文件、路径错误或网关关闭时均不会返回文件。

② 备用:经主服务 Caddy 反向代理

用于边缘节点网络质量较差时,由主服务作为中转下载入口;边缘公网 IP 与内部网关随机路径不会出现在此 URL 中。

[ 文件链接 ] - {{ fileLinkInfo.name }}

>> {{ fileLinkVideoEntry ? '当前显示 Video.js 浏览器播放器入口;再次点击标题栏 📺 可恢复媒体 URL。' : '以下为唯一的 CF-Caddy 对外媒体 URL,可复制到 VLC 或浏览器使用。' }}

CF-Caddy 文件 URL:{{ fileLinkInfo.name }}

文件大小:{{ fileLinkInfo.size || '-' }}

Nginx 相对路径:/{{ fileLinkInfo.resolvedPath }}

🌐 {{ fileLinkVideoEntry ? 'Video.js Caddy 播放器入口' : 'Caddy 分发 URL(局域网 / 面板接管入口)' }}

🔐 边缘 Nginx Basic Auth 凭据

用户名

密码

VLC 访问时如提示认证,请输入上方 Nginx 用户名和密码。

{{ liveShareInfo.mode === 'encoded-preview' ? '[ 编码片段直播 ] - 已编码 TS EVENT m3u8:' : '[ 直播流分发 ] - 实时流提取面板:' }} {{ liveShareInfo.name }}

>> {{ liveShareVideoEntry ? '当前显示 Video.js 浏览器播放器入口;再次点击标题栏 📺 可恢复原始 URL。' : (liveShareInfo.mode === 'encoded-preview' ? '已生成当前录制段的编码预览地址。' : '已生成当前任务的直播访问地址。') }} 当前运行节点: {{ liveShareInfo.nodeLabel }}

>> 正在与服务节点通信生成 Token 授权 URL,请稍候...
注意:安全 Token 生成失败,原因:{{ liveShareInfo.error }}
基础直播 URL 如已分配,仍可继续用于内网访问。

{{ liveShareVideoEntry ? 'Video.js 浏览器播放器入口' : 'CF-Caddy 媒体 URL' }}

{{ liveShareVideoEntry ? '② Video.js Caddy 播放器入口' : (liveShareInfo.mode === 'encoded-preview' ? '② Caddy 分发 EVENT 直播 m3u8 URL' : '② Caddy 分发 URL (局域网 / 面板接管入口)') }}

{{ liveShareVideoEntry ? '③ Video.js 鉴权播放器入口' : '③ 安全鉴权分发 URL (附带过期验证)' }}

访问授权过期时间: {{ liveShareInfo.expiresText || '-' }}

[ 录制段工具箱 ] - {{ pipelineSessionToolbox.task ? pipelineSessionToolbox.task.id : '-' }}
录制段: {{ pipelineSessionToolbox.session ? (pipelineSessionToolbox.session.startedLabel || pipelineSessionToolbox.session.sessionId) : '-' }}
仅对当前二级任务生效;不会解除任务锁定或影响其它录制段。
🧾 当前工具箱订单
正在读取尚未执行的工具箱订单...
当前没有可撤销的工具箱订单。
{{ order.label }} · {{ order.state }}
{{ order.kind === 'audio_repair_order' ? `已完成 ${order.completedBatches || 0}/${order.requestedBatches || 0} 批;当前批次不会中断` : '尚未被 Worker 接收;撤销后不会删除任何货物或账本' }}

订单一旦被 Worker 接收就不再显示撤销按钮;正在执行的 FFmpeg 批次不会被强行打断。

① 🧰 普通救援收尾

有原始 TS 时强制重新入队,等编码完成后收尾合成;没有原始 TS 时则尝试使用已有编码片段完成合成。适合录制已经结束但没有进入正常收尾的情况。

② 🧾 账本救援(仅账本错乱时使用)

适用于“内存盘仍有原始 TS,但待编码 / 积压显示为 0、或 claim 串到了其它录制段”。它会把当前段已有 part_ 片段和 claim 移入同目录备份,再清空当前段运行账本,由 Watcher 依据原始 HLS/TS 从头重新认领。原始 TS 不会删除;活跃编码、合成或收尾期间会拒绝执行。

③ 🎧 音轨问题处理与成品救援

视频直合会忽略当前二级任务的全部音轨,只合并所有可用视频 m4s;静音合成只处理已发现的问题音轨,没有问题时直接合成。两种方式都会在成品播放验证通过后自动删除二级任务。

视频直合是不可逆的二级任务清理操作,需要二次确认;验证失败时不会删除原始资料、视频片段或账本。

[ Worker 指挥面板 ] - {{ pipelineWorkerState.task || (pipelineWorkerTask ? pipelineWorkerTask.id : '-') }}
1. {{ pipelineWorkerSession ? '当前录制段 Worker 阵列' : '当前任务 Worker 阵列' }} 待编码: {{ pipelineWorkerState.pendingBatches }} 批 · {{ pipelineWorkerState.phase || 'WAITING' }}
>> 正在扫描 Worker 球阵...

紫球=大核 1000m,蓝球=中核 800m,红球=全局智能调度 Worker;金色描边=你手动指派的 Worker 名额。

全局智能调度 Worker 模式已接管:本任务工作单位显示为智能调度 Worker,单 Worker 模式与额外 Worker 指派暂不可用。
当前没有 Worker 正在处理这个任务。
{{ workerSlotLabel(worker.slotType) }} · {{ workerClassLabel(worker.workerClass) }}
{{ worker.worker }} · #{{ worker.sequence }} · {{ formatPipelineSpeed(worker.speed) }}
2. 🧶 智能调度人工批次订单
{{ pipelineWorkerState.superWorkerModeEnabled ? '3.' : '2.' }} 单 Worker 工作模式
{{ pipelineWorkerState.superWorkerModeEnabled ? '4.' : '3.' }} 额外 Worker 指派

新增指派

已指派名额

全局智能调度 Worker 模式已启用;已有额外指派会保留配置,但暂不参与调度。
单 Worker 模式已启用;已有额外指派会保留配置,但暂不参与调度。
暂无手动指派;仅使用首发与自动大核帮忙逻辑。
{{ workerClassLabel(assignment.workerClass) }}
{{ assignmentModeLabel(assignment.mode) }} · ≤{{ assignment.exitBelowBatches }}批退出
占用 Pod: {{ assignmentWorkerLabel(assignment) }}
[ 票据时间线查询 ] - Watcher 状态翻译

只输入会话 ID 会列出该会话的全部批次;点击某一条票据即可进入详细时间线。输入完整票据可直接查询。

⚠️ {{ pipelineTicketLookupError }}

{{ pipelineTicketLookupLog }}
[ 协作编码队列控制台 ] - 全局唯一工作队列
1. 当前队列工作状态 {{ pipelineQueueStatus.pipelineWorkersPaused ? 'WORKERS PAUSED' : (pipelineQueueStatus.schedulerOnline ? 'SCHEDULER ONLINE' : 'SCHEDULER NOT CONNECTED') }}

前端控制面已就绪;调度器后端尚未接入时,这里会保持待连接状态。

任务
{{ pipelineQueueStatus.taskCount }}
抓流 {{ pipelineQueueStatus.recordingCount }} / 等待 {{ pipelineQueueStatus.waitingCount }}
蓄水池
{{ formatPipelineSize(pipelineQueueStatus.bufferUsedMb) }}
上限 {{ formatPipelineSize(pipelineQueueStatus.bufferLimitMb) }}
编码池
{{ pipelineQueueStatus.workersBusy }}/{{ pipelineQueueStatus.workersMax }}
智能 CPU {{ pipelineQueueStatus.superWorkers }}/1 · 核显 {{ pipelineQueueStatus.superIgpuWorkers }}/1
大核 {{ pipelineQueueStatus.bigWorkers }}/{{ pipelineQueueStatus.maxBigWorkers }} · 中核 {{ pipelineQueueStatus.mediumWorkers }}/{{ pipelineQueueStatus.maxMediumWorkers }}
积压
{{ formatPipelineDuration(pipelineQueueStatus.backlogSeconds) }}
{{ pipelineQueueStatus.pendingBatches }} 个待处理批次
已完成批次: {{ pipelineQueueStatus.completedBatches }} 失败批次: {{ pipelineQueueStatus.failedBatches }}
2. 全局抓流蓄水池与编码池参数

TS 分片长度属于各录制任务;直播 URL 的滚动回看窗口在这里统一设置。

抓流与蓄水池

启用全局智能调度 Worker 模式

开启后拆分为两条独立通道:CPU 通道只处理 COPY/libx264/libx265,核显通道只处理 h264_vaapi;两条通道各保留一个智能 Worker,可并行工作。

🛑 当前场上有 {{ pipelineQueueStatus.secondaryTaskCount }} 个二级任务;为避免两套调度账本交叉接管,保存时禁止切换 Worker 模式。

✅ 当前没有二级任务,可以安全切换 Worker 模式。

全局智能调度 Worker(CPU + 核显双通道)

每条通道独立在本通道待编码达到 2 批时由 Watcher 唤醒;每完成一个批次后只在同通道任务间重新选择。直播中降到 1 批时休息,下播后的尾巴仍会收尾;两条通道均支持独立待命与释放。

下一个批次调度策略

💽 “内存直播 + 磁盘镜像编码”仅在全部内存盘二级任务结束后进入智能调度后台;进入后参与当前策略,但不与内存盘任务争抢下一批。

平方权重模式(仅在轮次重置时判定)

CPU 通道: {{ pipelineQueueStatus.superModePhase }} · {{ pipelineQueueStatus.superWorkers }}/1 · 实际 CPU: {{ pipelineQueueStatus.effectiveSuperWorkerCpuLimit }}
核显通道: {{ pipelineQueueStatus.superIgpuWorkers ? 'ACTIVE / STANDBY' : 'IDLE' }} · {{ pipelineQueueStatus.superIgpuWorkers }}/1 · 待处理 {{ pipelineQueueStatus.superIgpuPendingBatches }} 批
CPU 无损换防待生效: {{ pipelineQueueStatus.appliedSuperWorkerCpuLimit }} → {{ pipelineQueueStatus.pendingSuperWorkerCpuLimit || pipelineQueueSettings.superWorkerCpuLimit }},当前批次完成后切换

冷态保持 0 个;发现抓流后启动 1 个,待处理批次增加时自动扩容;全场清空后统一回收。

大核工作单位
(1000m)

中核工作单位
(800m)

以下参数为全部大核和中核 Worker 共用的全局调度参数。

[ 队列全局时间调度器 ] - 离线转码与后处理队列

>> 为所有“队列模式”离线转码任务设置每日工作窗口;“并发模式”任务始终不受此设置影响。

>> 正在读取全局队列调度设置...

队列模式任务

{{ tasks.filter(t => t.taskKind === 'transcode' && t.scheduleMode !== 'parallel' && !['completed', 'failed'].includes(t.status)).length }} 个受控任务

当前窗口状态

{{ !transcodeScheduleStatus.enabled ? '全天开放' : (transcodeScheduleStatus.inWindow ? '窗口已开启' : '窗口外 · 队列挂起') }}

现行时间窗口

{{ transcodeScheduleStatus.scheduleLabel || '全天允许执行' }}

允许开始时间

允许结束时间

同日示例:09:00 → 18:00,只在白天压制。

跨日示例:23:00 → 06:00,从当天夜间持续到次日清晨。

保存启用后,若当前不在时间窗口内,任务会立即挂起等待。

[ 离线压制任务向导 ] - {{ transcodeConfig.batchMode ? '批量队列处理配置' : '单文件手动处理配置' }}
选中处理对象:{{ transcodeFile ? transcodeFile.name : '-' }} 将批量创建 {{ transcodeConfig.batchCount }} 个队列任务
⚙️ 批量队列模式:系统会为每个已勾选视频创建独立转码任务;不能处理的文件会跳过,完成创建后会在任务日志汇总成功和失败清单。输出文件名由系统自动生成。
🧊 轻量封装转换模式:本任务只执行容器格式转换(例如 MKV → MP4),不会再次进行视频压制;CRF、线程、CPU 配额和优先级设置已锁定且不会生效。

视频处理模式 (Vcodec):

压缩参数 (CRF):

核心线程数 (Threads):

资源配额限制 (Limit):

格式说明:500m=0.5核,750m=0.75核,none=不进行限制

优先级 (Nice):

输出封装格式:

预期输出文件名:

说明:任务产出文件将保存在原文件所在目录。

处理调度策略:

最大并发数: