-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Editor video playback performance #1473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Remove frame padding stripping logic. Update frame processing to use stride and raw data. Improve shared buffer consumer with readInto and slot size. Increase shared buffer slot size. Update WebGPU renderer to use stride for bytesPerRow. Use Arc for decoded frame data to avoid cloning. Co-authored-by: richiemcilroy1 <richiemcilroy1@gmail.com>
…k-performance-6d4c Editor video playback performance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additional Comments (1)
-
apps/desktop/src-tauri/src/frame_ws.rs, line 58 (link)style: Inconsistent logging - both
println!andtracing::info!are used for the same messageNote: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
14 files reviewed, 5 comments
| const result = correctionBuffer.slice(0, expectedLength); | ||
| const response: StrideCorrectionResponse = { | ||
| type: "corrected", | ||
| buffer: result.buffer, | ||
| width, | ||
| height, | ||
| }; | ||
| self.postMessage(response, { transfer: [result.buffer] }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: The .slice() operation creates a full copy of the corrected data, negating the performance benefits of buffer reuse. Consider using correctionBuffer.subarray(0, expectedLength).slice() or transfer the original buffer directly if the worker doesn't need it anymore.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/utils/stride-correction-worker.ts
Line: 46:53
Comment:
**style:** The `.slice()` operation creates a full copy of the corrected data, negating the performance benefits of buffer reuse. Consider using `correctionBuffer.subarray(0, expectedLength).slice()` or transfer the original buffer directly if the worker doesn't need it anymore.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| let frame_opt = { | ||
| let mut rx = frame_rx.lock().await; | ||
| tokio::select! { | ||
| biased; | ||
| msg = socket.recv() => { | ||
| match msg { | ||
| Some(Ok(Message::Close(_))) | None => { | ||
| tracing::info!("WebSocket closed"); | ||
| break; | ||
| } | ||
| Some(Ok(_)) => { | ||
| continue; | ||
| } | ||
| Some(Err(e)) => { | ||
| tracing::error!("WebSocket error: {:?}", e); | ||
| break; | ||
| } | ||
| } | ||
| }, | ||
| frame = rx.recv() => frame, | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Potential deadlock: holding the mutex lock across the entire tokio::select! block could block other tasks trying to access the frame receiver. Is this intentional to ensure atomic processing of each frame, or could the lock scope be reduced?
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src-tauri/src/frame_ws.rs
Line: 178:199
Comment:
**logic:** Potential deadlock: holding the mutex lock across the entire `tokio::select!` block could block other tasks trying to access the frame receiver. Is this intentional to ensure atomic processing of each frame, or could the lock scope be reduced?
How can I resolve this? If you propose a fix, please make it concise.| for (let i = 0; i < frameQueue.length; i++) { | ||
| const frame = frameQueue[i]; | ||
| const frameNum = frame.timing.frameNumber; | ||
|
|
||
| const isSeek = | ||
| playbackStartTime !== null && | ||
| lastRenderedFrameNumber >= 0 && | ||
| (frameNum < lastRenderedFrameNumber || | ||
| frameNum > lastRenderedFrameNumber + 30); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: The seek detection logic uses a hardcoded threshold of 30 frames which may not work correctly for all frame rates. Should the seek detection threshold be based on frame rate or time duration instead of a fixed frame count?
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/utils/frame-worker.ts
Line: 436:444
Comment:
**style:** The seek detection logic uses a hardcoded threshold of 30 frames which may not work correctly for all frame rates. Should the seek detection threshold be based on frame rate or time duration instead of a fixed frame count?
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.| fallbackIndex = i; | ||
| } | ||
|
|
||
| if (diffMs < -LATE_THRESHOLD_MS && !isSeek) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Frame dropping threshold of 40ms may be too aggressive for lower frame rates where frames naturally arrive >40ms apart. Should LATE_THRESHOLD_MS be adjusted based on the target frame rate to avoid dropping frames that aren't actually late?
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/utils/frame-worker.ts
Line: 466:466
Comment:
**logic:** Frame dropping threshold of 40ms may be too aggressive for lower frame rates where frames naturally arrive >40ms apart. Should LATE_THRESHOLD_MS be adjusted based on the target frame rate to avoid dropping frames that aren't actually late?
How can I resolve this? If you propose a fix, please make it concise.
Summary
Originally merged to wrong branch in #1472.
Greptile Summary
Important Files Changed
apps/desktop/src/utils/frame-worker.tsapps/desktop/src-tauri/src/editor_window.rsapps/desktop/src/utils/socket.tsapps/desktop/src-tauri/src/frame_ws.rsapps/desktop/src/utils/stride-correction-worker.tsConfidence score: 3/5
frame_ws.rsfor the potential mutex deadlock issue andsocket.tsfor the substantial buffer size increase that could affect memory usageSequence Diagram
sequenceDiagram participant User participant Editor as Editor Component participant EditorInstance as EditorInstance participant Renderer as Renderer participant FrameWS as Frame WebSocket participant Worker as Frame Worker participant Decoder as Video Decoder User->>Editor: "Load project for editing" Editor->>EditorInstance: "create editor instance" EditorInstance->>Decoder: "spawn video decoders" EditorInstance->>Renderer: "initialize renderer" EditorInstance->>FrameWS: "create frame websocket" FrameWS->>Worker: "init shared buffer & canvas" User->>Editor: "seek to frame position" Editor->>EditorInstance: "emit render frame event" EditorInstance->>Decoder: "get frames for time" Decoder-->>EditorInstance: "return decoded frames" EditorInstance->>Renderer: "render frame with uniforms" Renderer->>Renderer: "composite layers (display, camera, cursor, effects)" Renderer-->>EditorInstance: "rendered frame data" EditorInstance->>FrameWS: "send frame via websocket" FrameWS->>Worker: "process frame with metadata" Worker->>Worker: "decode and queue frame" Worker-->>Editor: "frame rendered notification" User->>Editor: "start playback" Editor->>EditorInstance: "start playback with fps" EditorInstance->>EditorInstance: "spawn playback loop" loop Playback Loop EditorInstance->>Decoder: "get frames for current time" EditorInstance->>Renderer: "render frame" EditorInstance->>FrameWS: "send frame" FrameWS->>Worker: "process frame" Worker-->>Editor: "display frame" EditorInstance->>Editor: "update playhead position" end User->>Editor: "export video" Editor->>EditorInstance: "render video to channel" loop Export Loop EditorInstance->>Decoder: "get segment frames" EditorInstance->>Renderer: "render with export settings" Renderer-->>EditorInstance: "rendered frame" EditorInstance->>Editor: "export progress update" endContext used:
dashboard- CLAUDE.md (source)dashboard- AGENTS.md (source)