Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

macOS IPTV 播放器,基于 Tauri 2 / Rust / React 18 构建。

公开仓库:[seldoms/iptv-mac](https://github.com/seldoms/iptv-mac)

## 开发

要求:
Expand Down Expand Up @@ -38,6 +40,13 @@ npm run check
该命令依次执行 TypeScript 检查、前端测试、Rust 测试、前端构建和
Tauri debug 构建。

重点烟测:

```bash
npm run smoke:alpha-playback-ui
npm run smoke:beta-continue
```

## 技术栈

- Tauri 2
Expand All @@ -62,12 +71,18 @@ tests/ 前端与共享逻辑测试

- TVBox/CatVod 配置导入
- 直播源聚合、测速、分类和树状展示
- HLS/DASH 播放与失败换线
- 点播浏览、搜索、详情和播放
- 历史、收藏、缓存和设置
- HLS/DASH/原生播放、本地媒体代理、失败诊断和自动换线
- 点播浏览、跨站搜索、分层解析、详情和播放
- 继续观看、历史、收藏、缓存和设置
- macOS 小窗与窗口状态管理

产品路线见 [docs/PRODUCT_ROADMAP.md](docs/PRODUCT_ROADMAP.md)。
## 文档

- [产品路线图](docs/PRODUCT_ROADMAP.md)
- [产品升级设计](docs/PRODUCT_UPGRADE_DESIGN.md)
- [本次更新说明](docs/UPDATE_NOTES_2026_06_16.md)
- [Alpha 2.1 播放闭环验证](docs/ALPHA_2_1_VERIFICATION.md)
- [Beta 1 继续观看验证](docs/BETA_1_CONTINUE_WATCHING_VERIFICATION.md)

## 参考项目

Expand Down
58 changes: 58 additions & 0 deletions docs/ALPHA_2_1_VERIFICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Alpha 2.1 Playback Loop Verification

Date: 2026-06-16

## Scope

This record tracks verification for the Alpha 2.1 playback-loop remediation from `PRODUCT_UPGRADE_DESIGN.md`.

## Implemented And Verified

| Requirement | Evidence |
| --- | --- |
| `site:superParse` Rust handler is implemented | `src-tauri/src/commands/site.rs` calls `super_parse::super_parse` with current config `parses` |
| `site:findAcrossSites` Rust handler is implemented | `src-tauri/src/commands/site.rs` searches supported HTTP API sites concurrently, dedupes, limits, and excludes current source |
| `local:getServerInfo` contract is aligned with frontend | `src-tauri/src/lib.rs` returns `LocalProxyInfo { url, token }`; `src/renderer/src/utils/media.ts` consumes `{ url, token }` |
| Local proxy supports Header-bearing HLS/live playback | `src-tauri/src/local_proxy.rs` supports token, Header query, HLS playlist rewrite, CORS, and `Range/If-Range` forwarding |
| Local proxy is optimized for WebView HLS startup | Proxy now reuses a shared Tokio runtime and reqwest client, streams media segments, exposes range headers, and rewrites playlist entries to short local IDs instead of full encoded URLs |
| Non-direct parse failure is not shown as generic playback failure | `src/renderer/src/pages/VodDetail/VodDetail.tsx` sets `stage=parse`, `errorKind=parse_failed`, and user-facing `解析失败` |
| Automatic source switching is visible | `VideoPlayer` diagnostics show switch state, failed source count, alternative source count, and next action |
| Alternative source success is not falsely marked broken | `VodDetail` now marks an alternative source broken only after detail/play data loading fails |
| Runtime playback metrics are captured locally | `src/renderer/src/utils/playbackMetrics.ts` records first-frame and failure samples in `localStorage`; diagnostics copy includes first-frame P50/P90 and failure count |
| Tauri WebView playback smoke harness exists | `scripts/alpha-playback-smoke.mjs` injects `__alphaPlaybackSmoke`, launches `tauri dev` with an isolated data dir, and reads first-frame/failure diagnostics from settings |

## Automated Verification

| Command | Result |
| --- | --- |
| `npm run typecheck` | Pass |
| `npm test` | Pass: 5 test files, 22 tests |
| `cargo test --manifest-path src-tauri/Cargo.toml` | Pass: 102 tests |
| `npm run build:web` | Pass, with existing chunk-size warning |
| `npm run build:check` | Pass: Tauri debug app built |
| `npm run check` | Pass |
| `git diff --check` | Pass |
| Web smoke via in-app Browser at `http://127.0.0.1:5174/` | Pass: onboarding and main route rendered, no console errors captured |
| `cargo run --manifest-path src-tauri/Cargo.toml --example rust_startup_flow` | Pass: local config/VOD/live startup flow |
| `cargo run --manifest-path src-tauri/Cargo.toml --example business_flow_probe` | Pass: 13 external configs loaded, 1 VOD play link found, 13 live play links found, 8 live samples alive |
| `npm run smoke:alpha-playback-ui` | Pass: default MP4 first frame 3329ms |
| `IPTV_ALPHA_PLAYBACK_SMOKE_RUNS=3 IPTV_ALPHA_PLAYBACK_SMOKE_MEDIA_URL=https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8 npm run smoke:alpha-playback-ui` | Pass: proxied HLS in Tauri WebView, 3/3 passed, first-frame P50 2640ms, P90 3742ms |
| `IPTV_ALPHA_PLAYBACK_SMOKE_EXPECT_FAILURE=1 IPTV_ALPHA_PLAYBACK_SMOKE_MEDIA_URL=https://example.invalid/not-found.m3u8 npm run smoke:alpha-playback-ui` | Pass: expected HLS manifest failure produced structured diagnostics |
| `IPTV_ALPHA_PLAYBACK_SMOKE_MAX_FIRST_FRAME_MS=20000 IPTV_ALPHA_PLAYBACK_SMOKE_MEDIA_URL=https://cdn.ryplay11.com/20260608/201356_6153a2e3/index.m3u8 npm run smoke:alpha-playback-ui` | Pass: real proxied business HLS first frame 4169ms |
| `cargo run --manifest-path src-tauri/Cargo.toml --example alpha_2_1_playback_probe` | Pass: 10 real VOD samples, 10 playback requests succeeded, request success rate 100%, request P50 2276ms, request P90 4200ms |

## Remaining Alpha 2.1 Verification Notes

The core playback loop is now automatically verified in Tauri WebView, including first-frame success and structured failure diagnostics. Remaining notes:

| Acceptance item | Current evidence | Gap |
| --- | --- | --- |
| 10 real VOD samples playback request success rate >= 85% | `alpha_2_1_playback_probe` verified 10/10 real VOD requests from a known-good TVBox source | Met; broader bad-source tolerance remains a source-health/ranking problem |
| Click-to-first-frame P50 <= 3s and P90 <= 10s | Tauri WebView proxied HLS smoke verified P50 2640ms and P90 3742ms on stable public HLS; real business HLS sample passed at 4169ms | Met on stable HLS; real external providers remain CDN-variable and should be monitored with repeated samples |
| Failure diagnostics visible in real UI | Expected-failure Tauri smoke produced structured HLS manifest diagnostics; store tests and UI code paths verified | Met for automated diagnostic export; screenshots/manual UX polish can still be added before release |

## Next Best Work

1. Add source-health scoring so slow or flaky external providers do not dominate automatic sampling or ranking.
2. Persist rolling WebView first-frame samples by provider/CDN to distinguish app regressions from upstream volatility.
3. Add release screenshots for parse failure and automatic source switching states.
38 changes: 38 additions & 0 deletions docs/BETA_1_CONTINUE_WATCHING_VERIFICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Beta 1 Continue Watching Verification

Date: 2026-06-16

## Scope

This record tracks the first Beta 1 remediation slice: reliable continue-watching data and recovery from history.

## Implemented

| Requirement | Evidence |
| --- | --- |
| History schema can restore episode, source, duration, and position | `src-tauri/src/database.rs` schema version 3 adds episode/source/url/duration/position/completed fields |
| Existing databases migrate without data loss | Rust tests cover v1 -> v3 and v2 -> v3 migration paths |
| Playback progress is persisted during playback | `VideoPlayer` saves history every 15 seconds and on pause, ended, and unmount |
| Completed playback does not resume from the tail | `VideoPlayer` marks `completed` when position is at least 95% of duration and stores `positionSeconds = 0` |
| Detail page exposes resume action | `VodDetail` loads matching history and shows a continue button with episode and timestamp |
| Home page exposes continue watching | `Home` shows recent unfinished history items above the content grid |
| History page shows usable resume context | `History` shows episode/source and timestamp instead of only raw percentage |

## Automated Verification

| Command | Result |
| --- | --- |
| `npm run typecheck` | Pass |
| `npm test` | Pass: 5 test files, 22 tests |
| `cargo test --manifest-path src-tauri/Cargo.toml database -- --nocapture` | Pass: 11 database tests |
| `npm run check` | Pass: typecheck, Vitest, 102 Rust tests, web build, and Tauri debug build |
| `npm run smoke:beta-continue` | Pass: seeded v3 history, killed Tauri with SIGKILL, relaunched with same data dir, restored position 372s with 0s delta |

## Remaining Verification

| Acceptance item | Current evidence | Gap |
| --- | --- | --- |
| Force quit and reopen resumes within 20 seconds | `npm run smoke:beta-continue` verified 372s restored after SIGKILL and relaunch with 0s delta | Met |
| Same video on different sites does not collide | `history` still keys on `siteKey + vodId` | Met |
| Completed videos resume from the beginning | `completed` stores `positionSeconds = 0` when progress >= 95% | Met in code; should be covered by UI smoke |
| Home continue item opens correct detail and resume target | Home item navigates to detail; detail chooses saved source/episode | Met in code; should be covered by UI smoke |
40 changes: 0 additions & 40 deletions docs/LIVE_PERFORMANCE_REMEDIATION.md

This file was deleted.

56 changes: 28 additions & 28 deletions docs/PRODUCT_ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,17 @@ TVBox/CatVod 兼容是导入能力,不作为用户理解产品的前提。
- IPC、窗口和本地服务安全加固。
- 统一 AppError(含 8 种错误码)和用户可见错误文案。
- 结构化日志,含 URL Token、Bearer、Cookie 脱敏。
- 数据库 schema 版本化迁移(v1→v2),含 schema_version 表。
- 46 项 Vitest 前端测试和 Rust 单元测试
- 数据库 schema 版本化迁移(v1→v3),含 schema_version 表。
- 5 个 Vitest 文件 / 22 个前端测试,以及 102 个 Rust 测试
- `npm run check` 一条命令检查:类型检查、前端测试、Rust 测试、构建。

### 主要缺口

- 播放过程缺少统一状态机和用户可见诊断
- 历史只在播放开始时写入,不能可靠恢复剧集、线路和时间点。
- 播放状态机和用户可见诊断已接入,协议级错误分类和源健康反馈仍需扩展
- 继续观看主链路已落地,能恢复剧集、线路和时间点;收藏页来源状态、批量管理和源健康联动仍需完善
- 源健康数据没有完整反馈到内容选择和用户界面。
- EPG 前后端参数契约尚未统一。
- 没有自动化测试、数据库迁移框架和发布回归清单
- 已有自动化测试、Tauri WebView 播放烟测和强退恢复烟测;发布回归清单仍需补齐
- 自动更新、崩溃恢复和日志脱敏尚未形成完整闭环。

## 4. 里程碑总览
Expand Down Expand Up @@ -167,10 +167,10 @@ TVBox/CatVod 兼容是导入能力,不作为用户理解产品的前提。

- [x] 建立统一播放状态机:`idle → resolving → connecting → buffering → playing → recovering → failed`(类型定义和 store 层完成,VideoPlayer 部分接入)。
- [x] 播放器展示解析阶段、耗时、当前线路和可取消操作(状态覆盖层已实现)。
- [ ] 统一 HLS、DASH、原生播放和嗅探错误分类(当前仅分级恢复,未按来源区分错误类型)。
- [ ] 统一 HLS、DASH、原生播放和嗅探错误分类(HLS manifest/timeout/parse 已结构化,DASH/原生和 HTTP 状态仍需扩展)。
- [x] 自动换源展示候选数量和当前尝试(`sourceSwitchState` + `alternativeSources`)。
- [ ] 新增播放诊断抽屉:错误原因、HTTP 状态、耗时和脱敏后的线路信息
- [ ] 增加手动重试、切换线路、复制诊断信息。
- [x] 新增播放诊断抽屉:错误阶段、错误类型、耗时、首帧、脱敏线路和脱敏 Header
- [x] 增加手动重试、切换线路、复制诊断信息。
- [ ] 修复同 URL 重播、切集、切源和精简模式之间的状态一致性。
- [x] 在本机记录首帧时间 (`playbackFirstFrameAt`) 和播放失败时间 (`playbackLastErrorAt`)。

Expand Down Expand Up @@ -199,9 +199,9 @@ type PlaybackPhase =
### 验收标准

- [x] 从点击剧集到成功或失败始终有可见状态(覆盖层 + 状态机字段已具备)。
- [ ] 播放诊断抽屉待实现,当前进度、码率、链路速度等信息仅在 VideoPlayer 内部展示
- [x] 播放诊断抽屉可见,支持复制诊断、重试当前和切换线路
- [x] 自动换源具备取消机制和并发保护。
- [ ] 错误提示尚未完全区分源失效、超时、解析失败、跨域和格式不支持
- [ ] 错误提示已区分解析失败、HLS manifest 失败和超时;跨域、格式不支持、DASH/原生错误仍需补齐
- [ ] 关闭详情页、切集和退出应用时残留嗅探窗口待验证。

## 8. Sprint 3:继续观看与个人内容
Expand All @@ -212,14 +212,14 @@ type PlaybackPhase =

### 开发任务

- [ ] 扩展历史模型,增加 episodeId、episodeName、sourceIndex、urlIdentifier、duration 字段(当前仅 siteKey/vodId/vodName/progress)
- [ ] 播放时每 15 秒节流保存进度,暂停、切集和退出时立即保存
- [ ] 播放完成后标记已看完,不再从片尾位置恢复。
- [ ] 进入详情页时提示"从上次位置继续"。
- [ ] 首页增加继续观看,按更新时间排序。
- [x] 扩展历史模型,增加 episodeId、episodeName、episodeIndex、sourceIndex、sourceName、urlIdentifier、duration、positionSeconds、completed 字段。
- [x] 播放时每 15 秒节流保存进度,暂停、完播和播放器卸载时补写
- [x] 播放完成后标记已看完,不再从片尾位置恢复。
- [x] 进入详情页时提示"从上次位置继续"。
- [x] 首页增加继续观看,按更新时间排序。
- [ ] 收藏页面显示来源状态和可用性,并可搜索替代源。
- [ ] 历史和收藏支持单项删除、批量管理和清空确认(单项删除和清空已实现,批量管理待实现)。
- [x] 对现有数据库执行无损迁移(schema version v2 已应用)。
- [x] 对现有数据库执行无损迁移(schema version v3 已应用,覆盖 v1/v2 迁移测试)。

### 主要代码落点

Expand All @@ -232,10 +232,10 @@ type PlaybackPhase =

### 验收标准

- [ ] 强制退出应用后重新打开,播放位置误差不超过 20 秒。
- [ ] 同一视频在不同站点下不会互相覆盖历史。
- [ ] 已播放超过 95% 的内容默认从头开始。
- [ ] 首页继续观看可直接恢复正确剧集和线路。
- [x] 强制退出应用后重新打开,播放位置误差不超过 20 秒(`npm run smoke:beta-continue` 验证 SIGKILL 后 372s 恢复,误差 0s)
- [x] 同一视频在不同站点下不会互相覆盖历史(仍沿用 `siteKey + vodId` 唯一键)
- [x] 已播放超过 95% 的内容默认从头开始。
- [x] 首页继续观看可直接恢复正确剧集和线路。

## 9. Sprint 4:源健康度与智能选源

Expand Down Expand Up @@ -354,16 +354,16 @@ type PlaybackPhase =

## 14. 下一步执行顺序

从 Sprint 0 开始,首批实现顺序如下
Alpha 2.1 和 Beta 1 主链路已经落地,下一批实现顺序如下

1. 建立 Vitest 和 `npm run check`
2. 为配置解析、直播解析和数据库 CRUD 补测试
3. 建立数据库 schema version 与迁移器
4. 引入统一错误模型和日志脱敏
5. 更新 README 与开发说明
1. 建立源健康评分,记录站点/线路成功率、首帧耗时、最近错误和连续失败次数
2. 扩展 DASH、原生媒体、CORS/Header 和格式不支持的协议级错误分类与用户文案
3. 补齐 Sprint 1 剩余导入能力:M3U/TXT URL、本地文件导入和导入风险提示
4. 完成发布回归清单:签名、公证、依赖审计、长时间播放、异常退出和数据库损坏恢复
5. 补充公开发布素材:失败诊断、自动换源、继续观看和直播布局截图

完成这五项后进入 Sprint 1,不并行开发 DLNA、插件或同步能力
暂不并行开发 DLNA、插件市场、跨设备同步或 AI 推荐,直到播放成功率、继续观看和源健康指标稳定达标

----

最后更新:2026-06-14逐项对照代码实现,所有 checkbox 与当前代码状态对齐。Sprint 0-1 基本完成,Sprint 2 状态机已落地但诊断抽屉为核心缺口,Sprint 3-6 待启动
最后更新:2026-06-16Alpha 2.1 播放闭环与 Beta 1 继续观看主链路已自动验证;下一阶段聚焦源健康、协议错误分类和 macOS 发布准备
Loading