Skip to content

Add video speed control and improve playback smoothness#15

Merged
izadoesdev merged 2 commits into
OpenCut-app:mainfrom
StarKnightt:feature/speed-control
Jun 23, 2025
Merged

Add video speed control and improve playback smoothness#15
izadoesdev merged 2 commits into
OpenCut-app:mainfrom
StarKnightt:feature/speed-control

Conversation

@StarKnightt
Copy link
Copy Markdown
Collaborator

@StarKnightt StarKnightt commented Jun 23, 2025

Added a speed control dropdown in the timeline toolbar that lets users change video playback speed between 0.5x to 2x. The dropdown shows the current speed and offers preset options.

Made video playback smoother by:

  • Using better timing for speed changes
  • Improving video synchronization
  • Reducing playback stutters
  • Making speed changes more responsive

The speed control is now easily accessible while editing and works smoothly with all video clips.

Description

This feature helps to make things faster or slower on the video as well as makes things better.

Fixes # (issue)

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

completely working fine. awesome one

Test Configuration:

  • Node version:
  • Browser (if applicable):
  • Operating System:

Screenshots (if applicable)

image
Here it is btw, simple and good, no extra things, simply makes your video faster or slower.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Additional context

Add any other context about the pull request here.

Summary by CodeRabbit

  • New Features

    • Added playback speed control for video clips, allowing users to adjust video speed using preset buttons, a slider, or a dropdown menu.
    • Video playback speed can now be changed dynamically during editing and preview.
  • Improvements

    • Smoother and more precise playback timing for video previews.
    • Enhanced Properties Panel to display speed controls when a video clip is selected.
  • Bug Fixes

    • Reduced unnecessary timing adjustments during video playback for a better viewing experience.

Added a speed control dropdown in the timeline toolbar that lets users change video playback speed between 0.5x to 2x. The dropdown shows the current speed and offers preset options.

Made video playback smoother by:
- Using better timing for speed changes
- Improving video synchronization
- Reducing playback stutters
- Making speed changes more responsive

The speed control is now easily accessible while editing and works smoothly with all video clips.
@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 23, 2025

Deploy Preview for appcut failed. Why did it fail? →

Name Link
🔨 Latest commit 9c61b72
🔍 Latest deploy log https://app.netlify.com/projects/appcut/deploys/68596a52f4fc6c00089b036a

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 23, 2025

Walkthrough

Playback speed control was introduced and integrated across the editor. A new SpeedControl component allows users to adjust video playback speed. The playback store and state were updated to support variable speed, and the video player now synchronizes playback rate accordingly. Timeline and UI components were also updated for speed selection.

Changes

File(s) Change Summary
apps/web/src/components/editor/properties-panel.tsx Enhanced PropertiesPanel to detect video clips and render SpeedControl for video playback speed adjustment.
apps/web/src/components/editor/speed-control.tsx Added new SpeedControl component for selecting and adjusting playback speed.
apps/web/src/components/editor/timeline.tsx Added playback speed dropdown to timeline toolbar; updates playback store on selection.
apps/web/src/components/ui/command.tsx Changed DialogProps import source to @radix-ui/react-dialog.
apps/web/src/components/ui/video-player.tsx Updated VideoPlayer to track and apply playback speed; improved time sync threshold and preload behavior.
apps/web/src/stores/playback-store.ts Replaced interval timer with requestAnimationFrame; added speed state and setSpeed method; events updated.
apps/web/src/types/playback.ts Extended PlaybackState and PlaybackControls interfaces to support speed and setSpeed.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PropertiesPanel
    participant SpeedControl
    participant PlaybackStore
    participant VideoPlayer

    User->>PropertiesPanel: Selects a video clip
    PropertiesPanel->>SpeedControl: Renders speed controls
    User->>SpeedControl: Adjusts speed (button/slider)
    SpeedControl->>PlaybackStore: setSpeed(newSpeed)
    PlaybackStore-->>VideoPlayer: Dispatch playback-speed event
    PlaybackStore-->>VideoPlayer: Update speed in store
    VideoPlayer->>VideoPlayer: Update playbackRate to newSpeed
Loading

Poem

A rabbit hopped and tweaked the flow,
Now videos can play fast or slow!
With sliders, buttons, speeds galore,
The timeline’s never been less of a bore.
So hop along and press that play—
Your clips will leap in any way!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@izadoesdev izadoesdev merged commit 13817a5 into OpenCut-app:main Jun 23, 2025
Copy link
Copy Markdown
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: 0

🧹 Nitpick comments (2)
apps/web/src/components/ui/video-player.tsx (1)

104-109: Consider potential redundancy in speed synchronization

The component now has two mechanisms for syncing video speed:

  1. Event listener for playback-speed events (lines 68-72)
  2. useEffect that syncs on speed changes (lines 104-109)

While this ensures synchronization, it could cause redundant updates since both mechanisms respond to speed changes.

Consider whether both synchronization mechanisms are necessary, or if one could be sufficient for cleaner code and potentially better performance.

apps/web/src/components/editor/properties-panel.tsx (1)

29-39: Consider refactoring to reduce code duplication.

The logic for finding the first video clip duplicates the pattern used for finding image clips. Consider extracting a reusable helper function to reduce duplication.

+  // Helper function to find first clip of a specific media type
+  const findFirstClipByType = (type: "video" | "image") => {
+    return tracks
+      .flatMap((track) => track.clips)
+      .find((clip) => {
+        const mediaItem = mediaItems.find((item) => item.id === clip.mediaId);
+        return mediaItem?.type === type;
+      });
+  };
+
   // Get the first video clip for preview (simplified)
-  const firstVideoClip = tracks
-    .flatMap((track) => track.clips)
-    .find((clip) => {
-      const mediaItem = mediaItems.find((item) => item.id === clip.mediaId);
-      return mediaItem?.type === "video";
-    });
+  const firstVideoClip = findFirstClipByType("video");
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 054c681 and f72f5c1.

📒 Files selected for processing (7)
  • apps/web/src/components/editor/properties-panel.tsx (1 hunks)
  • apps/web/src/components/editor/speed-control.tsx (1 hunks)
  • apps/web/src/components/editor/timeline.tsx (3 hunks)
  • apps/web/src/components/ui/command.tsx (1 hunks)
  • apps/web/src/components/ui/video-player.tsx (4 hunks)
  • apps/web/src/stores/playback-store.ts (4 hunks)
  • apps/web/src/types/playback.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
apps/web/src/components/editor/speed-control.tsx (1)
apps/web/src/stores/playback-store.ts (1)
  • usePlaybackStore (45-93)
apps/web/src/components/ui/video-player.tsx (1)
apps/web/src/stores/playback-store.ts (1)
  • usePlaybackStore (45-93)
🔇 Additional comments (18)
apps/web/src/components/ui/command.tsx (1)

4-4: LGTM: Import specificity improvement

Good change to import DialogProps directly from the specific Radix UI package rather than a generic import. This improves clarity and potentially enables better tree-shaking.

apps/web/src/types/playback.ts (2)

6-6: LGTM: Appropriate type addition for speed state

The speed property addition to PlaybackState properly extends the interface to support playback speed functionality.


14-14: LGTM: Consistent method signature for speed control

The setSpeed method addition follows the same pattern as other control methods in the interface, maintaining consistency.

apps/web/src/components/editor/timeline.tsx (3)

31-37: LGTM: Proper imports for Select components

The import of Select-related components is correctly added to support the new speed control dropdown in the timeline toolbar.


46-46: LGTM: Consistent playback store integration

Properly added speed and setSpeed to the playback store destructuring, maintaining consistency with existing playback controls.


342-363: LGTM: Well-integrated speed control in timeline toolbar

The speed control dropdown is excellently integrated:

  • Properly positioned in the toolbar with appropriate visual separation
  • Uses consistent speed format with .toFixed(1)
  • Provides common speed presets (0.5x to 2.0x)
  • Includes helpful tooltip for accessibility
  • Maintains visual consistency with existing toolbar elements

The integration provides users with convenient access to speed control during timeline editing.

apps/web/src/components/editor/speed-control.tsx (2)

6-11: LGTM: Well-defined speed presets

The SPEED_PRESETS constant provides sensible default speed options that match the timeline dropdown and align with common video editing workflows.


13-46: LGTM: Comprehensive speed control interface

Excellent implementation providing both preset buttons and fine-grained slider control:

  • Preset buttons use proper variant switching to indicate active state
  • Slider range (0.1-2.0) with 0.1 step provides good granularity
  • Speed display formatting is consistent throughout
  • Component structure follows good React patterns

Verify that the slider's speed range (0.1-2.0) matches the clamping logic in the playback store to ensure consistency:

#!/bin/bash
# Check playback store speed clamping range
rg -A 5 -B 5 "setSpeed.*=>" 
apps/web/src/components/ui/video-player.tsx (5)

28-28: LGTM: Proper speed state integration

Correctly added speed to the playback store destructuring to support dynamic playback speed control.


63-63: Review the increased sync threshold

The sync threshold was increased from 0.2 to 0.5 seconds. While this may reduce micro-adjustments and improve performance, it could affect playback precision for fine-grained synchronization needs.

Consider whether this threshold increase aligns with the desired playback smoothness and accuracy requirements for video editing workflows.


68-72: Verify clip range restriction for speed events

The speed event handler only updates playback rate when isInClipRange is true. This means speed changes won't affect videos outside their clip range, which may be inconsistent with user expectations.

Consider whether speed changes should apply globally to all video elements or only to those currently in range. The current behavior might cause confusion if users expect speed changes to affect all videos immediately.


76-76: LGTM: Proper event listener management

Event listener setup and cleanup for playback-speed events is correctly implemented with proper lifecycle management.

Also applies to: 81-81


119-119: Review preload attribute change

Changed from preload="metadata" to preload="auto". This may improve loading behavior for speed control responsiveness but will increase bandwidth usage as it loads entire videos upfront.

Ensure this change aligns with performance requirements and acceptable bandwidth usage for the target use case.

apps/web/src/components/editor/properties-panel.tsx (1)

124-129: LGTM! Consistent conditional rendering pattern.

The video controls conditional rendering follows the same pattern as image controls, maintaining consistency in the component structure.

apps/web/src/stores/playback-store.ts (4)

9-9: LGTM! Correct type change for requestAnimationFrame.

The type change from NodeJS.Timeout | null to number | null is correct for browser requestAnimationFrame handles.


14-36: Verify timer logic handles edge cases correctly.

The requestAnimationFrame approach with delta time calculation is a good improvement for smoother playback. However, there are a few potential concerns:

  1. The first frame might have an unexpectedly large delta if there's a delay between lastUpdate initialization and the first updateTime call
  2. The recursive requestAnimationFrame call happens regardless of playing state, which could waste resources

Consider adding safeguards for the first frame and optimizing the recursive calls:

 const updateTime = () => {
   const state = store();
   if (state.isPlaying && state.currentTime < state.duration) {
     const now = performance.now();
     const delta = (now - lastUpdate) / 1000; // Convert to seconds
+    // Cap delta to prevent large jumps (e.g., after tab becomes active)
+    const cappedDelta = Math.min(delta, 0.1); // Max 100ms jump
     lastUpdate = now;
     
-    const newTime = state.currentTime + (delta * state.speed);
+    const newTime = state.currentTime + (cappedDelta * state.speed);
     if (newTime >= state.duration) {
       state.pause();
     } else {
       state.setCurrentTime(newTime);
       // Notify video elements to sync
       window.dispatchEvent(new CustomEvent('playback-update', { detail: { time: newTime } }));
     }
   }
-  playbackTimer = requestAnimationFrame(updateTime);
+  // Only continue if still playing
+  if (state.isPlaying) {
+    playbackTimer = requestAnimationFrame(updateTime);
+  }
 };

50-50: LGTM! Appropriate default speed value.

The default speed of 1.0 (normal speed) is appropriate and aligns with standard video player conventions.


83-89: LGTM! Proper speed clamping and event dispatch.

The speed clamping between 0.1x and 2.0x is reasonable for most use cases, and the custom event dispatch pattern is consistent with other methods in the store.

@StarKnightt StarKnightt deleted the feature/speed-control branch August 3, 2025 14:58
zstar1003 pushed a commit to zstar1003/FlashCut that referenced this pull request Jan 28, 2026
Add video speed control and improve playback smoothness
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.

2 participants