Skip to content

FFmpeg trim points#33

Merged
kentcdodds merged 7 commits into
mainfrom
cursor/ffmpeg-trim-points-31c9
Jan 26, 2026
Merged

FFmpeg trim points#33
kentcdodds merged 7 commits into
mainfrom
cursor/ffmpeg-trim-points-31c9

Conversation

@kentcdodds
Copy link
Copy Markdown
Member

@kentcdodds kentcdodds commented Jan 26, 2026

Adds a new 'Trim points' page for defining video trim ranges, generating ffmpeg commands, and executing them with live progress.


Open in Cursor Open in Web


Note

Introduces a dedicated Trim Points flow for defining removal ranges, previewing, and running ffmpeg with live progress.

  • New TrimPoints client page with waveform, timeline handles, range list, output summary, and command preview; navigable via header links
  • Server: adds POST /api/trim streaming endpoint (app/trim-api.ts) to run ffmpeg using normalized ranges and emit NDJSON logs/progress; integrates into src/app-server.ts
  • Shared trim utilities in app/trim-commands.ts to normalize ranges, compute output duration, and build ffmpeg args/preview
  • Router/config: registers /trim-points route and server handlers; app/client/app.tsx chooses page by pathname
  • Styling: extensive CSS for trim track, handles, waveform, and command panel
  • Editing workspace: adds "Cancel running" action and per-task cancel button; minor nav link to Trim Points

Written by Cursor Bugbot for commit 0ea8c33. This will update automatically on new commits. Configure here.

@cursor
Copy link
Copy Markdown

cursor Bot commented Jan 26, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@kentcdodds kentcdodds marked this pull request as ready for review January 26, 2026 21:34
Comment thread app/trim-api.ts
Comment thread app/client/trim-points.tsx
@cursor
Copy link
Copy Markdown

cursor Bot commented Jan 26, 2026

Bugbot Autofix resolved 2 of the 2 bugs found in the latest run.

  • ✅ Fixed: Race condition causes lost ffmpeg output before stream close
    • Changed to await both stdout and stderr readers using Promise.all before closing the stream controller to ensure all buffered output is processed.
  • ✅ Fixed: Cancel message overwritten by catch block error handling
    • Added a check for runController === null in the catch block to preserve the user-friendly cancellation message when abort occurs.

cursoragent and others added 4 commits January 26, 2026 21:55
Co-authored-by: me <me@kentcdodds.com>
Co-authored-by: me <me@kentcdodds.com>
- Wait for stdout/stderr readers to complete before closing stream
- Preserve user-friendly cancel message when abort occurs
Co-authored-by: me <me@kentcdodds.com>
@cursor cursor Bot force-pushed the cursor/ffmpeg-trim-points-31c9 branch from c58559f to a2fd531 Compare January 26, 2026 21:57
Co-authored-by: me <me@kentcdodds.com>

const loadWaveform = async (url: string) => {
if (!url || waveformStatus === 'loading') return
if (waveformSource === url && waveformStatus === 'ready') return
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Waveform data may display for wrong video

Medium Severity

The loadWaveform function returns early when waveformStatus === 'loading', but this creates a race condition. If a user loads video A and then quickly loads video B before A's waveform finishes, the second loadWaveform('B') call exits early without updating waveformSource. When video A's waveform fetch completes, its data is applied unconditionally (no check that waveformSource still matches the fetched URL), causing video A's waveform to display while video B is previewed.

Additional Locations (1)

Fix in Cursor Fix in Web

Comment thread app/client/trim-points.tsx
- Track fetched URL and discard stale waveform data when source changes
- Move cancelRun status updates inside runController check to prevent overwriting valid states
@cursor
Copy link
Copy Markdown

cursor Bot commented Jan 26, 2026

Bugbot Autofix resolved 2 of the 2 bugs found in the latest run.

  • ✅ Fixed: Waveform data may display for wrong video
    • Added fetchedUrl tracking and validation to discard stale waveform data when waveformSource changes during async operations.
  • ✅ Fixed: Cancel function overwrites status even when not running
    • Moved runStatus and runError assignments inside the runController conditional block to prevent overwriting valid states.

Comment thread app/client/trim-points.tsx
Comment thread app/client/trim-points.tsx
- Fix duration check to prevent negative timestamps for videos shorter than MIN_TRIM_LENGTH
- Add cleanup listener to abort ffmpeg operation when component unmounts
@cursor
Copy link
Copy Markdown

cursor Bot commented Jan 26, 2026

Bugbot Autofix resolved 2 of the 2 bugs found in the latest run.

  • ✅ Fixed: Insufficient duration check allows negative trim timestamps
    • Changed duration check from previewDuration <= 0 to previewDuration <= MIN_TRIM_LENGTH to prevent negative start values for very short videos.
  • ✅ Fixed: Missing cleanup of ffmpeg operation on unmount
    • Added handle.signal abort listener to cancel ongoing ffmpeg operations when the component unmounts.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

previewUrl = url
resetPreviewState()
handle.update()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Trim ranges persist when loading different video

Medium Severity

When loading a new video, trimRanges is not cleared. The resetPreviewState function only resets previewReady, previewError, and previewDuration, leaving existing trim ranges intact. If a user loads a shorter video after adding trim ranges to a longer one, the UI displays ranges that extend past the new video's duration. These invalid ranges appear in the list and timeline but are silently filtered out during normalization, causing a confusing "Add at least one trim range" error when the user attempts to run ffmpeg while seeing ranges in the UI.

Additional Locations (1)

Fix in Cursor Fix in Web

@kentcdodds kentcdodds merged commit 2504594 into main Jan 26, 2026
6 checks passed
@kentcdodds kentcdodds deleted the cursor/ffmpeg-trim-points-31c9 branch January 26, 2026 23:09
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 1.13.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants