Skip to content

feat(preview): MJPEG loopback stream server for single-surface playback (#64, #142)#153

Open
cuic19053-hue wants to merge 1 commit into
appergb:mainfrom
cuic19053-hue:feat-64-mjpeg-preview-stream
Open

feat(preview): MJPEG loopback stream server for single-surface playback (#64, #142)#153
cuic19053-hue wants to merge 1 commit into
appergb:mainfrom
cuic19053-hue:feat-64-mjpeg-preview-stream

Conversation

@cuic19053-hue

Copy link
Copy Markdown
Contributor

fixes #64
refs #142

问题

issue #142(P0 剪辑套件大面积失效)要求时间轴播放/预览按上游 palmier-pro 1:1 重写为单渲染面模型。当前预览是双面拼接(播放=DOM

修复

#64(MJPEG 回环传输)是 #142 忠实复刻路线的核心传输层:Rust 合成帧 → axum MJPEG 流 → 前端单 ,让 play/pause/seek/scrub 变成单面状态切换。

后端

  1. 新建 src-tauri/src/playback.rs:axum HTTP server 绑 127.0.0.1:0 随机端口,/stream 端点返回 multipart/x-mixed-replace MJPEG 流。�roadcast::channel::(2) 容量 2,满则丢帧不阻塞。
  2. 修改 src-tauri/src/render.rs:composite_frame 新增 preview: State<'_, Arc> 参数,渲染完成后 RGBA → JPEG(q75)→ sender.send() 推送到 broadcast channel。
    eceiver_count() > 0 守卫,无订阅时不编码(避免浪费 CPU)。
  3. 修改 src-tauri/src/lib.rs:注册 playback 模块 + get_preview_endpoint 命令。setup hook 中 �lock_on(PreviewServer::start()) 启动 server,manage 为 Tauri state。
  4. 修改 src-tauri/tauri.conf.json:csp: null → 明确 CSP,img-src/connect-src 含 http://127.0.0.1:*。

前端

  1. 修改 web/src/lib/api.ts:新增 getPreviewEndpoint(): Promise<string | null>。
  2. 修改 web/src/components/preview/Preview.tsx:mount 时获取 endpoint,播放态(isPlaying && previewEndpoint)渲染 消费 MJPEG 流;暂停/scrub 保留现有 imelineFrameUrl composite PNG 逻辑。

不在本 PR 范围

验证

  • cargo check -p opentake-tauri 通过 ✅
  • pnpm run build(tsc + vite)通过 ✅
  • 8 文件改动,219 行新增

安全

  • Server 绑 127.0.0.1(loopback only),外部网络不可达
  • CSP 限制 img-src/connect-src 仅 http://127.0.0.1:*
  • Broadcast channel 容量 2,满则丢帧不阻塞渲染线程

…ck (appergb#64, appergb#142)

- New src-tauri/src/playback.rs: axum HTTP server on 127.0.0.1:0 random
  port, /stream endpoint returns multipart/x-mixed-replace MJPEG stream.
  Broadcast channel (cap 2) feeds JPEG frames to connected <img> clients.
- render.rs: composite_frame pushes JPEG (q75) to broadcast sender when
  active subscribers exist (receiver_count > 0 guard avoids wasted CPU).
- lib.rs: register playback module + get_preview_endpoint command, start
  PreviewServer in setup hook via block_on, manage as Tauri state.
- tauri.conf.json: set explicit CSP with img-src/connect-src allowing
  http://127.0.0.1:* for the MJPEG stream.
- web/api.ts: add getPreviewEndpoint() wrapping invoke('get_preview_endpoint').
- web/Preview.tsx: playing state renders MJPEG <img> when previewEndpoint
  is available; paused/scrub retains existing composite PNG path.

This is the transport layer for issue appergb#142's single-surface model:
Rust composite frames flow through MJPEG to a single <img>, making
play/pause/seek a state switch on one render surface. The current frame
source is composite_frame (per-call GPU render); appergb#53's streaming decode
engine will replace it later.
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.

[#53-传输] 回环 axum MJPEG 预览流 + CSP + WebView2 回退

1 participant