Commit Graph

3790 Commits (322e4bcca37ef16e5ec823597b89f603dd2e7d6a)
 

Author SHA1 Message Date
Claude 322e4bcca3 Upgrade Yarn to 4.18.0
Two config keys come with this. `enableScripts` flipped its default to
false in the 4.13 line as supply-chain hardening, so it has to be set
explicitly here — esbuild, @swc/core and @parcel/watcher all need their
install scripts, as does the `electron-builder install-app-deps`
postinstall. `yarn set version` also wrote `approvedGitRepositories: **`,
a blanket opt-out of the new git-dependency approval prompt; that is
dropped again, since the lockfile has no git dependencies and leaving the
guard armed costs nothing until one is added.

The lockfile moves to metadata version 10 and one builtin patch hash for
`resolve` changes; no package resolutions move.

Incidentally this makes `--no-time-gate` available on `yarn add`/`yarn up`,
which 4.11 did not have — the npmMinimalAgeGate quarantine previously had
to be worked around with YARN_NPM_MINIMAL_AGE_GATE=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BtCagWFcr4MLHQD4zkPVf5
2 weeks ago
Claude e15a495f68 Upgrade electron-builder to 26.16.1
26.16.1 carries the fix for electron-userland/electron-builder#10167:
`security set-key-partition-list` was passed the .p12 import password
(CSC_KEY_PASSWORD) instead of the temporary keychain's own password, so
macOS signing could fail in CI whenever those two differ. The fix landed
after 26.16.0 was cut, so 26.16.1 is the first release that has it.

The version is spelled out explicitly because the `latest` dist-tag still
points at 26.15.3 — 26.16.x ships under the `v26` tag.

Verified unchanged in 26.16.1, since both are load-bearing here:
- the legacy snap template table (base/plugs pairing behind #3002)
- the appimage 1.0.3 toolset checksums (libfuse2-free runtime, #3022)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BtCagWFcr4MLHQD4zkPVf5
2 weeks ago
dependabot[bot] 5c4648fd8a Bump @xmldom/xmldom from 0.8.13 to 0.8.15
Bumps [@xmldom/xmldom](https://github.com/xmldom/xmldom) from 0.8.13 to 0.8.15.
- [Release notes](https://github.com/xmldom/xmldom/releases)
- [Changelog](https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/xmldom/xmldom/compare/0.8.13...0.8.15)

---
updated-dependencies:
- dependency-name: "@xmldom/xmldom"
  dependency-version: 0.8.15
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2 weeks ago
dependabot[bot] e5461d5141 Bump qs from 6.15.3 to 6.16.0
Bumps [qs](https://github.com/ljharb/qs) from 6.15.3 to 6.16.0.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.15.3...v6.16.0)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.16.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2 weeks ago
dependabot[bot] 1d20184b73 Bump fast-uri from 3.1.5 to 3.1.6
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.5 to 3.1.6.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.5...v3.1.6)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2 weeks ago
dependabot[bot] 77778499d3 Bump browserslist from 4.28.1 to 4.28.9
Bumps [browserslist](https://github.com/browserslist/browserslist) from 4.28.1 to 4.28.9.
- [Release notes](https://github.com/browserslist/browserslist/releases)
- [Changelog](https://github.com/browserslist/browserslist/blob/main/CHANGELOG.md)
- [Commits](https://github.com/browserslist/browserslist/compare/4.28.1...4.28.9)

---
updated-dependencies:
- dependency-name: browserslist
  dependency-version: 4.28.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2 weeks ago
Claude 5af02818fb Extract the audio stream shape into shared types
The { index, channels, channelLayout } shape was repeated inline in the
preview's main and renderer signatures. Move it to src/common/types.ts as
AudioStreamInfo, and let getFixChannelLayoutFilter take the narrower
AudioChannelInfo it actually needs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YCf7BBiPqNLUjVoN7rTCF6
3 weeks ago
Claude 541877ebfb Also fix custom channel layouts that aren't a standard speaker set
The previous check only looked for unknown/unused channels (UNSD/UNK), but
swresample's sane_layout() rejects any custom layout that doesn't form a
standard speaker set. So e.g. a surround stem pair stored as
"2 channels (BL+BR)", or "4 channels (FL+FR+FC+BL)", failed the same way
even though every channel is properly labelled.

ffprobe reports a layout as "N channels (A+B+...)" exactly when ffmpeg
could not express it as a native layout; anything that does form a standard
set is reported under its native name ("stereo", "quad", "5.1") and always
works. So key off that instead.

Verified against a .mov roundtrip of every layout: all native layouts are
left untouched, and BL+BR, FL+BL, SL+SR, FL+FR+SL, TFL+TFR and FL+FR+FC+BL
all go from failing to working.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YCf7BBiPqNLUjVoN7rTCF6
3 weeks ago
Claude 273ec3b1ce Exclude the tsc build output from vitest instead of from the build
Excluding src/common tests from tsconfig.common.json kept vitest from
running the compiled copies twice, but it also meant those test files were
no longer type checked at all by `tsc --build` (eslint only catches lint
issues, not type errors).

Exclude common-ts-dist from test discovery instead, so the tests are both
type checked and run exactly once.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YCf7BBiPqNLUjVoN7rTCF6
3 weeks ago
Claude ca6813f9a4 Fix playback and conversion of audio with unknown channel layout
DV/DVCPRO .mov files (e.g. captured by Final Cut / iMovie) carry a 'chan'
atom that labels every audio channel as "unused", so ffmpeg describes the
stream as "4 channels (UNSD+UNSD+UNSD+UNSD)".

swresample only accepts native or fully specified custom layouts, so as
soon as anything needs to resample or downmix such a stream it fails with:

  [SWR] Input channel layout '4 channels (UNSD+UNSD+UNSD+UNSD)' is not supported
  [af#0:1] Error reinitializing filters!
  Nothing was written into output file

This broke both preview playback and "convert to supported format" for
these files.

Prepend a `channelmap` filter that re-labels the channels, which turns the
layout into a plain "N channels" (unspecified) layout that swresample does
support. It only re-labels, the samples are untouched, and the stream then
behaves exactly as if it had carried no channel layout information at all.

Only applied to streams that actually have an unsupported layout, so files
with a proper layout keep their correct downmix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YCf7BBiPqNLUjVoN7rTCF6
3 weeks ago
Claude bd9ef59049
Fix wrong duration when cutting a file with cover art
An attached_pic packet has no position on the timeline, so the demuxer
emits it at pts 0. When seeking before the input (`-ss` before `-i`),
ffmpeg applies the seek offset to it anyway, dragging it to -(cut from),
and it reaches the muxer first. `-avoid_negative_ts make_zero` then
derives its file-wide correction from that packet and shifts every other
stream back by +(cut from), undoing the rebase to zero that the audio and
video already got.

The mov muxer records that as an empty edit, so each exported segment
declares the segment's end time in the source as its duration instead of
its length - e.g. splitting a 3.5h m4a into 7 parts yields parts that
report 30, 60, 90, 120... minutes. ffprobe subtracts the empty edit and
looks correct, but players reading mvhd (such as VLC) show the inflated
value. The media itself is intact, only the declared duration is wrong.

Downgrade `make_zero`/`make_non_negative` to `auto` when a cover art
stream is being copied. `auto` doesn't use the attached pic as its
reference, so the output gets the right duration and keeps the cover art.

Reproduced against the bundled ffmpeg (n8.0-23-gd1f31a829d-20251022) on
an AAC m4a with an mjpeg attached_pic stream. Not format specific - mp4
behaves identically. A file without a cover art stream is unaffected, and
for a file that also has a real video track `auto` additionally avoids the
keyframe-backtrack overshoot that `make_zero` produces.

Closes #3009

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W5WHGj7byjqxDEfSxRyuJD
3 weeks ago
Mikael Finstad e1f4348637
enable appimage artifact 1 month ago
Claude 9820b32856 Detect missing source file when extracting frames and tracks too
Follow-up to #2797. `cutMultiple` already calls `assertFileExists` before
spawning ffmpeg, so a source file that was moved or deleted after being
opened produces a clear "Source file no longer exists or is not
accessible" message instead of a raw ExecaError plus the generic "Unable
to export this file" checklist (change output format, try keyframe cut,
change working directory...), none of which can help.

The other export paths had no such guard, so they still fail with a bare
ffmpeg "No such file or directory". Add the same check to:

- `captureFramesRange` (export segment frames as images)
- `captureFrameFromFfmpeg` (capture snapshot)
- `extractStreams` (extract all tracks / extract single track)

`extractAllStreams`/`extractSingleStream` swallowed the error message and
showed a generic toast, so let UserFacingError through there as well,
matching how the export and merge flows already handle it.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqUn6Bh7hWqPqWejqR8p7u
1 month ago
Claude 20c6b9ea62 Only pass muxer private options to the muxer they belong to
`-movflags` (mov/mp4 family) and `-default_mode` (matroska family) were
added to every ffmpeg command regardless of the output format, so e.g.
exporting to matroska produced:

    ... -movflags "+faststart" -default_mode infer_no_subs -f matroska ...

ffmpeg tolerates private options belonging to a different muxer, so this
was harmless, but it adds noise to the command line we log, show under
"Last commands" and include in problem reports, which makes
troubleshooting harder than it needs to be.

Gate each set of flags on the output format. The format lists are derived
from ffmpeg's movenc.c and matroskaenc.c rather than the existing
util/streams.ts `isMov`/`isMatroska` helpers, because those are narrower
UI oriented lists that omit movenc formats we can output (3gp, 3g2, f4v,
psp) - reusing them would have silently dropped +faststart for those.

When the output format is unknown, ffmpeg infers the muxer from the file
extension, so the flags are kept as before.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqUn6Bh7hWqPqWejqR8p7u
1 month ago
Claude 1c3f75be36 Revert snap base to electron-builder's default
Setting `base: core22` left the snap declaring a core22 base while still
plugging the core18-era gnome-3-28-1804 content snap for its GNOME platform.
Mesa's DRI drivers in that platform cannot resolve their dependencies against
core22, so every GL/EGL path fails including the swrast software fallback, the
GPU process exits, and the main process segfaults before a window appears.

The base override never moved the platform. electron-builder's snap template
pairs `base: core20` with a hardcoded `gnome-3-28-1804` plug, and its legacy
snap path rewrites only the `base` field, leaving the plugs block untouched.
The two halves have to match, so the fix is to stop overriding the base and
let the template stay self-consistent.

Dropping the key rather than pinning core20 explicitly means the snap keeps
following whatever electron-builder's template ships.

This restores the pre-3.68 behaviour, which reopens #2614 for very new GPUs
whose hardware needs a newer Mesa than the platform provides. That trade is
deliberate: #2614 affected some GPUs, this affects every user.

Fixes #3002

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KboMatXCuTgjD6KfC1ik12
1 month ago
Claude 631572910e Build AppImage with the static (libfuse2-free) runtime
electron-builder's default AppImage toolset ("0.0.0") uses the legacy
AppImageKit runtime, which dlopens libfuse.so.2 at startup and fails on
distros that no longer ship libfuse2.

Opting into toolset appimage 1.0.3 uses AppImage/type2-runtime 20251108,
a static-pie runtime with libfuse/squashfuse linked in, so the AppImage
runs without any FUSE packages installed.

Fixes #3022

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmsuZZPx6pFKSjN6UZmGcJ
1 month ago
dependabot[bot] 08bcf877d9 Bump js-yaml from 4.3.0 to 4.3.1
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.3.0 to 4.3.1.
- [Changelog](https://github.com/nodeca/js-yaml/blob/4.3.1/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/4.3.0...4.3.1)

---
updated-dependencies:
- dependency-name: js-yaml
  dependency-version: 4.3.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
1 month ago
Mikael Finstad 3b9a59c288
Revise Linux installation details in README
remove flathub because not maintained by me
2 months ago
dependabot[bot] 2085739660 Bump undici from 6.27.0 to 6.28.0
Bumps [undici](https://github.com/nodejs/undici) from 6.27.0 to 6.28.0.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v6.27.0...v6.28.0)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 6.28.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2 months ago
dependabot[bot] 2271c18fff Bump fast-uri from 3.1.4 to 3.1.5
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/fastify/fast-uri/releases)
- [Commits](https://github.com/fastify/fast-uri/compare/v3.1.4...v3.1.5)

---
updated-dependencies:
- dependency-name: fast-uri
  dependency-version: 3.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2 months ago
dependabot[bot] 8279200c33 Bump ip-address from 10.2.0 to 10.4.0
Bumps [ip-address](https://github.com/beaugunderson/ip-address) from 10.2.0 to 10.4.0.
- [Release notes](https://github.com/beaugunderson/ip-address/releases)
- [Commits](https://github.com/beaugunderson/ip-address/compare/v10.2.0...v10.4.0)

---
updated-dependencies:
- dependency-name: ip-address
  dependency-version: 10.4.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2 months ago
Mikael Finstad d14422c91b
Update LosslessCut link in README 2 months ago
Claude d7e2ecd042 fail fast in startup check when ffmpeg executable is missing
On Windows, when the ffmpeg/ffprobe executable does not exist (e.g. a
custom FFmpeg directory pointing to a location without ffmpeg.exe),
cross-spawn (used by execa) falls back to running the command through
cmd.exe, which fails with exit code 1 and a confusing
"'...' is not recognized as an internal or external command" error
instead of ENOENT. This bypassed the "FFmpeg executable not found"
dialog and instead triggered the error report dialog.

Now check that the executables exist as part of the startup check
(which also re-runs whenever the custom FFmpeg directory setting
changes), so a missing executable yields a proper ENOENT. Also mention
the custom FFmpeg directory setting in the error dialog when one is
configured.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PE6aFnysh85Ryndeu6zXYG
2 months ago
Mikael Finstad 260802b810
update contributing 2 months ago
Mikael Finstad 260802195b
add doc about hardening 2 months ago
Mikael Finstad 2608023489
harden http server 2 months ago
Claude b0eb2b980e Use runner.arch instead of runner image names in Windows conditions
Gating steps on the exact matrix image name (windows-latest,
windows-11-arm) breaks silently whenever the image in the matrix is
renamed, as happened with the windows-2022 switch. runner.os and
runner.arch describe what we actually care about and are independent
of the image label.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PWvFPqUcXUzsYf3DY7RziJ
2 months ago
Claude 7da03ebdad Fix skipped Windows x64 build steps after windows-2022 matrix change
The matrix was switched from windows-latest to windows-2022, but the
Windows x64 ffmpeg download, electron-builder, e2e and screenshot upload
steps were still gated on matrix.os == 'windows-latest', so they never
ran and the artifact upload failed with
'File dist/LosslessCut-win-x64.7z does not exist'.

Gate them on runner.os == 'Windows' && matrix.os != 'windows-11-arm'
instead, so they are independent of the exact Windows runner image.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PWvFPqUcXUzsYf3DY7RziJ
2 months ago
slrslr a2f7bc61b2 Translated using Weblate (Czech)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/cs/
2 months ago
Pa Di 0d93075ec3 Translated using Weblate (Slovak)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/sk/
2 months ago
slrslr 3cb8ebf0df Translated using Weblate (Czech)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/cs/
2 months ago
Hosted Weblate user 54392 26c84882b9 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 96.1% (871 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/zh_Hans/
2 months ago
Roland Reck 85874a2af5 Translated using Weblate (German)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/de/
2 months ago
John Fowler 7222a65099 Translated using Weblate (Hungarian)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/hu/
2 months ago
slrslr e925feff89 Translated using Weblate (Czech)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/cs/
2 months ago
Igor Rückert 88c89137ef Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/pt_BR/
2 months ago
Oğuz Ersen 7d7c43652d Translated using Weblate (Turkish)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/tr/
2 months ago
bovirus 34f52f9f98 Translated using Weblate (Italian)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/it/
2 months ago
Hosted Weblate user 54392 49dc0bf408 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 96.1% (871 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/zh_Hans/
2 months ago
Kuzmich55 7a436ed588 Translated using Weblate (Russian)
Currently translated at 100.0% (906 of 906 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/ru/
2 months ago
Ngo Lam Bao An 52d7e01bdc Translated using Weblate (Vietnamese)
Currently translated at 76.1% (689 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/vi/
2 months ago
JaeHyung Lee f6668bede9 Translated using Weblate (Korean)
Currently translated at 100.0% (905 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/ko/
2 months ago
Kuzmich55 fbd6efbd4c Translated using Weblate (Russian)
Currently translated at 100.0% (905 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/ru/
2 months ago
John Fowler dc474f4708 Translated using Weblate (Hungarian)
Currently translated at 100.0% (905 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/hu/
2 months ago
bovirus 7d60c4783f Translated using Weblate (Italian)
Currently translated at 100.0% (905 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/it/
2 months ago
slrslr fffb37f2d9 Translated using Weblate (Czech)
Currently translated at 100.0% (905 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/cs/
2 months ago
Ahadiat Lamid 155966507b Translated using Weblate (Indonesian)
Currently translated at 97.5% (883 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/id/
2 months ago
Oğuz Ersen 2423500e17 Translated using Weblate (Turkish)
Currently translated at 100.0% (905 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/tr/
2 months ago
JaeHyung Lee 8d49edbab1 Translated using Weblate (Korean)
Currently translated at 100.0% (905 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/ko/
2 months ago
ssantos 5c16bdb314 Translated using Weblate (Portuguese)
Currently translated at 96.3% (872 of 905 strings)

Translation: LosslessCut/LosslessCut
Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/pt/
2 months ago