Skip to content

feat(player): HLS session progress polling with media server integration#209

Merged
mkdir700 merged 2 commits intodevfrom
mkdir700/hls-progress-integration
Oct 13, 2025
Merged

feat(player): HLS session progress polling with media server integration#209
mkdir700 merged 2 commits intodevfrom
mkdir700/hls-progress-integration

Conversation

@mkdir700
Copy link
Owner

@mkdir700 mkdir700 commented Oct 12, 2025

Summary by CodeRabbit

  • 新功能
    • 播放页新增转码会话就绪轮询与可视化进度(阶段文本与百分比),就绪后自动切换至 HLS 源。
  • 错误修复
    • 转码就绪失败时提供更清晰的错误提示,并在必要时回退到原始来源,提升播放稳定性。
  • 杂务
    • 后端组件指针更新,不影响现有功能。

Summary by CodeRabbit

  • 新功能

    • 播放页新增“转码准备”可视进度:分阶段文字与百分比进度条,加载时自动轮询直至就绪并切换到 HLS 播放源。
  • 性能与稳定性

    • 强化转码轮询与错误处理:超时/失败更明确回退到原始文件并记录日志,加载反馈更可靠。
  • 杂项

    • 移除字幕覆盖层的调试日志,减少噪音。
    • 同步子模块引用,无用户可见功能变更。

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 12, 2025

Walkthrough

该变更引入转码会话就绪轮询:新增 SessionService.getSessionProgress 与相关类型;在 PlayerPage 中轮询会话进度并在就绪后切换至 HLS 播放源,展示确定性进度条;移除 SubtitleOverlay 的调试日志;更新 backend 子模块引用。

Changes

Cohort / File(s) Summary
Backend 子模块
backend@submodule
子模块引用从 176ca823... 更新至 64aaf0bd...,无代码或行为变更。
Player 页面:会话轮询与进度 UI
src/renderer/src/pages/player/PlayerPage.tsx
新增会话就绪轮询逻辑(waitForSessionReady)、状态 waitingForSessionReadysessionProgress;创建会话后轮询 SessionService.getSessionProgress,就绪后获取/拼接 HLS 播放列表并切换播放器源;增加确定性进度条与阶段文本显示;增强错误处理与日志。
字幕覆盖:清理日志
src/renderer/src/pages/player/components/SubtitleOverlay.tsx
移除渲染路径中的调试日志行,渲染/交互行为不变。
SessionService:进度 API
src/renderer/src/services/SessionService.ts
新增导出接口 AudioProgressInfoSessionProgressResponse;新增 SessionService.getSessionProgress(sessionId),请求 /{sessionId}/progress,对 HTTP 425(Too Early)做特殊处理并记录日志,返回是否就绪与可选 playlist_url

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as 用户
  participant Player as PlayerPage
  participant Sess as SessionService
  participant Media as 媒体服务
  participant HLS as HLS 播放器

  User->>Player: 打开视频 / 请求播放
  Player->>Sess: 创建/使用会话(现有流程)
  note right of Player: 设置 waitingForSessionReady=true\n初始化 sessionProgress

  loop 轮询直到就绪或失败
    Player->>Sess: getSessionProgress(sessionId)
    Sess->>Media: GET /{sessionId}/progress
    Media-->>Sess: 200 {progress, is_ready, playlist_url} 或 425 Too Early
    alt 425 Too Early
      Sess-->>Player: 返回可重试(非就绪)
      note over Player: 等待后继续轮询
    else 返回进度
      Sess-->>Player: {progress_percent, progress_stage, is_ready, playlist_url}
      Player->>Player: 更新确定性进度条与阶段文本
    end
  end

  alt is_ready = true
    Player->>Player: 选择最终 HLS 播放列表 URL
    Player->>HLS: 切换至 HLS 源并开始播放
  else 错误或超时
    Player->>Player: 记录错误,回退到原始文件 URL(若适用)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

我是码兔守仓房,
轮询进度数时光,⏳
条条进度向前忙,▶️
字幕静默去调试,
HLS 一启歌声响。 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title Check ⚠️ Warning 当前标题“feat(player): HLS session progress polling with media server integration”准确反映了 HLS 会话进度轮询这一主要改动,但包含的“媒体服务器集成”部分并未在新增的客户端和服务端接口中体现,因此信息不符且可能误导审阅者。 请移除或修改标题中与实际变更无关的“媒体服务器集成”描述,使标题仅聚焦于 HLS 会话进度轮询功能,例如调整为“feat(player): 添加 HLS 会话进度轮询”。
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mkdir700/hls-progress-integration

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87d67f6 and bd5c9b6.

📒 Files selected for processing (1)
  • src/renderer/src/pages/player/PlayerPage.tsx (8 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
src/renderer/src/**/*.{ts,tsx,scss,css}

📄 CodeRabbit inference engine (CLAUDE.md)

优先使用 CSS 变量,避免硬编码样式值(颜色等)

Files:

  • src/renderer/src/pages/player/PlayerPage.tsx
src/renderer/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

尺寸与时长等不要硬编码,优先使用 useTheme() 的 token 或集中样式变量(如 motionDurationMid、borderRadiusSM/MD)

Files:

  • src/renderer/src/pages/player/PlayerPage.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: 定制 antd 组件样式优先使用 styled-components 包装 styled(Component),避免全局 classNames
项目的图标统一使用 lucide-react,不使用 emoji 作为图标
组件/Hook 顶层必须通过 useStore(selector) 使用 Zustand,禁止在 useMemo/useEffect 内部调用 store Hook
避免使用返回对象的 Zustand 选择器(如 useStore(s => ({ a: s.a, b: s.b })));应使用单字段选择器或配合 shallow 比较器
遵循 React「副作用与状态更新」规范:渲染纯函数、Effect 三分法、幂等更新、稳定引用、严格清理、禁止写回自身依赖、Provider 值 memo、外部状态 selector 稳定等
统一使用 loggerService 记录日志而不是 console
logger 使用示例中第二个参数必须为对象字面量(如 logger.error('msg', { error }))
任何组件或页面都不要写入 media 元素的 currentTime,播放器控制由编排器统一负责
在 styled-components 中:主题相关属性使用 AntD CSS 变量(如 var(--ant-color-bg-elevated));
在 styled-components 中:设计系统常量(尺寸、动画、层级、字体、毛玻璃等)使用 JS 常量(如 SPACING、BORDER_RADIUS、Z_INDEX、FONT_SIZES 等)

Files:

  • src/renderer/src/pages/player/PlayerPage.tsx
**/player/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Player 页面:统一在组件顶层使用 Zustand selector,禁止在 useMemo/useEffect 内调用 store Hook;useSubtitleEngine 通过参数传入 subtitles 等防御处理

Files:

  • src/renderer/src/pages/player/PlayerPage.tsx
🧠 Learnings (3)
📚 Learning: 2025-09-17T14:59:36.985Z
Learnt from: CR
PR: mkdir700/EchoPlayer#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T14:59:36.985Z
Learning: Applies to src/renderer/src/**/*.{ts,tsx} : 尺寸与时长等不要硬编码,优先使用 useTheme() 的 token 或集中样式变量(如 motionDurationMid、borderRadiusSM/MD)

Applied to files:

  • src/renderer/src/pages/player/PlayerPage.tsx
📚 Learning: 2025-09-17T14:59:36.985Z
Learnt from: CR
PR: mkdir700/EchoPlayer#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T14:59:36.985Z
Learning: Applies to **/*.{ts,tsx} : 在 styled-components 中:设计系统常量(尺寸、动画、层级、字体、毛玻璃等)使用 JS 常量(如 SPACING、BORDER_RADIUS、Z_INDEX、FONT_SIZES 等)

Applied to files:

  • src/renderer/src/pages/player/PlayerPage.tsx
📚 Learning: 2025-09-17T14:59:36.985Z
Learnt from: CR
PR: mkdir700/EchoPlayer#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-17T14:59:36.985Z
Learning: Applies to src/renderer/src/**/*.{ts,tsx,scss,css} : 优先使用 CSS 变量,避免硬编码样式值(颜色等)

Applied to files:

  • src/renderer/src/pages/player/PlayerPage.tsx
🧬 Code graph analysis (1)
src/renderer/src/pages/player/PlayerPage.tsx (2)
src/renderer/src/services/SessionService.ts (2)
  • SessionService (154-600)
  • SessionError (138-147)
src/renderer/src/infrastructure/styles/theme.ts (5)
  • SPACING (43-58)
  • COMPONENT_TOKENS (164-334)
  • ANIMATION_DURATION (91-100)
  • EASING (103-114)
  • FONT_SIZES (25-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (ubuntu-latest, 20)
  • GitHub Check: test (macos-latest, 20)
  • GitHub Check: test (windows-latest, 20)
🔇 Additional comments (3)
src/renderer/src/pages/player/PlayerPage.tsx (3)

20-26: 主题常量导入符合规范

正确导入设计系统常量以替代硬编码值,符合项目编码规范。


262-338: 就绪轮询集成与状态管理良好

正确设置初始进度状态、调用轮询逻辑,并在成功后标记转码状态为 completed(Line 317),失败时标记为 failed(Line 335)。播放列表 URL 解析具有稳健的回退处理(Lines 282-294)。


748-776: 样式组件正确使用设计系统常量,符合编码规范

确定性进度条样式已完全遵循项目规范:

  • 尺寸使用 SPACINGCOMPONENT_TOKENSFONT_SIZES 常量
  • 动画时长使用 ANIMATION_DURATION.SLOW
  • 缓动函数使用 EASING.STANDARD
  • 颜色使用 CSS 变量

完美解决了之前审查中关于硬编码值的问题。

Based on coding guidelines


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…back

- Add waitForSessionReady to poll session creation progress before playback
- Integrate useSessionProgress hook for reusable progress tracking logic
- Display deterministic progress bar with percentage and stage information during session initialization
- Add SessionService.getSessionProgress API with HTTP 425 handling for in-progress state
- Update backend submodule to v64aaf0b with HLS session progress support
- Remove excessive debug logging in SubtitleOverlay to reduce console noise

Changes:

PlayerPage:
- Add waitForSessionReady state and sessionProgress state for UI rendering
- Implement polling loop with 2s interval to fetch session progress until ready
- Display progress bar with stage text and percentage during session creation
- Handle HTTP 425 (session not ready) gracefully in progress polling
- Fallback to default playlist URL if progress response URL parsing fails

useSessionProgress Hook:
- Provide reusable session progress polling with configurable interval (default 2s)
- Auto-stop polling when session is ready or error occurs
- Expose startPolling, stopPolling, reset methods for lifecycle control
- Implement progress threshold (5%) to reduce log noise

SessionService:
- Add getSessionProgress(sessionId) API to fetch session creation progress
- Define SessionProgressResponse and AudioProgressInfo interfaces
- Treat HTTP 425 as normal in-progress state (not error)

This enhancement provides real-time visual feedback during HLS session
initialization, improving user experience by showing progress instead of
generic "loading..." spinner. The polling mechanism ensures playback starts
only after the session is fully ready, preventing premature playlist access.
@mkdir700 mkdir700 force-pushed the mkdir700/hls-progress-integration branch from b167306 to 87d67f6 Compare October 12, 2025 14:52
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35cf4ce and 87d67f6.

📒 Files selected for processing (4)
  • backend (1 hunks)
  • src/renderer/src/pages/player/PlayerPage.tsx (7 hunks)
  • src/renderer/src/pages/player/components/SubtitleOverlay.tsx (0 hunks)
  • src/renderer/src/services/SessionService.ts (2 hunks)
💤 Files with no reviewable changes (1)
  • src/renderer/src/pages/player/components/SubtitleOverlay.tsx
🧰 Additional context used
📓 Path-based instructions (4)
src/renderer/src/**/*.{ts,tsx,scss,css}

📄 CodeRabbit inference engine (CLAUDE.md)

优先使用 CSS 变量,避免硬编码样式值(颜色等)

Files:

  • src/renderer/src/services/SessionService.ts
  • src/renderer/src/pages/player/PlayerPage.tsx
src/renderer/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

尺寸与时长等不要硬编码,优先使用 useTheme() 的 token 或集中样式变量(如 motionDurationMid、borderRadiusSM/MD)

Files:

  • src/renderer/src/services/SessionService.ts
  • src/renderer/src/pages/player/PlayerPage.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: 定制 antd 组件样式优先使用 styled-components 包装 styled(Component),避免全局 classNames
项目的图标统一使用 lucide-react,不使用 emoji 作为图标
组件/Hook 顶层必须通过 useStore(selector) 使用 Zustand,禁止在 useMemo/useEffect 内部调用 store Hook
避免使用返回对象的 Zustand 选择器(如 useStore(s => ({ a: s.a, b: s.b })));应使用单字段选择器或配合 shallow 比较器
遵循 React「副作用与状态更新」规范:渲染纯函数、Effect 三分法、幂等更新、稳定引用、严格清理、禁止写回自身依赖、Provider 值 memo、外部状态 selector 稳定等
统一使用 loggerService 记录日志而不是 console
logger 使用示例中第二个参数必须为对象字面量(如 logger.error('msg', { error }))
任何组件或页面都不要写入 media 元素的 currentTime,播放器控制由编排器统一负责
在 styled-components 中:主题相关属性使用 AntD CSS 变量(如 var(--ant-color-bg-elevated));
在 styled-components 中:设计系统常量(尺寸、动画、层级、字体、毛玻璃等)使用 JS 常量(如 SPACING、BORDER_RADIUS、Z_INDEX、FONT_SIZES 等)

Files:

  • src/renderer/src/services/SessionService.ts
  • src/renderer/src/pages/player/PlayerPage.tsx
**/player/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Player 页面:统一在组件顶层使用 Zustand selector,禁止在 useMemo/useEffect 内调用 store Hook;useSubtitleEngine 通过参数传入 subtitles 等防御处理

Files:

  • src/renderer/src/pages/player/PlayerPage.tsx
🧬 Code graph analysis (2)
src/renderer/src/services/SessionService.ts (1)
src/renderer/src/services/Logger.ts (1)
  • error (422-424)
src/renderer/src/pages/player/PlayerPage.tsx (1)
src/renderer/src/services/SessionService.ts (2)
  • SessionService (154-600)
  • SessionError (138-147)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (macos-latest, 20)
  • GitHub Check: test (windows-latest, 20)
  • GitHub Check: test (ubuntu-latest, 20)
🔇 Additional comments (3)
src/renderer/src/pages/player/PlayerPage.tsx (3)

7-7: 引入 SessionError 以识别 425 语义 — LGTM

用于区分“未就绪”与真实错误,符合预期。


169-171: 初始化等待/进度状态 — LGTM

开始前清空状态,避免脏数据。


380-383: 在 finally 中复位等待与加载状态 — LGTM

确保非取消场景下正确收尾。

Comment on lines +99 to 105
const [waitingForSessionReady, setWaitingForSessionReady] = useState(false)
const [sessionProgress, setSessionProgress] = useState<{
percent: number
stage: string
status: string
} | null>(null)
// const { pokeInteraction } = usePlayerUI()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

进度本地状态定义 OK;可提取为类型别名以增强可读性

将 { percent, stage, status } 提为 SessionProgressViewState,便于复用。

🤖 Prompt for AI Agents
In src/renderer/src/pages/player/PlayerPage.tsx around lines 99 to 105, extract
the anonymous object type used for sessionProgress into a named type alias (e.g.
SessionProgressViewState) and replace the inline generic with that alias; add
the type alias near the top of the file (or next to related types), update the
useState declaration to use useState<SessionProgressViewState | null>(null), and
export the alias if it will be reused elsewhere.

// 加载视频数据
useEffect(() => {
let cancelled = false
const pollIntervalMs = 2000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

避免硬编码轮询间隔,提取为常量/配置

将 2000ms 提取到常量(或主题 token/配置),便于统一调整与测试。

-    const pollIntervalMs = 2000
+    const pollIntervalMs = POLL_INTERVAL_MS // 顶部或模块常量,例如 2000

可在文件顶部新增:

const POLL_INTERVAL_MS = 2000

As per coding guidelines

🤖 Prompt for AI Agents
In src/renderer/src/pages/player/PlayerPage.tsx around line 113, the poll
interval is hardcoded as 2000ms; extract this magic number into a named constant
(e.g., POLL_INTERVAL_MS) declared at the top of the file or moved to a shared
config/constants file, then replace the inline 2000 value with that constant so
the interval is configurable and easier to test.

Comment on lines +115 to +165
const waitForSessionReady = async (sessionId: string) => {
while (!cancelled) {
try {
const progress = await SessionService.getSessionProgress(sessionId)
if (cancelled) {
break
}

setSessionProgress((prev) => {
const stage = progress.progress_stage?.trim() || prev?.stage || '处理中...'
const rawPercent =
typeof progress.progress_percent === 'number'
? progress.progress_percent
: Number(progress.progress_percent)
const percent = Number.isFinite(rawPercent) ? rawPercent : (prev?.percent ?? 0)
return {
percent,
stage,
status: progress.status
}
})

if (progress.is_ready) {
setSessionProgress((prev) => ({
percent: 100,
stage: progress.progress_stage?.trim() || prev?.stage || '就绪',
status: progress.status
}))
return progress
}
} catch (progressError) {
if (
progressError instanceof SessionError &&
progressError.statusCode &&
progressError.statusCode === 425
) {
// 会话尚未返回进度,等待下一轮
} else {
throw progressError
}
}

if (cancelled) {
break
}

await new Promise((resolve) => setTimeout(resolve, pollIntervalMs))
}

throw new Error('会话进度轮询已取消')
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

轮询缺少失败/超时退出条件,存在无限等待风险

  • 未处理 progress.error_message 或 status=error/failed 等错误态,可能无限等待。
  • 无总超时上限,后端异常时用户会一直卡在“处理中”。

建议:

  • 检测错误态并立即中止。
  • 增加总超时(如 120s,可配置)。
  • 保持已有的 425 继续轮询语义。

示例修改(核心片段):

-    const waitForSessionReady = async (sessionId: string) => {
+    const waitForSessionReady = async (sessionId: string) => {
+      const MAX_WAIT_MS = 120_000 // 可提取到常量
+      const startTs = Date.now()
       while (!cancelled) {
         try {
           const progress = await SessionService.getSessionProgress(sessionId)
           if (cancelled) {
             break
           }
+          // 错误态快速失败
+          if (
+            progress.error_message ||
+            progress.status === 'error' ||
+            progress.status === 'failed'
+          ) {
+            throw new Error(progress.error_message || '会话进度报告错误状态')
+          }
           setSessionProgress((prev) => {
             const stage = progress.progress_stage?.trim() || prev?.stage || '处理中...'
             const rawPercent =
               typeof progress.progress_percent === 'number'
                 ? progress.progress_percent
                 : Number(progress.progress_percent)
             const percent = Number.isFinite(rawPercent) ? rawPercent : (prev?.percent ?? 0)
             return {
               percent,
               stage,
               status: progress.status
             }
           })
           if (progress.is_ready) {
             setSessionProgress((prev) => ({
               percent: 100,
               stage: progress.progress_stage?.trim() || prev?.stage || '就绪',
               status: progress.status
             }))
             return progress
           }
         } catch (progressError) {
           if (
             progressError instanceof SessionError &&
             progressError.statusCode &&
             progressError.statusCode === 425
           ) {
             // 会话尚未返回进度,等待下一轮
           } else {
             throw progressError
           }
         }
+        // 超时保护
+        if (Date.now() - startTs > MAX_WAIT_MS) {
+          throw new Error('会话准备超时')
+        }
         if (cancelled) {
           break
         }
         await new Promise((resolve) => setTimeout(resolve, pollIntervalMs))
       }
       throw new Error('会话进度轮询已取消')
     }

As per coding guidelines

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const waitForSessionReady = async (sessionId: string) => {
while (!cancelled) {
try {
const progress = await SessionService.getSessionProgress(sessionId)
if (cancelled) {
break
}
setSessionProgress((prev) => {
const stage = progress.progress_stage?.trim() || prev?.stage || '处理中...'
const rawPercent =
typeof progress.progress_percent === 'number'
? progress.progress_percent
: Number(progress.progress_percent)
const percent = Number.isFinite(rawPercent) ? rawPercent : (prev?.percent ?? 0)
return {
percent,
stage,
status: progress.status
}
})
if (progress.is_ready) {
setSessionProgress((prev) => ({
percent: 100,
stage: progress.progress_stage?.trim() || prev?.stage || '就绪',
status: progress.status
}))
return progress
}
} catch (progressError) {
if (
progressError instanceof SessionError &&
progressError.statusCode &&
progressError.statusCode === 425
) {
// 会话尚未返回进度,等待下一轮
} else {
throw progressError
}
}
if (cancelled) {
break
}
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs))
}
throw new Error('会话进度轮询已取消')
}
const waitForSessionReady = async (sessionId: string) => {
const MAX_WAIT_MS = 120_000 // 可提取到常量
const startTs = Date.now()
while (!cancelled) {
try {
const progress = await SessionService.getSessionProgress(sessionId)
if (cancelled) {
break
}
// 错误态快速失败
if (
progress.error_message ||
progress.status === 'error' ||
progress.status === 'failed'
) {
throw new Error(progress.error_message || '会话进度报告错误状态')
}
setSessionProgress((prev) => {
const stage = progress.progress_stage?.trim() || prev?.stage || '处理中...'
const rawPercent =
typeof progress.progress_percent === 'number'
? progress.progress_percent
: Number(progress.progress_percent)
const percent = Number.isFinite(rawPercent) ? rawPercent : (prev?.percent ?? 0)
return {
percent,
stage,
status: progress.status
}
})
if (progress.is_ready) {
setSessionProgress((prev) => ({
percent: 100,
stage: progress.progress_stage?.trim() || prev?.stage || '就绪',
status: progress.status
}))
return progress
}
} catch (progressError) {
if (
progressError instanceof SessionError &&
progressError.statusCode === 425
) {
// 会话尚未返回进度,等待下一轮
} else {
throw progressError
}
}
// 超时保护
if (Date.now() - startTs > MAX_WAIT_MS) {
throw new Error('会话准备超时')
}
if (cancelled) {
break
}
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs))
}
throw new Error('会话进度轮询已取消')
}
🤖 Prompt for AI Agents
In src/renderer/src/pages/player/PlayerPage.tsx around lines 115-165, the
session polling loop lacks failure/status and total-timeout handling which can
cause infinite waits; modify waitForSessionReady to (1) accept/configure a total
timeout (e.g. default 120000 ms) and record a startTime, (2) on each loop check
elapsed time and immediately throw a timeout Error when exceeded, (3) inspect
the returned progress for explicit error conditions (e.g. progress.status ===
'error' || progress.status === 'failed' || progress.error_message) and throw a
descriptive Error to abort polling (but preserve the existing special-case
handling for SessionError with statusCode === 425 so it continues polling), and
(4) ensure any thrown errors clear/stop the loop and propagate to caller so the
UI can show failure instead of hanging.

Comment on lines +528 to +550
const progressPercent = Math.max(0, Math.min(100, Math.round(sessionProgress?.percent ?? 0)))

return (
<Container>
<LoadingContainer>
<LoadingText>加载中...</LoadingText>
<LoadingBarContainer>
<LoadingBarProgress />
</LoadingBarContainer>
{waitingForSessionReady ? (
<>
<ProgressStageText>
{sessionProgress?.stage || '正在创建转码会话...'}
</ProgressStageText>
<DeterminateBarTrack>
<DeterminateBarFill $percent={progressPercent} />
</DeterminateBarTrack>
<ProgressPercentText>{progressPercent}%</ProgressPercentText>
</>
) : (
<>
<LoadingText>加载中...</LoadingText>
<LoadingBarContainer>
<LoadingBarProgress />
</LoadingBarContainer>
</>
)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

新文案需接入 i18n;无障碍可读性可加 aria 标签

  • '正在创建转码会话...'、'处理中...'、'就绪' 均为新文案,建议使用 t()。
  • 进度条可添加 aria-valuenow/aria-valuemin/aria-valuemax 增强可访问性。

示例:

-  {sessionProgress?.stage || '正在创建转码会话...'}
+  {sessionProgress?.stage || t('player.transcode.creatingSession')}

Determinate 容器:

- <DeterminateBarFill $percent={progressPercent} />
+ <DeterminateBarFill
+   $percent={progressPercent}
+   role="progressbar"
+   aria-valuemin={0}
+   aria-valuemax={100}
+   aria-valuenow={progressPercent}
/>

As per coding guidelines

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const progressPercent = Math.max(0, Math.min(100, Math.round(sessionProgress?.percent ?? 0)))
return (
<Container>
<LoadingContainer>
<LoadingText>加载中...</LoadingText>
<LoadingBarContainer>
<LoadingBarProgress />
</LoadingBarContainer>
{waitingForSessionReady ? (
<>
<ProgressStageText>
{sessionProgress?.stage || '正在创建转码会话...'}
</ProgressStageText>
<DeterminateBarTrack>
<DeterminateBarFill $percent={progressPercent} />
</DeterminateBarTrack>
<ProgressPercentText>{progressPercent}%</ProgressPercentText>
</>
) : (
<>
<LoadingText>加载中...</LoadingText>
<LoadingBarContainer>
<LoadingBarProgress />
</LoadingBarContainer>
</>
)}
const progressPercent = Math.max(0, Math.min(100, Math.round(sessionProgress?.percent ?? 0)))
return (
<Container>
<LoadingContainer>
{waitingForSessionReady ? (
<>
<ProgressStageText>
{sessionProgress?.stage || t('player.transcode.creatingSession')}
</ProgressStageText>
<DeterminateBarTrack>
<DeterminateBarFill
$percent={progressPercent}
role="progressbar"
aria-valuemin={0}
aria-valuemax={100}
aria-valuenow={progressPercent}
/>
</DeterminateBarTrack>
<ProgressPercentText>{progressPercent}%</ProgressPercentText>
</>
) : (
<>
<LoadingText>加载中...</LoadingText>
<LoadingBarContainer>
<LoadingBarProgress />
</LoadingBarContainer>
</>
)}

Comment on lines +108 to +134
/**
* 音频进度信息
*/
export interface AudioProgressInfo {
status: string
progress_percent: number
processed_time: number
total_duration: number
transcode_speed: number
eta_seconds: number
error_message: string | null
}

/**
* 会话进度响应
*/
export interface SessionProgressResponse {
session_id: string
status: string
progress_percent: number
progress_stage: string
error_message: string | null
is_ready: boolean
playlist_url: string | null
audio_progress: AudioProgressInfo | null
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

进度类型与实际使用不一致,建议放宽为联合类型并将 stage 设为可选

PlayerPage 中对 progress_percent 做了 number/string 的兼容处理,且对 progress_stage 使用了可选链。为避免类型与后端/实际返回不一致导致的隐患,请将类型调整为联合并将 stage 设为可选。

 export interface AudioProgressInfo {
   status: string
-  progress_percent: number
+  progress_percent: number | string
   processed_time: number
   total_duration: number
   transcode_speed: number
   eta_seconds: number
   error_message: string | null
 }

 export interface SessionProgressResponse {
   session_id: string
   status: string
-  progress_percent: number
-  progress_stage: string
+  progress_percent: number | string
+  progress_stage?: string
   error_message: string | null
   is_ready: boolean
   playlist_url: string | null
   audio_progress: AudioProgressInfo | null
 }

请同时确认后端返回是否存在其它可能为 string 的数值字段(如 transcode_speed、eta_seconds),必要时一并放宽类型。As per coding guidelines

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* 音频进度信息
*/
export interface AudioProgressInfo {
status: string
progress_percent: number
processed_time: number
total_duration: number
transcode_speed: number
eta_seconds: number
error_message: string | null
}
/**
* 会话进度响应
*/
export interface SessionProgressResponse {
session_id: string
status: string
progress_percent: number
progress_stage: string
error_message: string | null
is_ready: boolean
playlist_url: string | null
audio_progress: AudioProgressInfo | null
}
/**
* 音频进度信息
*/
export interface AudioProgressInfo {
status: string
progress_percent: number | string
processed_time: number
total_duration: number
transcode_speed: number
eta_seconds: number
error_message: string | null
}
/**
* 会话进度响应
*/
export interface SessionProgressResponse {
session_id: string
status: string
progress_percent: number | string
progress_stage?: string
error_message: string | null
is_ready: boolean
playlist_url: string | null
audio_progress: AudioProgressInfo | null
}
🤖 Prompt for AI Agents
In src/renderer/src/services/SessionService.ts around lines 108 to 134, the
defined interfaces are too strict compared to actual usage: make numeric fields
that are treated as string or number (at least progress_percent and any
backend-returned numeric-like fields such as transcode_speed, eta_seconds,
processed_time, total_duration) into union types number | string, and mark
progress_stage as optional (progress_stage?: string). Update AudioProgressInfo
and SessionProgressResponse accordingly and audit other numeric fields returned
by the backend to relax types where needed.

…e tokens

- Import theme constants (SPACING, FONT_SIZES, ANIMATION_DURATION, etc.)
- Replace hardcoded width (240px) with SPACING.XXL * 5
- Replace hardcoded heights (4px) with COMPONENT_TOKENS.PROGRESS_BAR.TRACK_HEIGHT_HOVER
- Replace hardcoded border-radius (2px) with COMPONENT_TOKENS.PROGRESS_BAR.TRACK_BORDER_RADIUS
- Replace hardcoded font-sizes (16px, 14px) with FONT_SIZES.BASE and FONT_SIZES.SM
- Replace hardcoded transition timing with ANIMATION_DURATION.SLOW and EASING.STANDARD
- Fix: Add setTranscodeStatus('completed') call after HLS session completes

Changes ensure theme consistency, maintainability, and proper status tracking
across components. Progress bar now respects design system tokens for
cross-theme compatibility.
@mkdir700 mkdir700 merged commit 74de721 into dev Oct 13, 2025
5 checks passed
@mkdir700 mkdir700 deleted the mkdir700/hls-progress-integration branch October 13, 2025 01:12
@coderabbitai coderabbitai bot mentioned this pull request Oct 13, 2025
mkdir700 added a commit that referenced this pull request Oct 13, 2025
…ion (#209)

* feat(player): implement HLS session progress polling with visual feedback

- Add waitForSessionReady to poll session creation progress before playback
- Integrate useSessionProgress hook for reusable progress tracking logic
- Display deterministic progress bar with percentage and stage information during session initialization
- Add SessionService.getSessionProgress API with HTTP 425 handling for in-progress state
- Update backend submodule to v64aaf0b with HLS session progress support
- Remove excessive debug logging in SubtitleOverlay to reduce console noise

Changes:

PlayerPage:
- Add waitForSessionReady state and sessionProgress state for UI rendering
- Implement polling loop with 2s interval to fetch session progress until ready
- Display progress bar with stage text and percentage during session creation
- Handle HTTP 425 (session not ready) gracefully in progress polling
- Fallback to default playlist URL if progress response URL parsing fails

useSessionProgress Hook:
- Provide reusable session progress polling with configurable interval (default 2s)
- Auto-stop polling when session is ready or error occurs
- Expose startPolling, stopPolling, reset methods for lifecycle control
- Implement progress threshold (5%) to reduce log noise

SessionService:
- Add getSessionProgress(sessionId) API to fetch session creation progress
- Define SessionProgressResponse and AudioProgressInfo interfaces
- Treat HTTP 425 as normal in-progress state (not error)

This enhancement provides real-time visual feedback during HLS session
initialization, improving user experience by showing progress instead of
generic "loading..." spinner. The polling mechanism ensures playback starts
only after the session is fully ready, preventing premature playlist access.

* refactor(PlayerPage): replace progress bar hardcoded values with theme tokens

- Import theme constants (SPACING, FONT_SIZES, ANIMATION_DURATION, etc.)
- Replace hardcoded width (240px) with SPACING.XXL * 5
- Replace hardcoded heights (4px) with COMPONENT_TOKENS.PROGRESS_BAR.TRACK_HEIGHT_HOVER
- Replace hardcoded border-radius (2px) with COMPONENT_TOKENS.PROGRESS_BAR.TRACK_BORDER_RADIUS
- Replace hardcoded font-sizes (16px, 14px) with FONT_SIZES.BASE and FONT_SIZES.SM
- Replace hardcoded transition timing with ANIMATION_DURATION.SLOW and EASING.STANDARD
- Fix: Add setTranscodeStatus('completed') call after HLS session completes

Changes ensure theme consistency, maintainability, and proper status tracking
across components. Progress bar now respects design system tokens for
cross-theme compatibility.
@coderabbitai coderabbitai bot mentioned this pull request Oct 13, 2025
mkdir700 added a commit that referenced this pull request Oct 13, 2025
…ion (#209)

* feat(player): implement HLS session progress polling with visual feedback

- Add waitForSessionReady to poll session creation progress before playback
- Integrate useSessionProgress hook for reusable progress tracking logic
- Display deterministic progress bar with percentage and stage information during session initialization
- Add SessionService.getSessionProgress API with HTTP 425 handling for in-progress state
- Update backend submodule to v64aaf0b with HLS session progress support
- Remove excessive debug logging in SubtitleOverlay to reduce console noise

Changes:

PlayerPage:
- Add waitForSessionReady state and sessionProgress state for UI rendering
- Implement polling loop with 2s interval to fetch session progress until ready
- Display progress bar with stage text and percentage during session creation
- Handle HTTP 425 (session not ready) gracefully in progress polling
- Fallback to default playlist URL if progress response URL parsing fails

useSessionProgress Hook:
- Provide reusable session progress polling with configurable interval (default 2s)
- Auto-stop polling when session is ready or error occurs
- Expose startPolling, stopPolling, reset methods for lifecycle control
- Implement progress threshold (5%) to reduce log noise

SessionService:
- Add getSessionProgress(sessionId) API to fetch session creation progress
- Define SessionProgressResponse and AudioProgressInfo interfaces
- Treat HTTP 425 as normal in-progress state (not error)

This enhancement provides real-time visual feedback during HLS session
initialization, improving user experience by showing progress instead of
generic "loading..." spinner. The polling mechanism ensures playback starts
only after the session is fully ready, preventing premature playlist access.

* refactor(PlayerPage): replace progress bar hardcoded values with theme tokens

- Import theme constants (SPACING, FONT_SIZES, ANIMATION_DURATION, etc.)
- Replace hardcoded width (240px) with SPACING.XXL * 5
- Replace hardcoded heights (4px) with COMPONENT_TOKENS.PROGRESS_BAR.TRACK_HEIGHT_HOVER
- Replace hardcoded border-radius (2px) with COMPONENT_TOKENS.PROGRESS_BAR.TRACK_BORDER_RADIUS
- Replace hardcoded font-sizes (16px, 14px) with FONT_SIZES.BASE and FONT_SIZES.SM
- Replace hardcoded transition timing with ANIMATION_DURATION.SLOW and EASING.STANDARD
- Fix: Add setTranscodeStatus('completed') call after HLS session completes

Changes ensure theme consistency, maintainability, and proper status tracking
across components. Progress bar now respects design system tokens for
cross-theme compatibility.
github-actions bot pushed a commit that referenced this pull request Oct 13, 2025
# [1.1.0-alpha.3](v1.1.0-alpha.2...v1.1.0-alpha.3) (2025-10-13)

### Bug Fixes

* **codec-compatibility:** handle missing codec information gracefully ([46ed61a](46ed61a))
* **FFmpegSection:** manage completion timeout for download process ([99018a0](99018a0))
* **FFprobeSection:** add return statement to download progress polling function ([d99231f](d99231f))
* **FFprobeSection:** ensure timeout cleanup after download success ([75d8429](75d8429))
* **FFprobeSection:** manage success timeout for download completion ([f4332d0](f4332d0))
* **FFprobeSection:** standardize font size using theme constants ([4665620](4665620))
* **FFprobeSection:** standardize spacing in styled components ([ef89ef6](ef89ef6))
* **MediaServerService:** enhance error handling for file existence check ([fe552e3](fe552e3))
* **MediaServerService:** replace fs.existsSync with async stat for file existence check ([566af29](566af29))
* **player:** apply playback rate change through orchestrator when cycling speeds ([#210](#210)) ([d69cc52](d69cc52))
* **player:** remove HLS player missing error handling ([5c2aa64](5c2aa64))
* **TranscodeLoadingIndicator:** remove logging for loading indicator display ([fe69cd0](fe69cd0))
* **UvBootstrapperService:** enhance UV download logic with cached path checks ([e39cb7d](e39cb7d))
* **UvBootstrapperService:** ensure temp directory cleanup after download ([811b597](811b597))
* **UvBootstrapperService:** prevent concurrent downloads by checking download controllers ([17be090](17be090))
* **VolumeIndicator:** skip indicator display on initial render ([d0cfb23](d0cfb23))

### Features

* **media-server:** add transcode cache cleanup for deleted videos ([b5b9601](b5b9601))
* **player:** HLS session progress polling with media server integration ([#209](#209)) ([0135646](0135646))
mkdir700 added a commit that referenced this pull request Oct 15, 2025
…ion (#209)

* feat(player): implement HLS session progress polling with visual feedback

- Add waitForSessionReady to poll session creation progress before playback
- Integrate useSessionProgress hook for reusable progress tracking logic
- Display deterministic progress bar with percentage and stage information during session initialization
- Add SessionService.getSessionProgress API with HTTP 425 handling for in-progress state
- Update backend submodule to v64aaf0b with HLS session progress support
- Remove excessive debug logging in SubtitleOverlay to reduce console noise

Changes:

PlayerPage:
- Add waitForSessionReady state and sessionProgress state for UI rendering
- Implement polling loop with 2s interval to fetch session progress until ready
- Display progress bar with stage text and percentage during session creation
- Handle HTTP 425 (session not ready) gracefully in progress polling
- Fallback to default playlist URL if progress response URL parsing fails

useSessionProgress Hook:
- Provide reusable session progress polling with configurable interval (default 2s)
- Auto-stop polling when session is ready or error occurs
- Expose startPolling, stopPolling, reset methods for lifecycle control
- Implement progress threshold (5%) to reduce log noise

SessionService:
- Add getSessionProgress(sessionId) API to fetch session creation progress
- Define SessionProgressResponse and AudioProgressInfo interfaces
- Treat HTTP 425 as normal in-progress state (not error)

This enhancement provides real-time visual feedback during HLS session
initialization, improving user experience by showing progress instead of
generic "loading..." spinner. The polling mechanism ensures playback starts
only after the session is fully ready, preventing premature playlist access.

* refactor(PlayerPage): replace progress bar hardcoded values with theme tokens

- Import theme constants (SPACING, FONT_SIZES, ANIMATION_DURATION, etc.)
- Replace hardcoded width (240px) with SPACING.XXL * 5
- Replace hardcoded heights (4px) with COMPONENT_TOKENS.PROGRESS_BAR.TRACK_HEIGHT_HOVER
- Replace hardcoded border-radius (2px) with COMPONENT_TOKENS.PROGRESS_BAR.TRACK_BORDER_RADIUS
- Replace hardcoded font-sizes (16px, 14px) with FONT_SIZES.BASE and FONT_SIZES.SM
- Replace hardcoded transition timing with ANIMATION_DURATION.SLOW and EASING.STANDARD
- Fix: Add setTranscodeStatus('completed') call after HLS session completes

Changes ensure theme consistency, maintainability, and proper status tracking
across components. Progress bar now respects design system tokens for
cross-theme compatibility.
github-actions bot pushed a commit that referenced this pull request Oct 15, 2025
# [1.1.0-beta.1](v1.0.0...v1.1.0-beta.1) (2025-10-15)

### Bug Fixes

* **AppUpdater, FFmpegDownloadService:** update default mirror source to global ([83194b3](83194b3))
* **build:** adjust resource handling for media-server in packaging ([086bd1b](086bd1b))
* **codec-compatibility:** handle missing codec information gracefully ([ea29f21](ea29f21))
* **FFmpegSection:** manage completion timeout for download process ([39b43c0](39b43c0))
* **FFprobeSection:** add return statement to download progress polling function ([49636cf](49636cf))
* **FFprobeSection:** ensure timeout cleanup after download success ([81a1431](81a1431))
* **FFprobeSection:** manage success timeout for download completion ([ce55d49](ce55d49))
* **FFprobeSection:** standardize font size using theme constants ([6387445](6387445))
* **FFprobeSection:** standardize spacing in styled components ([ba3c3d4](ba3c3d4))
* **homepage:** improve bottom spacing for card grid ([#194](#194)) ([801b6cd](801b6cd))
* make subtitle overlay container semantic ([2d6ae60](2d6ae60))
* **MediaServerService:** enhance error handling for file existence check ([11b74ef](11b74ef))
* **MediaServerService:** replace fs.existsSync with async stat for file existence check ([c9c98da](c9c98da))
* **player:** apply playback rate change through orchestrator when cycling speeds ([#210](#210)) ([fa9aa09](fa9aa09))
* **player:** remove HLS player missing error handling ([c7b593e](c7b593e))
* remove green glow effect from progress bar ([#196](#196)) ([abc6f3e](abc6f3e)), closes [#e50914](https://github.com/mkdir700/EchoPlayer/issues/e50914) [#00b96](https://github.com/mkdir700/EchoPlayer/issues/00b96)
* **semantic-release:** enhance version increment rules for prerelease branches ([#199](#199)) ([5d1e533](5d1e533))
* **theme:** resolve theme color not updating immediately for Switch components and progress bars ([#197](#197)) ([eed9ea2](eed9ea2))
* **TranscodeLoadingIndicator:** remove logging for loading indicator display ([085db44](085db44))
* **useSubtitleScrollStateMachine:** start auto-return timer on user interactions ([8496ae0](8496ae0))
* **UvBootstrapperService:** enhance UV download logic with cached path checks ([fc0791a](fc0791a))
* **UvBootstrapperService:** ensure temp directory cleanup after download ([02c7b16](02c7b16))
* **UvBootstrapperService:** prevent concurrent downloads by checking download controllers ([19d31e7](19d31e7))
* **VolumeIndicator:** skip indicator display on initial render ([82d2281](82d2281))
* **workflow:** update artifact listing command for better compatibility ([dfb6ee4](dfb6ee4))

### Features

* integrate session-backed HLS playback flow ([#200](#200)) ([ee972d1](ee972d1))
* intro backend for hls player ([2d34e7b](2d34e7b))
* **media-server:** add transcode cache cleanup for deleted videos ([e2de9ad](e2de9ad))
* **media-server:** implement runtime runtime management system ([#204](#204)) ([f5f68b0](f5f68b0))
* optimize media-server build output to resources directory ([#201](#201)) ([1b8c28e](1b8c28e))
* **player:** add animated loading progress bar to PlayerPage ([#206](#206)) ([8ba6f7f](8ba6f7f))
* **player:** add media server recommendation prompt for incompatible videos ([#205](#205)) ([63221a2](63221a2))
* **player:** add subtitle search functionality ([c3228c3](c3228c3))
* **player:** add toggle auto-pause functionality ([98b59ef](98b59ef))
* **player:** HLS session progress polling with media server integration ([#209](#209)) ([a76e8c2](a76e8c2))
* **PlayerSettingsLoader:** add mask mode to subtitle overlay ([56e4f65](56e4f65))
* **player:** update seek button icons from rewind/fastforward to undo/redo ([#193](#193)) ([1612c43](1612c43))
* **RegionDetection:** integrate region detection service for IP-based country identification ([dbeb077](dbeb077))
* **subtitle:** introduce mask mode for subtitle overlay ([e1fb3eb](e1fb3eb))
* **SubtitleOverlay:** enhance positioning and collision handling ([92b061a](92b061a))
* **UvBootstrapperService:** enhance download management with concurrency control ([20522e9](20522e9))

### Reverts

* "fix(build): adjust resource handling for media-server in packaging" ([2133401](2133401))
github-actions bot pushed a commit that referenced this pull request Oct 16, 2025
# [1.1.0](v1.0.0...v1.1.0) (2025-10-16)

### Bug Fixes

* **AppUpdater, FFmpegDownloadService:** update default mirror source to global ([83194b3](83194b3))
* **build:** adjust resource handling for media-server in packaging ([086bd1b](086bd1b))
* **codec-compatibility:** handle missing codec information gracefully ([ea29f21](ea29f21))
* **FFmpegSection:** manage completion timeout for download process ([39b43c0](39b43c0))
* **FFprobeSection:** add return statement to download progress polling function ([49636cf](49636cf))
* **FFprobeSection:** ensure timeout cleanup after download success ([81a1431](81a1431))
* **FFprobeSection:** manage success timeout for download completion ([ce55d49](ce55d49))
* **FFprobeSection:** standardize font size using theme constants ([6387445](6387445))
* **FFprobeSection:** standardize spacing in styled components ([ba3c3d4](ba3c3d4))
* **homepage:** improve bottom spacing for card grid ([#194](#194)) ([801b6cd](801b6cd))
* make subtitle overlay container semantic ([2d6ae60](2d6ae60))
* **MediaServerService:** enhance error handling for file existence check ([11b74ef](11b74ef))
* **MediaServerService:** replace fs.existsSync with async stat for file existence check ([c9c98da](c9c98da))
* **player:** apply playback rate change through orchestrator when cycling speeds ([#210](#210)) ([fa9aa09](fa9aa09))
* **player:** remove HLS player missing error handling ([c7b593e](c7b593e))
* **player:** restore muted state when re-entering player page ([1ec5c56](1ec5c56))
* remove green glow effect from progress bar ([#196](#196)) ([abc6f3e](abc6f3e)), closes [#e50914](https://github.com/mkdir700/EchoPlayer/issues/e50914) [#00b96](https://github.com/mkdir700/EchoPlayer/issues/00b96)
* **semantic-release:** enhance version increment rules for prerelease branches ([#199](#199)) ([5d1e533](5d1e533))
* **theme:** resolve theme color not updating immediately for Switch components and progress bars ([#197](#197)) ([eed9ea2](eed9ea2))
* **TranscodeLoadingIndicator:** remove logging for loading indicator display ([085db44](085db44))
* **useSubtitleScrollStateMachine:** start auto-return timer on user interactions ([8496ae0](8496ae0))
* **UvBootstrapperService:** enhance UV download logic with cached path checks ([fc0791a](fc0791a))
* **UvBootstrapperService:** ensure temp directory cleanup after download ([02c7b16](02c7b16))
* **UvBootstrapperService:** prevent concurrent downloads by checking download controllers ([19d31e7](19d31e7))
* **VolumeIndicator:** skip indicator display on initial render ([82d2281](82d2281))
* **workflow:** update artifact listing command for better compatibility ([dfb6ee4](dfb6ee4))

### Features

* integrate session-backed HLS playback flow ([#200](#200)) ([ee972d1](ee972d1))
* intro backend for hls player ([2d34e7b](2d34e7b))
* **media-server:** add transcode cache cleanup for deleted videos ([e2de9ad](e2de9ad))
* **media-server:** implement runtime runtime management system ([#204](#204)) ([f5f68b0](f5f68b0))
* optimize media-server build output to resources directory ([#201](#201)) ([1b8c28e](1b8c28e))
* **player:** add animated loading progress bar to PlayerPage ([#206](#206)) ([8ba6f7f](8ba6f7f))
* **player:** add media server recommendation prompt for incompatible videos ([#205](#205)) ([63221a2](63221a2))
* **player:** add subtitle search functionality ([c3228c3](c3228c3))
* **player:** add toggle auto-pause functionality ([98b59ef](98b59ef))
* **player:** HLS session progress polling with media server integration ([#209](#209)) ([a76e8c2](a76e8c2))
* **PlayerSettingsLoader:** add mask mode to subtitle overlay ([56e4f65](56e4f65))
* **player:** update seek button icons from rewind/fastforward to undo/redo ([#193](#193)) ([1612c43](1612c43))
* **RegionDetection:** integrate region detection service for IP-based country identification ([dbeb077](dbeb077))
* **subtitle:** introduce mask mode for subtitle overlay ([e1fb3eb](e1fb3eb))
* **SubtitleOverlay:** enhance positioning and collision handling ([92b061a](92b061a))
* **UvBootstrapperService:** enhance download management with concurrency control ([20522e9](20522e9))

### Reverts

* "fix(build): adjust resource handling for media-server in packaging" ([2133401](2133401))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant