Commit Graph
656 Commits
Author SHA1 Message Date
Jonathan CardosoandBrandon Thomas afdb8019c1 media: say which colour values no tag gave (#4086) (#4089)
With no colour tags, FilmCraft decodes with BT.709 transfer and
primaries and the matrix by frame size, and probe and media.colorInfo
showed those values with nothing saying they were defaults, so an
untagged file looked the same as one tagged BT.709.

VideoStreamInfo gets color_assumed (optional, left out when unknown):
which of the matrix, transfer and primaries no tag in the file gave.
MP4/MOV and Matroska take it from the same sources as the colour, APV
from its colour description, and AVI, MXF and Y4M mark all three.
probe prints it as video.color_assumed and media.colorInfo as assumed,
next to the unchanged metadata.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-11-03 00:04:13 -05:00
Jonathan Cardoso f4f3dd5eff engine: timeline.move reads a time object and names an entry it cannot use (#4113) (#4116)
A moves[] entry gave its time only as integer ticks. Any other form, or
a missing clip or track, dropped the entry: alone it failed with "need
`moves`", next to other entries only those moved and the call said ok.
`time` now goes through tick_or_time_p like timeline.place's sourceIn,
and an entry without a usable clip, track or time is refused by its
index before anything moves.
2026-11-03 00:03:35 -05:00
Jonathan Cardoso 96d8e22c2d Image-sequence export reports the stills it wrote, not the path it was given (#4018)
* fix(export): an image-sequence export reports the stills it wrote

An export to `a.png` as an image sequence writes `a000.png`, `a001.png` and so on, but the
job's result, `file.exportMedia`'s `path` and the CLI's "exported" line all named `a.png`,
which does not exist.

The report now names the first still, the name `file.import` and `probe --image-sequence`
take for a sequence. `file.exportMedia` and `export.quick` name it as `path` up front, from
the frame count `export.resolve` uses, and add `lastPath`. The CLI prints both. A single
file keeps its path.

Fixes #4009

* fix(automation): a cancelled image-sequence export is cleaned up by its stills' name

Since `file.exportMedia` names an image sequence's first still as `path`, the MCP cancel
clean-up took `a000` as the stem: it left `a001.png` and every later still, and the `a.srt`
sidecar, behind. The result now also carries `basePath`, the name the stills are numbered
from, and the clean-up goes by it.

* fix(automation): an image-sequence cancel clean-up keeps the base name and finds .jpeg stills

An image-sequence export numbers every still, a single frame included, so a file under its base
name (`a.png`) is never its own: cancelling one deleted a user's `a.png` if it was saved during
the export. The stills of a `.jpeg` sequence were left behind instead, since the extension was
read as a format name, and `jpeg` names Motion-JPEG there; `file.exportMedia` keeps `.jpeg`
for a JPEG sequence.

* fix(automation): a cancelled image sequence removes only the stills it numbered

The clean-up matched any `<stem><3+ digits>.<ext>` written during the export, so cancelling an
export to `a.jpeg` could delete `a1000.jpeg`, the first still of an export to `a1.jpeg` in the
same folder. It now takes the digits and the last index from the result's `lastPath` and removes
only those names: `a000.jpeg` to `a120.jpeg` for a 121-frame export.
2026-11-03 00:03:30 -05:00
scks1andClaude Opus 5.5 8e81d41567 Name Apple Intermediate Codec and show why a clip is unreadable (part of #3646) (#4010)
* media: name Apple Intermediate Codec and say why a clip is unreadable

Part of #3646. A MOV in Apple Intermediate Codec (fourcc icod, the
editing codec of iMovie and Final Cut) imported with its codec named
"unknown", and its frames failed with "no decoder for unknown video".
Only the log showed that error: the Project panel's badge said
"Unreadable" and nothing more.

- codecs: codec_label names icod "Apple Intermediate Codec". The
  "no decoder" errors of make_video_decoder and software_video_decoder
  use that label for sample entries the parser keeps as Unknown, so
  the error reads "no decoder for Apple Intermediate Codec video".
  Other codecs keep their short names in that error.
- ui-egui: an Unreadable badge shows on hover the error the media pool
  recorded, on cards (Icon and Freeform view) and in List view, which
  now registers its badge as project.item.<id>.offline as cards do.
  This covers every cause the pool records, such as "H.264: field
  pictures", not only this codec.
- docs: an Apple Intermediate Codec row in codec-parity.md, and the
  hover in project-files.md.

FilmCraft still has no AIC decoder. Apple publishes no specification
for it, so a clean-room decoder (AGENTS.md section 2) needs a
maintainer ruling, and #3646 stays open for that.

Tests: apple_intermediate_codec_is_named_though_nothing_decodes_it in
filmcraft-codecs (the label and all three errors), and
unreadable_badge_says_why_on_hover in the ui-egui it suite (both views).

Developed with an AI assistant (Árbol, running Muse).

* ui: keep the List view's badges beside a long name (#3646)

In List view, a name that left less than 40 px of its column hid the
item's offline icon and proxy chip, and with them the Unreadable
badge's automation id and the reason it shows on hover. The badges now
keep their room at the end of the Name column, and a long name is cut
short before them. Only a column too narrow for the badges leaves them
out. Rows that showed their badges before, and rows without badges,
draw as they did.

unreadable_badge_says_why_on_hover imports a file whose name is wider
than the Name column, so its List view pass covers this case. Found by
CodeRabbit in its review of the pull request.

Developed with an AI assistant (Árbol, running Muse).

* codecs, ui: doc comments for codec_label and media_badge (#3646)

Both functions gained a role with the Apple Intermediate Codec change:
codec_label also names the codec in the no-decoder errors, and
media_badge records why an Unreadable file cannot be read. Their doc
comments say so.

Developed with an AI assistant (Árbol, running Muse).

* ui: end a List-view name cut short with "…" and show it in full on hover (#3646)

Keeping the badges' room at the end of the Name column can cut short a name
that used to fit, and the cut left no sign of it. The List view now draws the
name with the cards' elided_name, so a cut name ends in "…", and hovering it
shows the whole name, as the cards already do. Names that fit draw as before.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 00:02:55 -05:00
Jonathan CardosoandBrandon Thomas 8ce79afd23 captions: SCC and MCC export name the characters they drop or replace (#4023) (#4036)
CEA-608 has no code for some characters (the ellipsis, CJK) and the SCC
and MCC writers dropped them, or sent a close basic-set one (’ as '),
without saying so. The CEA-708 service in MCC sent ? the same way, for
instance for an em dash.

charset_warnings lists each such character once, with how often and
the first caption that has it, using the writers' own tables, and
captions.export returns the list as warnings. The list is capped at
20 characters per stream plus one summary line.

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-11-03 00:02:10 -05:00
wweimao f3f1afd160 M10.7: fix per-character Stroke and Stroke 2 controls (#3938) 2026-11-03 00:01:43 -05:00
Jonathan Cardoso a4bc8edd50 captions: TTML export writes the track language, import keeps it (#4025) (#4038)
TTML and DFXP exports always wrote xml:lang="en", whatever the caption
track's language. The document now carries the language: export takes
the track's, TTML import reads xml:lang (a language tag of at most 35
characters, else a warning), and captions.import takes an optional
language that wins over both.
2026-11-03 00:01:18 -05:00
Jonathan Cardoso baddebdc30 interchange: EDL media relinked with Align Timecode lands on the file's own time (#3990) (#3996)
* interchange: EDL media relinked with Align Timecode lands on the file's own time (#3990)

An EDL's source times are timecodes, but its media items had no start
timecode, so Align Timecode had nothing to align from and a clip relinked
after an offline import kept its timecode as media time (the file's last
frame). EDL media now starts at timecode 0, and the relink shift reads each
timecode at its own file's rate, as the import-time rebase does.

* engine: EDL relink test checks the placeholder is listed missing, not its offline flag (#3990)

#4000 stops flagging EDL clips named only by clip name offline, so the setup asks media.findMissing instead, which lists the item either way.

* engine: the EDL relink test also runs with 25 fps media (#3990)

make_movie_at takes the frame rate. Under a 24 fps EDL a 25 fps file's timecode must be read at 25 fps: with the old shift (old_rate.tick_of(b - a)) the clip lands at -149 s instead of 1 s.
2026-11-03 00:00:45 -05:00
Jonathan Cardoso 5c73ee4af6 cli: --save runs on one project take turns, so no edit is lost (#3926)
* cli: --save runs on one project take turns, so no edit is lost (#3924)

A run reads the project, edits it and writes the whole file back, so two
at once silently dropped the edits of whichever saved first. A run that
saves over the file it opened now holds an OS lock on `.<name>.lock` next
to the project from before its read until it exits. The next run says so
on stderr, waits, then edits what the first one saved.

The OS drops the lock however the process ends, so a crash leaves nothing
stale. If the lock can't be taken the run warns and saves as it did before.
The desktop app and `mcp` sessions don't take this lock.

* cli: the save lock goes by the path being saved over (#3924)

A save through a symlink replaces the link with a plain file. Resolving
the path therefore gave the runs before and after that save different
locks, and a run still waiting on the old lock could overwrite a later
run's save. The lock now uses the path as written, so replacing the link
can't change which lock a run takes.
2026-11-02 00:38:13 -05:00
JohnandClaude Opus 5.5 e6eec33a42 G13: TikTok, Instagram Reels and YouTube Shorts export presets (#3721)
* G13: TikTok, Instagram Reels and YouTube Shorts export presets

Three Web & Social presets for short-form vertical video: H.264
1080×1920 (9:16), scaled to fill, at the sequence's frame rate, AAC
48 kHz stereo, with Loudness Normalization on at −14 LUFS and a −1 dBTP
ceiling, the level the platforms play at; 10, 8 and 12 Mbps VBR. They
share a short_form() helper; Social Vertical is unchanged.

short_form_presets_are_vertical_and_loudness_normalized checks size,
rate, scaling, bitrate, audio and loudness. Real exports measured
−14.1 LUFS from both a −19 and a −8.4 LUFS source.

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

* G13: the short-form presets test checks each maximum bitrate

CodeRabbit on #3721: assert max_bitrate_kbps (12, 10 and 16 Mbps) and
the VBR 1 pass mode next to the target bitrate, so a change to the
ceiling alone fails the test.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 15:15:40 -05:00
.CooCoo af28e9acee History: each step shows the icon of the tool or command that made it (#3776)
* History: each step shows the icon of the tool or command that made it

Each undo and redo step now keeps the id of the command that made it,
through undo, redo, merged and grouped steps and the history limit.
The History panel paints that command's icon before each label: a
timeline tool's icon for the commands the tool runs, FilmCraft's own
icon for other commands that have one, and a plain square for the rest
and for edits made outside a command. Undone steps draw their icon dimmed
like their labels. The Open row has no icon. history.list is unchanged.

* History: ripple trims show the Ripple tool's icon

A ripple trim's undo step records its own id, timeline.trim.ripple,
whether it comes from a Ripple tool drag, a ripple edit point in trim
mode or a dynamic ripple trim, and the History panel shows the Ripple
tool's icon for it. Trim mode nudges, Extend Edit to Playhead and dynamic
trims record the edit point's kind (timeline.trim, timeline.roll or the
ripple id) instead of the outer trim command, so a regular trim shows the
Selection tool's icon and a roll shows the Rolling tool's icon. Trim
Previous and Next Edit to Playhead show the Selection tool's icon.

* History: icon targets on a part-scrolled row match the drawn icon

The History panel registered each row's icon target from the row rect after clipping it to the scroll area, so on a row partly scrolled out the target moved off the drawn icon, and an icon scrolled out entirely was still registered. The target is now the drawn icon's rect clipped to the scroll area, registered only while part of it shows.

* History: Apply Default Transitions to Selection shows the plain square

The trim. family gave trim.applyDefaultTransition the Rolling tool's icon, although the command adds transitions at the selected edit points and makes no rolling edit. It now shows the plain square, as the sequence transition commands do.
2026-11-01 15:15:33 -05:00
MarekSpodBiedry 3f89e7fdbb Serialize bridge render_frame calls so parallel requests get their own frame (#3837) (#3872) 2026-11-01 15:15:03 -05:00
Patrik LermonandClaude Opus 5.5 04476bf9cb Export: the time left counts down between batches; the status bar shows it once a second, in place (#3816)
* Export: the time left counts down between batches; the status bar shows it once a second, in place

An export finishes its frames in batches of up to 16. The estimate measured the speed to the
latest reading, so between batches the speed sagged and the time left grew, then fell when the
next batch landed: about ±13 % on a heavy 4K60 export, enough to flip between 1:04:50 and 56:11.
It now measures the speed between batch arrivals and counts down from the last one; a batch three
intervals late falls back to the speed up to now, so a stall still makes the estimate grow.

The status bar redrew its text every frame, right-aligned against the bar, in Inter's proportional
digits, so "Exporting… 46%" moved sideways with every change of the time left. The text now
changes at most once a second, its digits sit in cells of equal width, and its room only grows
while the job runs (from the start it fits 100 % and a time under an hour).

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

* Export: no "0 s left" while the last batch is late; the status text has room for any time left from the start

The countdown between batches reached zero when the last batch took longer than the speed said,
and showed "0 s left" until it was three intervals late; it now gives way to the speed up to now as
soon as it runs out. The status bar's room was for a time under an hour, so an export's first
estimate over an hour still moved the text once; it is now for 99:59:59 from the start.

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

* Export: the queue's and the Progress panel's job text change once a second, with digits of one width

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

* ui-egui: tabular_label is read by screen readers as a label

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 15:14:46 -05:00
5ed4952d43 Add shared custom colors and complete marker editing (#1435)
* M3: Add shared custom colors and complete marker editing

* #1435: refine native colors and range endpoint flags

Use the macOS Colors panel for custom label colors and reuse the established egui picker on other hosts. Preserve draft confirmation, exact sRGB values, native text shortcuts and project ownership. Compact the swatches and center the add control, split range glyphs across their endpoints, localize the new controls, protect newer marker edits from stale dialogs, and cover the behavior with rendered UI and hit-test regressions.

Co-authored-by: Codex <noreply@openai.com>

* #1435: preserve imported palettes and marker double-click ownership

Union saved OTIO palettes across timelines with deduplication, bounded capacity,
first-name preservation and explicit overflow warnings. Keep null authors
consistent with omitted fields, and consume marker double-clicks before the
work-area gesture so opening the editor does not alter project history.

Correct the CSV URL column and schema documentation. Add six regressions for
palette retention/capacity, author handling, and physical overlapping gestures.

Validation: full cargo xtask ci (3666 passed, 45 skipped), 42 rendered UI tests,
and strict workspace/all-target Clippy on Rust 1.99.1.

Co-authored-by: Codex <noreply@openai.com>

* #1435: retain OTIO swatch names and generator labels

Ignore orphan name entries when retaining saved palette names so input ordering
does not hide valid names after the first 64 entries. Keep names bounded by the
retained palette and preserve existing valid names.

Include generator preset labels alongside custom label colors in OTIO metadata.
Add regressions for orphan-prefixed name maps and three generator kinds with
preset/custom colors through actual export/import round trips.

Validation: both regressions failed before fixes; all 72 interchange tests and
full cargo xtask ci pass (3668 tests, 45 skipped), plus strict workspace/all-target
Clippy on Rust 1.99.1.

Co-authored-by: Codex <noreply@openai.com>

* #1435: preserve distinct OTIO generator item identity

Use exported FilmCraft item IDs for generator media identity so identical
content can retain distinct source names, labels and custom colors. Repeated
references to one source item still share a single imported media entry.

Preserve content-based fallback for missing or invalid item IDs. Cover black
video, bars and tone, and color mattes with distinct items/shared references,
plus legacy and malformed identity metadata.

Validation: distinct-generator regression failed before fix; legacy compatibility
passed. All 74 interchange tests and final full cargo xtask ci pass (3670 tests,
45 skipped); strict workspace/all-target Clippy also passes on Rust 1.99.1.

Co-authored-by: Codex <noreply@openai.com>

* #1435: align Edit Marker layout and add safe marker navigation

Give the editor a wide aligned form, larger Notes area, side action column,
and grouped palette with vertical marker types. Expand the Web Link field
with the form and keep actions accessible in small windows.

Previous/Next saves valid edits as one Undo step and stays with the original
sequence/source owner, including coincident markers. Invalid drafts stay open;
unchanged navigation and Done add no history. Keep native/shared color pickers,
Author, Notes, URL validation and immediate marker creation.

Validation: all 45 rendered sequence/marker UI tests pass, including five new
navigation/owner/validation/layout regressions. Native macOS layout, picker
Cancel and exact single-step Undo restoration verified. Full standard cargo
xtask ci passes 3675 tests (45 skipped), doctests and all remaining gates;
strict Rust 1.99.1 workspace/all-target Clippy also passes.

Co-authored-by: Codex <noreply@openai.com>

* #1435: refine Edit Marker proportions and action alignment

Narrow the dialog to 680 logical pixels and keep the core order Name,
Time/Duration, Notes, Color and marker type. Place Author after the type-specific
options as secondary metadata. Preserve our palette, custom picker and range controls.

Use consistently sized, centered rounded action buttons with a primary Done action.
Shorten Delete Marker to Delete and remove the navigation helper and unused translations.
Keep the existing navigation save/validation/Undo semantics and automation IDs.

Validation: all 45 rendered marker/sequence UI tests pass, including small-window
action accessibility. Actual macOS layout and no-op Previous/Next/Cancel verified.
Full standard cargo xtask ci passes 3675 tests (45 skipped), doctests, formatting,
Clippy, translations, layers, assets and 49 WASM crates. Strict Rust 1.99.1
workspace/all-target Clippy passes separately.

Co-authored-by: Codex <noreply@openai.com>

* #1435: tighten marker layout and validate text editing

Use a narrower aligned form with Author below Name, bounded scrolling Notes,
left-aligned colors, centered actions and an inline Web Link URL/open icon.
Remove the legacy Flash Cue choice while preserving imported marker types.

Constrain timecode typing/paste to complete numeric colon-separated fields,
validate drop-frame labels and frame bounds, and disable Done for invalid timing.
Preserve high-frame-rate timecodes and point-marker semantics when Duration is
unchecked. Route native/menu clipboard and text Undo commands to focused fields;
explicit engine commands retain project Undo and selection semantics.

Validation: standard cargo xtask ci passes 3679 tests (45 standard skips),
doctests, fmt, strict workspace/all-target Clippy, i18n, layers, 69 assets and
49 WASM crates. Also passed 48 rendered marker/sequence tests and strict Rust
1.99.1 Clippy. Actual macOS clipboard, bounded Notes, point save and exact Undo
were checked. Windows/Linux desktop interaction remains pending.

Co-authored-by: Codex <noreply@openai.com>

* M0: Wait for frame-worker recovery before asserting

Do not treat a nonempty request queue as proof of worker death in the
panic-recovery regression. Keep waiting for all injected faults and enough
post-fault completions, then drain the queue without adding more seeks.
Retain the exact fault-count, successful-recovery and empty-queue assertions
and bound the wait with a two-minute deadline.

The inherited test failed twice in independent fork CI. It did not reproduce
locally: baseline passed 20 normal and 10 delayed-report runs; the repair
passed 50 normal and 10 delayed-report runs. No product or marker UI changes.

Validation: standard cargo xtask ci passed all 4485 tests (52 standard skips),
doctests, formatting, strict workspace/all-target Clippy, i18n, layers,
69 assets and 49 WASM crates.

Assisted-by: OpenAI Codex

---------

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <codex@openai.com>
2026-11-01 03:04:14 +01:00
aiongg 562f550221 Merge main into backlog-r1 2026-10-31 05:27:25 +00:00
aiongg 3cce1d1349 docs: tidy wording 2026-10-31 04:25:39 +00:00
aiongg 239f7987de docs: fix punctuation 2026-10-31 04:17:42 +00:00
aiongg 5c18340e3f docs: tidy agent, contributor and asset docs 2026-10-31 04:17:32 +00:00
aiongg 9f7a9d6342 Merge integration track timeline 2026-10-31 03:39:23 +00:00
aiongg a9d15b9542 Merge integration track ui2 2026-10-31 03:39:22 +00:00
aiongg 01608757f5 Merge integration track fx 2026-10-31 03:39:22 +00:00
aiongg d6b1265dc4 Merge integration track text 2026-10-31 03:38:55 +00:00
aiongg 8595147b71 Merge integration track i18n 2026-10-31 02:17:34 +00:00
aiongg bf0386bf76 Merge integration track sys 2026-10-31 02:17:26 +00:00
aiongg 69ed33ae57 Merge integration track io 2026-10-31 02:17:17 +00:00
aiongg bf1a400b27 Merge integration track export 2026-10-31 02:17:03 +00:00
aiongg b583037822 Merge integration track audio 2026-10-31 02:17:03 +00:00
aiongg c2ac002f8f Merge PR #3684: Render Effects In to Out renders only red segments, like the reference app (#1220) 2026-10-31 02:16:02 +00:00
aiongg 09f99fc97b Integration: #3516 numpad section states the limitation and the 0 binding only 2026-10-31 02:15:27 +00:00
aiongg a589de7b06 Integration: #3093 ADR links point at the platform backend files 2026-10-31 02:15:27 +00:00
aiongg 810320933d Merge PR #2612: Clip Mismatch Warning: a first clip that doesn't match an empty sequence asks
# Conflicts:
#	crates/engine/src/commands.rs
#	crates/engine/src/settings.rs
#	crates/ui-egui/src/i18n/es.tsv
#	crates/ui-egui/src/i18n/ja.tsv
#	crates/ui-egui/src/i18n/zh-cn.tsv
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/panels/timeline.rs
2026-10-31 02:15:20 +00:00
aiongg e930e085a7 Merge PR #3718: docs: transcripts: word bounds are only moved across pauses 2026-10-31 02:15:16 +00:00
aiongg ba5d3ab6ca Merge PR #3516: docs(#2645): document numpad key limitation and workarounds in keyboard.md 2026-10-31 02:15:16 +00:00
aiongg 1629892f63 Merge PR #3093: docs(platform): update FFI architecture decision to match implementation (#2814) 2026-10-31 02:15:16 +00:00
aiongg abeac167cc Merge PR #1423: #1421: roadmap.md and gaps.md G14: mark shipped codecs and languages as done 2026-10-31 02:15:16 +00:00
aiongg e2e0c96f7b Merge PR #1419: #1418: parity docs: correct entries outdated by merged work 2026-10-31 02:15:03 +00:00
aiongg 6ea11662a1 Merge PR #1412: #1411: docs/gaps.md: remove entries for features that already shipped 2026-10-31 02:14:54 +00:00
aiongg 8f16aea983 Merge PR #3714: bs: Add Bosnian (bs) to the interface languages 2026-10-31 02:14:54 +00:00
aiongg 2a501fa39e Merge PR #2116: feat(media): import PSD files as their flattened composite (Merge All Layers)
# Conflicts:
#	docs/file-format-parity.md
#	docs/gaps.md
2026-10-31 02:14:38 +00:00
aiongg 6f4f383ca4 Merge PR #2705: #2489: an imported shortcut set is always listed; .kys files explain why they can't be read 2026-10-31 02:14:06 +00:00
aiongg 59695f22ae Merge PR #2344: i18n: Turkish (tr) interface catalog (#1377) 2026-10-31 02:13:56 +00:00
aiongg e5e3c2b881 Merge PR #2984: Recovery: retain durable journals and contain autosave worker failures 2026-10-31 02:13:48 +00:00
aiongg c11c0e7e25 Merge PR #1118: fix: シーケンス配置時の自動文字起こしを実行 #903 2026-10-31 02:13:33 +00:00
aiongg f319ff9af3 Merge PR #3389: #3357: caption track font style 2026-10-31 02:13:13 +00:00
aiongg 7e608027ea Merge PR #2288: i18n: Russian covers the whole interface 2026-10-31 02:13:09 +00:00
aiongg a3f66a1e47 Merge PR #2660: #2419: Bokeh Blur runs on the GPU 2026-10-31 02:12:50 +00:00
aiongg 5b83f337ab Merge PR #1930: i18n: Swedish (sv) interface translation 2026-10-31 02:12:36 +00:00
aiongg 5054344c26 Merge PR #3690: Graphics: document what Responsive Design – Time remaps 2026-10-31 02:12:31 +00:00
aiongg d57d6afd97 Merge PR #3407: timeline: Track Select Forward/Backward selects and moves the captions with the clips (#3388) 2026-10-31 02:12:28 +00:00
aiongg da9642af10 Merge PR #3723: Export: background jobs read their own copy of each file, so playback keeps its decoder
# Conflicts:
#	crates/engine/src/proxies.rs
2026-10-31 02:12:09 +00:00