Skip to content

Cut a clip: quick trim (part 1 of #326) - #439

Merged
KnifeLemon merged 14 commits into
KnifeLemon:mainfrom
flexeykinDev:feature/clip-trim
Oct 24, 2026
Merged

KnifeLemon merged 14 commits into
KnifeLemon:mainfrom
flexeykinDev:feature/clip-trim

Conversation

@flexeykinDev

Copy link
Copy Markdown
Contributor

What does this change?

The first part of #326, split as asked in its review: the quick trim Cut a clip only. There is no editor mode, no Join videos and no window zoom in this PR.

Cut a clip (tool-clip) makes a clip out of a longer video (for example 15–60 s of highlights) without leaving Filee. It goes first on the back of the video donut, in place of FLAC. FLAC stays in the library, so anyone who wants it can add it back. Settings schema 33 adds the tool to existing libraries the same way: first on the back face, FLAC taken off it. A back face the user filled up without FLAC, or one with the tool already on the front, is left as it is.

Dropping videos on the tool opens a window that looks like the crop overlay:

  • Choosing the clip:
    • the frame at the start, end or playhead, shown large;
    • an overview of the whole video: 16 frames, the loudness, handles and a ruler;
    • 15 s / 30 s / 60 s buttons; Z zooms in on the clip.
  • The sequence (Premiere-style, kept small): V1 pictures, A1 the video's own sound, A2 music from another file.
  • Space plays the clip as it will be written, with sound. The frames come from FFmpeg as raw BGRA over a pipe; the sound plays through ffplay from Filee's FFmpeg download (without it the preview is silent).
  • Editing:
    • C (blade) splits at the playhead;
    • Delete leaves a gap with a Close gap button; Shift+Delete closes up at once;
    • dragging a piece's edge takes back what was cut or cuts more away.
  • Per piece: volume (a line on A1), mute, and speed 0.25×–4× with the pitch kept.
  • For the whole clip:
    • several pieces selected at once;
    • the magnet (M);
    • Remove silence (silencedetect);
    • fade in / out;
    • Ctrl+Z / Ctrl+Y.

Writing it: Save starts an ordinary conversion (ClipTool.ConversionOf, which carries a ClipEdit in MediaOptions.Clip). The toast, cancel, the output rules ({name}_clip) and the history all work as for any conversion.

  • One plain stretch is copied with -ss/-to and -c copy (Fast, no re-encoding, the default).
  • Anything else is one filter graph (MediaEncoding.ClipGraphOf). It is encoded with the preset's quality, size and codec.

Docs: a Clip window section in docs/ARCHITECTURE.md next to Crop overlay, and the ffplay note in docs/ENGINES.md.

How was it tested?

  • dotnet format --verify-no-changes
  • dotnet test:
    • Core: all pass, including ClipToolTests (the schema 33 migration: FLAC replaced, a full back face, the tool on the front, a tool saved by an older Filee) and ClipCutterTests.
    • Engines: ClipTests, with real FFmpeg runs.
    • App: ClipWindowTests, RenderTests.Clip_window_renders, the donut flip and localization tests.
  • Tried in the app (Windows 11).

Screenshots (UI changes)

tests/Filee.App.Tests/bin/<config>/net10.0/screenshots/clip-*.png

Checklist

@KnifeLemon KnifeLemon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks @flexeykinDev, and thanks for splitting #326 so quickly and exactly as we asked. The scope is right: only the quick trim, no Join tool, tool-clip first on the video back face with to-flac taken off both the built-in face and the migration (it stays in the library), the "Clip window" section next to "Crop overlay" in ARCHITECTURE.md and the ffplay note in ENGINES.md. Leaving the EditorLayers.CleanUp fix for the editor PR makes sense, since that code isn't in this one.

I merged current main into it locally and built it (Release, dotnet format --verify-no-changes clean). Core tests 508/508 (3 skipped as usual), the Engines clip and media tests with real FFmpeg and ffplay 170/170, and the App clip, localization, donut flip and availability tests 157/158; the one failure is the Nepali key check, see below. The clip window renders cleanly in all eight RenderTests looks, Arabic right to left included. The arm64 "portable" job failed at the very end, in the smoke test (filee --quit exited with 1, Filee took longer than the timeout to exit). Nothing in this PR touches start-up or shutdown, and x64, both macOS jobs and the Windows build passed on the same commit, so we'll re-run it.

Since you opened the PR, main got Nepali (#334), so ne.json is now missing the 58 new strings. Don't worry about it, we'll add them when merging. The settings schema number is ours too: we renumber at merge time, in merge order, so 33 may become a later number.

A few small things before we merge:

  1. Keyboard access. The window style sets Focusable=False on every Button and ToggleButton, so Tab never reaches Fade in/out, Music…, Remove silence, Close gaps, 15/30/60 s, "Fast, no re-encoding", Skip, Maximize or Close, and some of these have no shortcut. A keyboard or screen reader user can't use them. The tunnel handlers already take Space and Enter (key down and key up), so clicking a button can't make Space press it later anyway. Please drop that style and, when a button has keyboard focus (reached with Tab), let Space/Enter press it instead of playing/saving.
  2. The work folder isn't swept after a crash. %TEMP%/Filee/clip-<hex> isn't a name JobQueue.DeleteStaleWorkFolders recognizes (10 lowercase hex characters), so if Filee is killed, the frames, loudness samples and preview JPEGs stay there. Naming the folder like a job folder under JobQueue.DefaultWorkRoot (Guid.NewGuid().ToString("N")[..10]) reuses the existing clean-up. That's the same thing we asked for on #437.
  3. Music picker. The file type is called "Audio", hard-coded in English, and the picker has no title. Please use a localized string for both (for example clip.music / a new clip.music_files).
  4. Volume range. The slider goes up to 2 and the hint says 0–200 %, but ClipPart.MaxVolume is 4 ("+12 dB") and Clamped keeps up to 4. Please pick one limit so the model, the slider and the text agree.
  5. Audio tracks (small). "Fast, no re-encoding" keeps every audio track (-map 0:a), but an exact cut or an edited clip keeps only the first (0:a:0). Fine either way, but please make it the same, or say so in the fast_hint, so a multi-track video doesn't lose tracks only when a setting changes.

Optional, no need to block on it: Esc closes the window right away, even after a lot of cutting. A quick "Discard this clip?" when there are edits, or Esc only stopping playback and clearing the selection, would save someone's work now and then.

Thanks again, this is really nice work, and we're looking forward to the editor part on top of it.

…focused from the keyboard), the work folder named like a job's so a crash sweep takes it, a localized music picker, volume up to 200 % everywhere, the first audio track when copying too
@flexeykinDev

Copy link
Copy Markdown
Contributor Author

Thanks for the careful review! All five are in 1996df4:

  1. Keyboard access: the Focusable=False style is gone, so Tab reaches every button. A button focused from the keyboard (Tab or arrows) is pressed by Space / Enter as usual. After a click, Space still plays and Enter still saves, so a clicked button is never pressed again by them. New test: A_button_reached_with_Tab_is_pressed_by_Space_and_Enter.
  2. Work folder: it is now JobQueue.DefaultWorkRoot/<10 hex>, so DeleteStaleWorkFolders sweeps it after a crash.
  3. Music picker: it has a title and a localized file type (clip.music_pick, clip.music_files, in every language the PR has).
  4. Volume: ClipPart.MaxVolume is now 2 (+6 dB), so the model, the slider, the A1 line and the 0–200 % hint agree.
  5. Audio tracks: Fast, no re-encoding now keeps the first audio track (0:a:0), like the exact and edited clips and Filee's other video conversions.

The Esc confirmation I'd rather do with the editor PR, where there's more work to lose. I'll add it there unless you'd like it in this one.

@flexeykinDev

Copy link
Copy Markdown
Contributor Author

I merged current main and added the Nepali strings for the clip window (395fd67), so the localization check passes again and you don't need to add them at merge time.

@KnifeLemon KnifeLemon left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks @flexeykinDev, all five are in: Tab reaches every button and Space / Enter press the one reached from the keyboard (sliders and lists keep their arrows too), the work folder is named like a job's under JobQueue.DefaultWorkRoot, the music picker has a localized title and file type, the volume stops at 200 % everywhere, and thanks for adding the Nepali strings yourself. Keeping the Esc confirmation for the editor PR is fine.

On 395fd67: Core 510/513, the clip, media-encoding and FFmpeg tests 98/98 with real FFmpeg, the clip window, availability, donut flip and localization tests 159/159, and dotnet format is clean.

Main moved again after your push (#464, #401, #445), so the branch conflicts in BuiltInData, AppSettings, UserDataStore, FfmpegConverter and MediaEncoding. That's on us; when merging we'll:

  • line the audio tracks up with main. Since #401 (issue #396) main keeps every audio track when it converts a video, so "the first track, like Filee's other conversions" no longer holds. The fast copy and the exact cut will keep every track as main's Video() does (the first one in FLV and DV), and an edited clip, which goes through one filter graph, keeps the first track; clip.fast_needs_encode will say so.
  • keep raw camera streams (.h264, .h265, main's MediaInfo.RawStream) off the fast copy: they carry no timestamps, so a clip of one is always encoded.
  • put "Cut a clip" first on the video donut's back face as you have it, in place of FLAC: main's back face is now full (12) with "Extract audio", "Compress video" and "Merge videos", so it stays at 12.
  • add the Thai strings for the 60 keys, fix clip.fast_hint in Korean to 해요체, and move the doc comment MusicPickerTitle took from BusyText back.
  • give the settings schema its number in merge order.

Approving; the editor part is welcome on top of this once it's in.

To get this into the next release, we'll push the remaining changes to your branch ourselves today (maintainer edits are on). Have a look at the commits when they land, and tell us if anything looks off.

KnifeLemon and others added 9 commits October 24, 2026 03:10
Cut a clip keeps its settings migration after main's schema 41 (now 42) and
sits first on the video donut's back face in place of FLAC, next to main's
everyday tools. An exact clip keeps the first audio track, as a copied or
edited clip does, while other conversions keep every track. Thai strings for
the clip window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's spreadsheet print studio (KnifeLemon#437) took settings schema 42, so Cut a
clip moves to 43. The print studio's preset has no Tool of its own, which
this branch reads as a crop: WindowService.ShowTool opens the studio before
it reaches the crop, and PresetAvailability judges it before the crop check.
A schema 36 library now gets the clip tool first on the video back face too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The palette test no longer adds its own "tool-clip": the clip tool is a
built-in preset on this branch, and a second one under the same id put a
chip twice under the Edit tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ersions)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FITS (KnifeLemon#505) took settings schema 43, so Cut a clip moves to 44.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The USM video format (KnifeLemon#508) takes schema 44 and goes into main first, so
the clip tool's migration moves to 45.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
USM (KnifeLemon#508) is schema 44 on main; Cut a clip stays at 45, after it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@KnifeLemon
KnifeLemon merged commit bedc0f6 into KnifeLemon:main Oct 24, 2026
10 checks passed
KnifeLemon added a commit to Perricheno/Filee that referenced this pull request Oct 24, 2026
Cut a clip (KnifeLemon#439) is schema 45 and USM 44 on main; the PDF Edit group stays
at 46. WindowService.ShowTool opens the page editor for "Reorder / delete
pages" and "Add pages" before the crop (their presets have no Tool of their
own, which reads as a crop; "Crop PDF" is one), and PresetAvailability
judges the PDF tools before the image crop. Turkish strings for the PDF
page tools. The palette tests now expect "Edit" among the built-in groups
and leave the PDF tools out where a single kind is the point.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants