23 Commits
Author SHA1 Message Date
kira1928 ad81d2b9cf fix: 根据 review 收紧录制器停止与 E2E 清理 2026-08-18 01:10:20 +09:00
524f3329c7 fix(test): 修复 E2E active_recordings 泄漏并终止渲染失败的录制重试
E2E 中 update-full/update-workflow 的 "active_recordings 为 0" 断言偶发失败,根因有三:

1. fixture 模板 out_put_tmpl 使用了 live.Info 上不存在的字段 {{.StartTime}},
   导致每次文件名渲染都失败(自 #1061 起)。改为合法的时间戳写法。
2. recording.spec.ts 通过 UI 添加的 dev 直播间从不清理;workers=1 下所有 spec
   共用同一后端进程,残留房间被 mock 持续判定为在播,泄漏进后续 spec 的断言。
   增加 afterAll 统一删除全部直播间。
3. 文件名渲染失败后 recorder 会以 5s 间隔无限重试、刷屏且被计入活跃录制数。
   现改为派发一次 LiveEnd 交由 manager 回收(与 stopRetryForExplicitOffline
   同构),避免无意义的重试风暴。

并将两处 active_recordings 断言改为轮询,容忍录制器回收的短暂延迟。

via [HAPI](https://hapi.run)

Co-Authored-By: HAPI <noreply@hapi.run>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-17 22:51:54 +09:00
Joftal 589586837e chore(config): 移除 config.yml 中弹幕相关冗余注释 2026-08-11 11:28:52 +08:00
Joftal c88bfb3495 fix(test): 修复云盘上传设置测试断言
- 使用 .first().toBeVisible() 替代 toHaveCount(1)
- 页面有多个包含「云盘上传」的元素
2026-08-06 14:10:50 +08:00
Joftal 82391d8afa fix(test): 更新云盘上传设置测试用例
- 云盘上传 UI 已启用,更新测试期望值为 1
2026-08-06 11:54:17 +08:00
Joftal 597853cd6c chore(test): 更新测试配置模板
- tests/e2e/fixtures/test-config.template.yml 新增 openlist 凭据字段
2026-08-06 10:52:17 +08:00
kira1928andClaude Fable 5 d5d8b797e4 fix: 处理第三轮 code review 意见(并发安全、路径语义一致性、后处理等待)
Gemini 高危:
- FFmpegAsyncInit 增加 ffmpegInitRunning CAS 守卫,并发调用(如 e2e
  多次 reinit)时只有第一个生效,避免并发 tool.Install()
- setFFmpegStatus 用 ffmpegStatusMu 串行化存储、变化通知与回调执行,
  保证订阅者看到的状态顺序与实际更新顺序一致
- ./ffmpeg 兜底改为 LookPath 任何失败都尝试:Unix 下当前目录不在 PATH,
  返回 ErrNotFound 而非 ErrDot,原来只处理 ErrDot 在 Unix 上不生效;
  该逻辑收敛到 utils.LookupSystemFFmpeg 供状态检测与实际查找共用

Gemini 中危:
- tool.Install() 前检查 ctx.Err(),程序退出中不再发起耗时下载

Codex P2:
- 配置了无效 ffmpeg_path 时不再走 remotetools 下载(下载了实际录制也
  不会用),直接置 not_found 并提示修正配置,状态与实际查找语义一致;
  e2e 相应改为 ffmpeg_path 留空 + BILILIVE_IGNORE_SYSTEM_FFMPEG=1
  环境变量屏蔽系统 FFmpeg(CI 预装 ffmpeg,无法用真实 PATH 模拟)
- 等待逻辑上移为 tools.WaitFFmpegAsyncInitDone 供多处复用:ffmpeg
  parser、pipeline 后处理阶段(convert_mp4 / burn_subtitles /
  custom_command)及 recorder 的 legacy custom commandline 在获取
  FFmpeg 路径前等待后台初始化结束,短直播后处理不再因下载未完成而失败

Copilot:
- WaitForToolsInit 轮询改用 time.NewTicker 复用计时器
- FFmpegBanner 初始状态查询失败时打印 console.warn,不再静默吞掉
- mock server 检查 w.Write 错误,客户端断开后立即停止发送

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 15:16:30 +09:00
kira1928 6096171663 Merge remote-tracking branch 'origin/master' into feat/async-ffmpeg-init
# Conflicts:
#	src/servers/sse.go
#	src/webapp/src/utils/sse.ts
2026-07-08 14:01:15 +09:00
kira1928andClaude Fable 5 9811e0431b fix: 处理第二轮 code review 意见并修复 e2e 基础设施问题
后端:
- ffmpeg parser 找不到 FFmpeg 且异步初始化仍在 checking/downloading 时
  挂起等待终态(可被 ctx 取消或 Stop 中断),等待结束后立即重查并开始
  录制,不再进入"找不到 FFmpeg → 5 秒重试"失败循环(Codex P1)
- isFFmpegAvailableWithoutRemotetools 与 utils.GetFFmpegPath 语义对齐:
  配置了 ffmpeg_path 时以该路径为准不回退 PATH;补 exec.ErrDot → ./ffmpeg
  兜底(Copilot / Codex P2)
- WaitForToolsInit 在 Init() 重试进行中不再立即返回旧错误,等待本轮
  结束后读取最新结果;Init 的 defer 先发布结果再更新状态机(Gemini / Copilot)
- 新增 tools.FFmpegStatusChanged() 状态变化通知 channel

前端:
- ffmpeg-banner / update-banner 从 fixed 定位改为普通文档流,自然向下
  堆叠且把内容推开,不再互相重叠或遮挡页面顶部(Gemini high / Codex P3)
- SSEEventType 补充遗漏的 memory_warning 并注册监听

测试基础设施:
- mock server 新增 -speed 启动参数,限速在 bgo 启动前即生效(Codex P2)
- mock server 下载循环每个 chunk 前重新读取限速,运行时调速立即生效
  (Copilot / Codex P2)
- 修复 mock zip 结构:模拟真实发布包的单一顶层目录,避免 remotetools
  解压剥层后 pathToEntry 对不上导致 install 后找不到工具
- 新增 dev 专用 POST /api/debug/ffmpeg/reinit;下载失败用例先清工具缓存
  再重新触发初始化,解决用例间状态污染(Codex P2)
- e2e 等待逻辑去掉会被 SSE 长连接卡死的 networkidle(Codex P2)
- playwright.ffmpeg.config.ts 的清理副作用限定主进程执行,避免 worker
  重新加载配置时删掉下载中的工具目录
- CI 接入 ffmpeg 下载 e2e 并上传报告;package.json 加 test:e2e:ffmpeg
  (Codex P3)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 13:52:46 +09:00
kira1928 3a4cb8ab8d Merge pull request #1149 from bililive-go/copilot/080ui
暂时隐藏 0.8.0 中未开放的云盘上传与 IO 统计 UI
2026-07-08 13:16:48 +09:00
Joftal f1a0a54d13 fix:E2E TEST2 2026-06-23 11:03:13 +08:00
Joftal ab16033220 fix:E2Etest 2026-06-23 10:30:48 +08:00
Joftal 9a3a8d95f2 feat:优化批量新增直播间功能逻辑 2026-06-23 10:11:53 +08:00
kira1928andClaude Sonnet 4.6 13c32ff68d test: 添加 FFmpeg 异步初始化 e2e 测试,并修复 code review 发现的两个 Bug
## e2e 测试基础设施

### 测试辅助工具
- test/fake-ffmpeg/main.go: 极简 FFmpeg 替身程序,响应 -version 参数
- test/ffmpeg-mock-server/main.go: 模拟 FFmpeg 下载服务器
  - 启动时自动编译 fake-ffmpeg 并打包成 zip(含 bin/ffmpeg.exe 路径)
  - GET /ffmpeg.zip: 支持 ?speed=<字节/秒> 限速和 ?fail=true 失败模拟
  - POST /control: 运行时动态修改限速/失败行为
  - GET /health: 等待 zip 就绪后返回 200(供 Playwright 做启动检查)

### 测试 Fixture
- tests/e2e/fixtures/test-tools-config.json: remotetools 测试配置,将所有
  平台的 FFmpeg 下载 URL 重定向至 127.0.0.1:8890/ffmpeg.zip
- tests/e2e/fixtures/ffmpeg-test-config.template.yml: bgo 测试配置
  - 端口 8085(避免与正常测试冲突)
  - ffmpeg_path 指向不存在路径(强制走 remotetools 下载流程)
  - 独立 app_data_path(避免与正常测试的缓存互相干扰)

### 后端调试注入端点(dev 构建专有)
- src/servers/debug_routes_dev.go: POST /api/debug/ffmpeg/force-state
  供 e2e 测试注入任意 FFmpeg 状态,无需实际触发下载
- src/servers/debug_routes_stub.go: 非 dev 构建的空实现
- src/servers/server.go: 注册 registerDevDebugRoutes(apiRoute)
- src/tools/tools.go: 导出 ForceFFmpegStatus() 供调试端点调用
- src/tools/dev_config.go: 支持 REMOTETOOLS_CONFIG 环境变量覆盖
  remotetools 配置路径,使下载流程测试可指向 mock server

### E2E 测试文件
- tests/e2e/ffmpeg-status.spec.ts: 9 条状态注入测试(在正常配置下运行)
  - 验证 ready/checking/downloading/not_found/error 各状态的 Banner 显示
  - 验证状态切换后 Banner 正确消失
  - 验证 GET /api/ffmpeg/status 返回格式和 Alert 类型
- tests/e2e/ffmpeg-download.spec.ts: 3 条完整下载流程测试(需 mock server)
  - 慢速下载时出现 downloading Banner,加速后 Banner 消失
  - 下载失败时显示 error Banner
  - 页面刷新后正确恢复当前状态
- playwright.ffmpeg.config.ts: 下载流程测试专用配置
  - 运行 ffmpeg-mock-server 和使用独立 bgo 实例(端口 8085)
  - 通过 REMOTETOOLS_CONFIG 环境变量注入测试用 remotetools 配置
  - 每次运行前清空 external_tools 目录,确保测试从干净状态开始
- playwright.config.ts: 新增 testIgnore 排除 ffmpeg-download.spec.ts
  (该文件需要 mock server,仅在 playwright.ffmpeg.config.ts 下运行)

## Bug 修复(对应 PR #1150 code review)

### Fix 1: WaitForToolsInit 错误分支死代码(tools.go)
原代码将 WaitForToolsInit 返回的所有非 nil 错误都当作 ctx 取消处理,
但 WaitForToolsInit 在 Init() 失败时也返回该错误,导致:
- FFmpeg 状态永久停留在 "checking"
- not_found/error 状态永远不会被设置
修复:通过 ctx.Err() != nil 区分 ctx 取消和 Init 失败,失败时
正确调用 setFFmpegStatus({State: "not_found"})

### Fix 2: 前端竞态条件(ffmpeg-banner/index.tsx)
原代码将 handleSSEMessage 定义在 useEffect 外部(useCallback),
导致:HTTP 初始化请求如果晚于 SSE 推送到达,会用旧状态覆盖新状态,
使 Banner 重新出现并永久卡在旧状态;且组件卸载后 HTTP 回调仍会
调用 setStatus 造成内存泄漏。
修复:
- 将 handler 移入 useEffect,添加 active flag 防止卸载后更新
- 添加 sseReceived flag,HTTP 响应到达时若已收到 SSE 则忽略
- 移除不再需要的 useCallback import

### Fix 3: FFmpegAsyncInit 过早访问 remotetools(tools.go)
原注释称"先检查系统 PATH / 配置文件中的 FFmpeg,不需要 remotetools",
但实际调用 utils.IsFFmpegExist → utils.GetFFmpegPath → remotetools.Get().GetTool(),
在 Init() 完成前访问未配置好的 remotetools,可能产生误判。
修复:新增 isFFmpegAvailableWithoutRemotetools() 仅检查配置路径
(os.Stat)和系统 PATH(exec.LookPath),不触碰 remotetools。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 01:02:30 +09:00
copilot-swe-agent[bot]andkira1928 c8be6de537 test: 提升隐藏UI测试稳定性
Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>
2026-06-21 14:02:43 +00:00
copilot-swe-agent[bot]andkira1928 7d294ab879 test: 精简隐藏UI断言
Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>
2026-06-21 13:58:21 +00:00
copilot-swe-agent[bot]andkira1928 b376da35a0 fix: 暂时隐藏未完成功能UI
Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>
2026-06-21 13:57:04 +00:00
Joftal 1fd022d9e1 fix:修复E2E Tests error 2026-05-25 14:14:39 +08:00
Joftal ac6038b3dd fix:E2E Tests add danmu test 2026-04-28 13:32:07 +08:00
Joftal 033d812393 优化视频大小分割输入框智能化,支持输入Xmb、XGB格式 2026-02-25 14:20:22 +08:00
kira1928 4c0d2fa6b6 完善自动更新功能 (#1073)
* 完善自动更新功能

* 修复 CI error

* 根据review意见更新代码

* 修复e2e CI
2026-02-18 02:19:53 +09:00
kira1928 1cdf122995 完善自动更新功能 2026-02-05 00:30:13 +09:00
15b0b12777 0.8.0/dev (#1061)
* Initial plan

* Initial plan for hierarchical configuration system

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Implement hierarchical configuration system with platform and room-level overrides

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Add config validation, platform key mapping, and hierarchical config example

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Add enhanced GUI configuration interface with hierarchical config support

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Complete implementation with documentation and working web UI demo

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 根据反馈完善层级配置系统:移除二进制文件,更新中文界面,支持所有直播平台

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 改进配置界面:添加YAML解析库,输出模板预览和详细工具提示

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 完善监控列表界面:增加直播间详细信息展开功能

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 修复后端API支持和前端功能,添加日志查看功能

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 修复前端编译错误,调整优化package.json

* 实现真实的层级配置系统:添加日志存储,解析配置,更新所有组件使用解析后配置

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 实现层级配置系统:支持平台级设置、中文GUI界面、监控详情展示和真实数据后端

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 实现真实的平台访问频率限制功能

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 为所有主要直播平台添加访问频率限制支持

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 完成层级配置系统:平台访问频率限制功能全面实现

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 实现层级配置系统:支持平台级设置、中文GUI界面、监控详情展示、真实数据后端和统一访问频率限制

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 修复CI lint错误:添加webapp默认构建文件

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* feat: 新增ntfy通知功能

* feat: 添加停止录制时的ntfy推送通知

* 优化ntfy推送通知

* Update src/notify/ntfy/ntfy.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix test error

* 为每个直播间分别保留一组直播间自己的log信息,供前端取用。
前端监控列表的详细信息现在由SSE实时更新。
为详情页面的日志增加了一些便利功能。

* 升级antd v3 -> v6

* 升级 react-router-dom v5-> v6

* 优化层级设置UI,访问频率限制逻辑等

* code refine

* fix CI error

* Fix CI error

* Fix CI error

* Fix "Component state update uses potentially inconsistent value" issue

* 根据代码review修复问题:替换废弃方法,添加null检查,修复state更新和变量使用

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 修复CI编译错误:添加default构建文件并修正handler.go中的变量引用

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Initial plan

* Implement real-time countdown for next GetInfo request

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Add real-time download speed display for recording streams

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Fix setState callbacks to return prevState instead of null

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Use safe type assertion for RecorderManager to prevent panic

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Address PR review comments: add periodic SSE broadcast, fix optional chaining, cleanup memory leaks

- Add periodic (3s) broadcast of recorder status via SSE for real-time download speed updates
- Use optional chaining (?.) for safer recorder_status.speed access
- Remove redundant nil check for recorder in GetRecorder
- Clean up countdownTimers state when rows are collapsed to prevent memory leak
- Use Math.ceil() for countdown initialization to avoid premature "available" display
- Set up broadcast callback in server initialization to avoid circular dependencies

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Fix race condition and improve comments in status broadcaster

- Add sync.WaitGroup to ensure broadcaster goroutine exits cleanly
- Update comments to reflect callback-based implementation
- Ensure proper cleanup sequence in Close() method

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Improve error handling in recorder status retrieval

- Add warning log when GetStatus() fails for better observability
- Simplify logic by assigning status regardless of nil value
- Helps with debugging recorder status issues

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Improve countdown display and download speed formatting

- Add SSE list threshold config (default 50 rooms) in RPC settings
- Change download speed format from "0.562x" to "MB/s" or "KB/s" based on bitrate
- Update recorder status broadcast interval from 3s to 5s
- Fix countdown display: use "距离下次刷新" instead of "距下次GetInfo请求"
- Change "立即可用" to "正在刷新" for better UX
- Implement auto-calibrating countdown that adjusts with SSE updates
- Track last update times to maintain accurate countdown state

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* Add list-level SSE subscription with configurable threshold

- Enable SSE for live room list by default when room count < threshold
- Automatically switch to detail-only SSE when list exceeds threshold
- Update SSE subscription strategy dynamically when rooms added/removed
- Wildcard SSE subscription ('*') receives all live_update events
- List refreshes automatically when receiving SSE updates
- Clean up list-level subscription on component unmount

Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>

* 任务系统 init

* 新增任务列表,直播事件功能和对应数据库

* 修复新增功能前后端bug

* 暂时commit部分修改内容,还未充分检查

* 0.8.0/dev (#1059)

* 优化视频播放界面,新增退出视频播放按钮(支持ESC退出)

* 文件列表新增文件重命名和删除操作,支持批量操作

* 设置界面引入前端校验,确保前后端参数一致性,之前前端非法参数可以保存到后端config,如最小录制时长。本次修改在前端加入校验提示,非法参数直接拦截并提示有效值

* 哔哩哔哩cookie功能优化,新增扫码登录和验证机制

* 哔哩哔哩cookie界面优化

* fix code review

* 修复重命名、删除、批量操作的越权问题

* 表单验证间隔检测规则保持这里为0

* 完善报错

* 回滚误改的listening_count

* 修改文案

* 修复哔哩哔哩cookie界面api反复调用问题

* 补充console

* 重复的 ESC 键监听器问题修复

* 修复cookie潜在的内存问题

* cookie错误处理日志

* 错误日志改进

* 补充注释

* 调整文件编码转义,支持特殊字符,国际化,emojy等

* 修复--rsp是ReadableStream,只能读一次。如果 rsp.json() 失败后再去 rsp.text() 会失败。所以原始代码 clone 了一个 response 使用。

* 实现直播流选择,可选画质设置

* ci: 对齐版本、修复 lint 警告并添加开发工具模板

版本对齐:
- 将 CI 中的 Go 版本从 1.24 更新到 1.25 (匹配 go.mod)
- 将 Node.js 配置改为使用 .node-version 文件 (v20.10.0)
- 升级 actions/setup-go 到 v5, actions/setup-node 到 v4

Lint 修复:
- 修复 staticcheck 警告 (S1039, ST1023, S1009, QF1008)
- 删除未使用的函数:
  - recorder.go: renderUploadPath, logAvailableStreams, extractRoomID
  - store.go: getIntFromMap, getFloat64FromMap
  - runjob_windows.go: runWithKillOnClose
- 重新生成 mock 文件

开发环境:
- 添加 VS Code 调试配置模板 (.vscode/launch.example.json)
- 更新 .gitignore 支持本地 launch.json 自定义
- 更新 README 添加使用说明

* feat: 添加版本统计、更新器增强与开发环境改进

版本统计:
- 新增 telemetry 包,仅统计程序版本号
- 用于了解用户更新程序的整体趋势
- 不收集平台、架构或任何其他个人数据

更新器增强:
- 实现 SHA256 校验和验证,确保下载完整性
- 支持 tar.gz 和 zip 压缩包解压
- 优先使用 bililive-go.com 代理,回退到 GitHub 直连

开发环境:
- 升级 Go 版本到 1.25
- 新增 tools/devtools.go 管理开发工具依赖 (delve, gopls, staticcheck)
- Makefile 添加 help 命令
- 新增 test/ 目录和 launcher 测试基础设施

* fix: 修复前端 ESLint 警告并启用严格模式构建

ESLint 修复:
- config-info/index.tsx: 移除未使用的 useNavigate 和 addPlatformVisible
- history-panel/index.tsx: 移除未使用的 List、UserOutlined、HistoryResponse
- live-list/index.tsx: 移除未使用的 Modal

构建配置改进:
- 默认 build 命令使用 CI=true 模式,警告视为错误
- 添加 cross-env 依赖实现跨平台环境变量设置
- 添加 yarn lint 命令进行独立 ESLint 检查
- ESLint 配置中将 no-unused-vars 规则设为 error

这确保本地开发与 CI 行为一致,尽早发现代码问题

* 删除未使用的golang函数

* feat: 添加 Playwright E2E 测试框架

- 集成 Playwright 进行端到端测试
- 使用 osrp-stream-tester 作为测试流服务器
- 添加基础 UI 测试和直播录制测试用例
- 创建 GitHub Actions E2E 测试工作流
- 更新 Makefile 添加测试相关命令

使用方法:
- make install-e2e  # 安装测试依赖
- make test-e2e     # 运行 E2E 测试
- make test-e2e-ui  # 带 UI 运行测试

* fix: 添加 package-lock.json 以修复 CI

* feat: 添加 Playwright E2E 测试框架、相关测试用例和 GitHub Actions 工作流。

* ci: 新增 Playwright E2E 测试工作流。

* feat: 添加 Playwright E2E 测试 GitHub Actions 工作流。

* feat: 添加 E2E 测试的 GitHub Actions 工作流。

* feat: 添加端到端测试以及对应的 GitHub Actions CI 工作流

* feat: 新增录制功能的端到端测试

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kira1928 <2352900+kira1928@users.noreply.github.com>
Co-authored-by: July <31428852+onlyjuly@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Joftal <42807405+Joftal@users.noreply.github.com>
2026-01-31 03:44:14 +09:00