Commit Graph

491 Commits

Author SHA1 Message Date
Brandon Thomas 7811da4ec0
Merge pull request #122 from coygeek/docs/add-star-history
docs: add star history chart to README
2026-10-07 05:57:38 -04:00
Brandon Thomas ce9d43a014
Merge pull request #128 from punkhop/fix/crisp-line-icons
Icons: draw straight lines on whole device pixels
2026-10-07 05:57:34 -04:00
Brandon Thomas 98979fdf74
Merge pull request #127 from carlitosteso3/i18n-spanish
i18n: Spanish interface language (Español)
2026-10-07 05:57:31 -04:00
Brandon Thomas dc16c0e219
Merge pull request #126 from carlitosteso3/fix/packaging-metadata
Packaging: describe FilmCraft, not PhotoCraft, in package metadata (#94, #100)
2026-10-07 05:57:27 -04:00
Brandon Thomas 631235e8b2
Merge pull request #120 from justjohn12345/pr/timeline-scrolling
Timeline: the wheel scrolls as in Premiere, and the view cannot be lost
2026-10-07 05:57:23 -04:00
Brandon Thomas 2bfcd512c2
Merge pull request #79 from justjohn12345/pr/layer-corner-scaling
graphics: all eight layer handles scale towards the pointer
2026-10-07 05:57:19 -04:00
Brandon Thomas aa1143ea74
Merge pull request #109 from dcarnelutti/gpu/alpha-plane-upload
gpu: upload and composite the alpha plane of Y'CbCr frames
2026-10-07 05:57:15 -04:00
Brandon Thomas 36d8114d2f
Merge pull request #118 from HEOJUNFO/fix/probe-pixfmt-from-config
codecs: MP4/MOV pixel format and alpha come from hvcC, avcC and the ProRes frame header (#103)
2026-10-07 05:57:10 -04:00
Brandon Thomas 79057f9c36
Merge pull request #102 from EthanSuquet/fix/mp4-duration-edit-list
codecs: an MP4/MOV clip lasts as long as its edit list plays it
2026-10-07 05:57:06 -04:00
Brandon Thomas cb69b55e56
Merge pull request #101 from EthanSuquet/fix/h264enc-corrupt-frames
h264enc: strict ffmpeg oracle that sees damaged slices (#74)
2026-10-07 05:57:01 -04:00
Brandon Thomas 7fcbaeab5e
Merge pull request #83 from EthanSuquet/fix/webm-frame-lookup-rounding
codecs: look video frames up by the nearest timestamp unit (WebM at 30 fps drops every third frame)
2026-10-07 05:56:56 -04:00
Brandon Thomas 205e4bf68e
Merge pull request #96 from punkhop/fix/move-onto-occupied-spot
timeline.move: report the clips an overwrite move covers
2026-10-07 05:56:52 -04:00
Brandon Thomas b8cc3925c3
Merge pull request #68 from punkhop/fix/clear-deletes-a-bin
project: Clear deletes a bin it is given, with everything in it
2026-10-07 05:56:48 -04:00
Brandon Thomas 6a0fca1cd1
Merge pull request #64 from punkhop/fix/xml-master-clip-keeps-its-bin
interchange: an FCP7 master clip lands in its bin when a sequence used it first
2026-10-07 05:56:44 -04:00
Brandon Thomas 05a731b309
Merge pull request #77 from justjohn12345/pr/test-fixes
Tests: fix seed_sweep overflow and the speed-dependent export progress test
2026-10-07 05:56:39 -04:00
carlitosteso3 96e9a00997 packaging: describe FilmCraft, not PhotoCraft, in package metadata (#94, #100)
The Linux, macOS, web and Windows packaging still carried PhotoCraft's
image-editor metadata.

- nfpm.yaml (#94): deb/rpm summary and description describe the video
  editor; filmcraft-cli is a command runner, MCP server and exporter;
  Debian section video instead of graphics.
- AppStream (#100): AudioVideo/Video/AudioVideoEditing categories, matching
  the desktop entry; video keywords; the screenshot is the README hero image
  (the old filmcraft-demo.jpg URL was a 404).
- macOS Info.plist.in (#100): export the .fcproj project type (JSON) instead
  of PhotoCraft's .pcraft; app category video; drop the PSB and QOI imported
  types, which FilmCraft does not read.
- filmcraft.wxs header comment: the MSI declares no file associations.
- web hosting guide: iframe title "FilmCraft video editor".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:06:08 -05:00
carlitosteso3 ed535180cb i18n: Spanish interface language
Add Español next to English and 日本語 (Edit ▸ Language ▸ Español, also in the
native menu bar). SPANISH covers every menu, submenu and menu item label
(347 entries, Latin American Spanish); names, formats and percentages stay
as they are. A new test checks that every entry is a current menu label, so
a renamed command cannot leave a dead entry behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:06:02 -05:00
Peet Guercio 3a48a99c94 Icons: draw straight lines on whole device pixels
The panel menu mark (≡) on the active tab was three 1.5 pt lines placed
at fractional positions, so at 1x they straddled pixels and anti-aliasing
made the gaps look uneven (3 px then 4 px). Every line icon had the same
half-pixel blur.

The icon pen now draws strokes a whole number of device pixels wide and
snaps every horizontal or vertical segment (and any that runs less than
a pixel sideways) onto the pixel grid, rounding from the icon's centre
the same way on both sides, so equal steps on the 16 grid stay equal on
screen at 1x and 2x. The tab's menu mark is now the Hamburger icon drawn
by the pen instead of hand-drawn lines.

Tests: every icon at 1x and 2x at four sizes off the pixel grid has only
whole-pixel straight lines; the menu mark's two gaps are equal at 1x,
1.5x and 2x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:40:55 -07:00
Coy Geek 8d5acae231 docs: add star history chart to README
Show FilmCraft GitHub star growth with a linked Star History chart at the bottom of the README. Preserve the date view and top-left legend.
2026-10-06 19:33:01 -07:00
justjohn12345 0bcfcfff16 Timeline: the wheel scrolls as in Premiere, and the view cannot be lost
Three problems with scrolling the Timeline:

1. Cmd + wheel zoomed, like Option + wheel. egui turns Cmd + wheel into a
   zoom before the panel sees it, and the panel only knew "zoom" and "scroll
   sideways".
2. The plain wheel scrolled sideways; the tracks could only be scrolled up
   and down with Shift held.
3. The view could be scrolled without limit past the end of the sequence (39
   minutes past a 26 second one). There the zoom scroll bar's thumb sat at
   the right end and stayed there when dragged: the bar's range grew with the
   scroll position, so the view moved but the thumb did not.

Now, as Premiere Pro 26.5.2 does on macOS (checked in the app):
- wheel: the tracks under the pointer, up and down (video tracks above the
  divider, audio tracks below);
- Cmd + wheel: the Timeline, sideways;
- Option + wheel: zoom about the pointer.
The existing setting Timeline Mouse Scrolling ("Vertical" by default) is
wired up: "Horizontal" swaps the first two. A sideways gesture (trackpad
swipe, tilt wheel, Shift + wheel) always scrolls sideways and a pinch zooms.
The wheel is read from its events, with their own modifiers.

The Timeline ends ten minutes past the end of the sequence, where Premiere's
view stops too, and the view is kept inside it however it is moved (wheel,
scroll bar, zoom, a script; not-a-number positions are reset).

The zoom scroll bar spans that extent. Its thumb is as wide as the share in
view, never narrower than 34 points, and its travel covers the whole scroll
range: it reaches both ends of the bar and stays under the pointer while
dragged (the drag follows the pointer's position, not a sum of steps). A
click or press beside the thumb brings the thumb there. The handles at its
ends zoom as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 22:14:00 -04:00
heojunfo f761a299a7 codecs: MP4/MOV pixel format and alpha come from hvcC, avcC and the ProRes frame header (#103)
The probe guessed the pixel format from the codec profile alone: HEVC
reported nothing, H.264 High 4:2:2 had no bit depth, and ProRes 4444
claimed alpha because of its fourcc.

- HEVC: chroma format and bit depth from hvcC.
- H.264: from the avcC High-profile extension (ISO/IEC 14496-15 §5.3.3),
  else from the first SPS; unknown (empty) if neither can be read.
- ProRes: the first frame header gives the chroma format and alpha
  (alpha_channel_type), as the first DNx frame header already does.

Checked against ffprobe on ffmpeg-made HEVC 4:2:0/4:2:2 8/10-bit,
H.264 4:2:0/4:2:2 8/10-bit and ProRes 422 HQ / 4444 with and without
alpha. Unit tests cover hvcC, avcC (extension and SPS fallback) and
ProRes 4444 with and without alpha.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-07 10:44:38 +09:00
Dario Carnelutti 1b92ea210b gpu: upload and composite the alpha plane of Y'CbCr frames
The GPU compositor uploaded only the Y, Cb and Cr planes of a Yuv8/Yuv16 frame and
the shader returned alpha 1.0 for them, so a ProRes 4444 overlay (banner, lower third,
outro) was drawn opaque in the Program monitor and covered the footage under it.
Exports were correct because they use the CPU compositor.

Frames with an alpha plane now upload it as a fourth texture (R8Unorm, or R16Float
converted like the other planes), bound at binding 5 of the layer and blend layouts.
A uniform slot (p3.y) carries the alpha scale (0 = no alpha plane); the shader reads
the alpha at full resolution and premultiplies the linear colour by it.

Adds gpu_draws_yuv_alpha_plane_like_the_cpu: an alpha ramp over an opaque layer at
8, 10 and 12 bits, GPU against the CPU compositor. It fails without the change
(p99 diff 190/255) and passes with it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 15:04:48 -06:00
EthanSuquet 1f2f20a700 codecs: an MP4/MOV clip lasts as long as its edit list plays it
The clip duration came from the media duration (`mdhd`), which runs on
the decode timeline. ffmpeg / x264 MP4s with B-frames skip the reorder
delay with an edit, so every one imported a frame too long (a 120-frame
file became 121 frames, the last a held repeat). A video track delayed
by a leading empty edit was a frame short, and its last frame could not
be reached.

Use the sum of the track's edits (movie timescale, what `tkhd` records)
when there is an edit list. Fragmented files, and edit lists that add up
to nothing or overflow a Tick, keep the media duration.

Tests: a unit test with crafted edit lists (skip, empty edit, hostile
sizes) and an ffmpeg oracle test (libx264 with B-frames: 60 frames,
was 61).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:37:06 -04:00
Peet Guercio dfaf31bfec Timeline: timeline.move reports the clips an overwrite move covers
An overwrite move shortens, splits or removes whatever already sits where a
clip lands, as Premiere's drag does, but the reply only named the clips it
moved: a script moving clips one at a time never learned that an earlier move
had cut one it had not reached yet. The reply now lists each covered clip
under `overwritten` with its length before and after and the ids what is
left of it lives on as. The edit itself is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:19:04 -07:00
EthanSuquet 3eae70b11e h264enc: strict ffmpeg oracle that sees damaged slices (#74)
ffmpeg prints "corrupt decoded frame" as a warning, so the oracle's
`-v error -ec 0` decode let a stream with a whole slice missing pass
silently. Switching that decode to `-v warning` is not enough: with
`-ec 0`, ffmpeg 7.1/8.1 flags every picture that has more than one
slice, libx264's multi-slice streams included, while the pixels are
unchanged. That is the 119/120 in #74; the encoder's bitstream is not
at fault (VideoToolbox decodes the same streams bit-identically, and
ffmpeg with strict error detection reports nothing).

The oracle now decodes with ffmpeg's default concealment, `-v warning`
and `-err_detect +crccheck+bitstream+buffer+explode`, fails on any
output or a non-zero exit, and still compares every pixel with the
encoder's reconstruction. A negative control drops and truncates
slices (CAVLC and CABAC, 3 slices) and checks the oracle reports each
one; it fails with the old flags.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:02:53 -04:00
EthanSuquet 2b49201e84 codecs: video frames are looked up by the nearest timestamp unit, so a 1 ms WebM shows every frame
Problem (#73): a 30 fps WebM played and exported with every third frame
missing and the frame before it shown twice (20 unique frames a second).
The same happens at 29.97, 60, 59.94, 24 and 23.976 fps, and with MP4
files whose video track has a 1 ms timescale. 25 and 50 fps were fine.

Cause: Matroska stores block timestamps in TimestampScale units (usually
1 ms), rounded to the nearest unit, so at 30 fps frame 2 (66.67 ms) is
stored as 67. MkvSource::video_frame converted the requested time to track
units with a floor (66), and the lookup (last sample with pts <= target)
returned frame 1. Every frame whose timestamp was rounded up was skipped.
Mp4Source::video_at, and the web build's WebCodecs MP4 path, floored the
same way against the track timescale; normal MP4 timescales hold frame
times exactly, so only coarse (1000) timescales were hit.

Fix: new Tick::to_rational_round (nearest unit, halves up, total for zero
and negative timebases), used for the video lookup target and the
catch-up threshold in mkv.rs, mp4.rs and webcodecs.rs. A requested time
now matches a frame whose stored timestamp is within half a unit of it,
the same precision the timestamps have. Truncating muxers (stamps rounded
down) still work. Times on exact timebases (90 kHz, 15360, 30000/1001…)
convert exactly as before.

Test: crates/codecs/src/rounded_pts_tests.rs builds synthetic Motion-JPEG
streams in the test (each picture shows its index as black/white blocks),
muxed as WebM with 1 ms timestamps and as MOV with a 1000 timescale, at
30, 29.97, 60, 59.94, 24, 23.976 and 25 fps with nearest and truncated
stamps. Requesting every frame's start over 3 s must show every frame
exactly once, and every frame's midpoint must show that frame. Before the
fix both tests failed ("30 fps, Nearest ms stamps: 30 of 90 frames never
shown [2, 5, 8, 11]…, 30 shown twice [1, 4, 7, 10]…"). The time crate
tests cover the rounding, ties and hostile timebases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 15:16:37 -04:00
Brandon Thomas 771b614ad4
Merge pull request #81 from storytold/pr/craft-fonts
Fonts: use craft-fonts as an optional build input (Japanese UI and title fallback)
2026-10-06 15:08:06 -04:00
Brandon Thomas 7f8e102b13 Fonts: the Japanese interface uses craft-fonts first; absolute CRAFT_FONTS_DIR
The merged Japanese interface (#38) looked only for a system font. When
FilmCraft is built with craft-fonts, theme::install already appends the
Japanese faces to every font family, so switching to Japanese uses them
(no system scan) and works on the web too; otherwise it falls back to an
installed system font as before. Docs use an absolute CRAFT_FONTS_DIR
(build.rs runs in crates/text, so a relative path resolves from there).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:26:14 -04:00
justjohn12345 b0aeabdb8d graphics: all eight layer handles scale towards the pointer
A corner handle scales both axes alike with the opposite corner held in place;
the edge handles (top, right, bottom, left) are now grabbable and stretch only
their own axis with the opposite edge held in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:17:29 -04:00
justjohn12345 c80d23fd2e graphics: a corner handle scales the layer away from the opposite corner
Dragging a corner handle of a graphic layer in the Program monitor scaled about
the layer's anchor, so a text layer (anchor at its bottom-left) grew up and to
the right whichever corner was dragged. The opposite corner now stays in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:52:20 -04:00
justjohn12345 ea491ef467 automation: the export progress test no longer depends on machine speed
A short export can finish inside one 100 ms poll, which left a single progress
notification and no time to answer the ping. The test now tries longer exports
until one outlasts a few polls, and cancels a longer one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:51:43 -04:00
justjohn12345 fb824c6fb0 mpeg2v: seed_sweep derives its seeds without overflowing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:51:43 -04:00
Brandon Thomas 9953befe28 Fonts: use craft-fonts as an optional build input
crates/text/build.rs embeds the fonts of a storytold/craft-fonts checkout
named by CRAFT_FONTS_DIR as filmcraft_text::fonts::CRAFT_FONTS (native:
all of them; wasm32: only BIZ UDPGothic Regular). Unset, CRAFT_FONTS is
empty and nothing changes. A bad CRAFT_FONTS_DIR is a warning, or an
error with CRAFT_FONTS_REQUIRED=1. Never a Cargo dependency, no network.

- UI: the Japanese faces are the last fallback of every egui font family
  (BIZ UDPGothic first, Bold first in the semibold/medium families).
- Text engine: registered after the bundled faces; fallback_for picks
  them after the bundled faces and before system faces (Mincho for serif
  text, Gothic otherwise, nearest weight).
- Tests: Japanese glyphs (no tofu) in the UI and title paths, skipped
  without craft-fonts; the theme works with CRAFT_FONTS empty.
- Release: every build job checks out craft-fonts at a pinned commit and
  builds with CRAFT_FONTS_DIR + CRAFT_FONTS_REQUIRED; packages carry
  OFL-<family>.txt. NOTICE, ATTRIBUTION.md (optional build input), AGENTS.md,
  CLAUDE.md, README and docs/contributing.md describe it.

FilmCraft main bundles no Japanese font, so no font files move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:40:29 -04:00
Brandon Thomas a2f6ba8b44
Merge pull request #72 from storytold/pr/docs-hw-decode-correction
Docs: hardware decode correction; log the 2026-10-06 community batch
2026-10-06 11:39:47 -04:00
Brandon Thomas 83481c146f Docs: hardware decode was only active in the desktop app since #41; log the 2026-10-06 community batch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:39:41 -04:00
Brandon Thomas 5c8471c9f4
Merge pull request #41 from justjohn12345/pr/decode-memory
MEM1–MEM4 + HW1: clip memory on a timeline from 12 GB to 1.9 GB; hardware decode actually on
2026-10-06 11:38:03 -04:00
Brandon Thomas 37361900a9
Merge pull request #38 from midasdf/feat/japanese-interface-language
i18n: Japanese interface language (uses an installed system font)
2026-10-06 11:37:57 -04:00
Brandon Thomas e89feeac4d
Merge pull request #58 from punkhop/fix/speed-ripples-linked-clips-once
edit: a speed change with ripple moves later clips once
2026-10-06 11:37:52 -04:00
Brandon Thomas 555bfe7c18
Merge pull request #57 from punkhop/fix/ripple-delete-split-edit
edit: ripple delete closes one gap for a clip with a split edit
2026-10-06 11:37:47 -04:00
Brandon Thomas 5dd09386f6
Merge pull request #56 from punkhop/fix/ripple-trim-keeps-split-edit
edit: a ripple trim takes a later split edit along
2026-10-06 11:37:42 -04:00
Brandon Thomas 475c294678
Merge pull request #45 from punkhop/fix/move-linked-partners
engine: timeline.move takes linked partners along
2026-10-06 11:37:38 -04:00
Brandon Thomas 51026bd2b2
Merge pull request #60 from punkhop/fix/place-on-a-sound-track
engine: timeline.place on an audio track places the sound there
2026-10-06 11:37:32 -04:00
Brandon Thomas d886d2f322
Merge pull request #44 from punkhop/fix/unknown-track-is-an-error
engine: naming a track that does not exist is an error
2026-10-06 11:37:28 -04:00
Brandon Thomas 39ef62607d
Merge pull request #47 from punkhop/fix/app-help-and-unknown-flags
filmcraft: --help prints usage and an unknown option is an error
2026-10-06 11:37:22 -04:00
Brandon Thomas 8dfa8fff4c
Merge pull request #52 from punkhop/fix/explicit-targets-enable
engine: a command whose targets are named in the parameters does not need a selection
2026-10-06 11:37:16 -04:00
Brandon Thomas 8a795324f4
Merge pull request #50 from punkhop/fix/replace-reports-short-media
engine: Replace With Clip reports clips that run past the new media
2026-10-06 11:37:11 -04:00
Brandon Thomas eb3ca3e811
Merge pull request #49 from punkhop/fix/replace-from-bin-keep-source-in
engine: clip.replaceFromBin can keep the clip's source In
2026-10-06 11:37:05 -04:00
Brandon Thomas 950879ef10
Merge pull request #59 from punkhop/fix/inspect-reports-reverse
engine: sequence.inspect reports a reversed clip
2026-10-06 11:36:58 -04:00
Brandon Thomas 7377def476
Merge pull request #48 from punkhop/fix/sequence-inspect-readback
engine: sequence.inspect reports clip ends, gain and marker comments
2026-10-06 11:36:53 -04:00
Brandon Thomas 5bc07026c7
Merge pull request #43 from punkhop/fix/import-auto-points
engine: a project saved after an interchange import opens again
2026-10-06 11:36:46 -04:00