Skip to content

Fix/settings scroll align - #7

Merged
pdjdev merged 141 commits into
build/osxfrom
fix/settings-scroll-align
Oct 21, 2026
Merged

pdjdev merged 141 commits into
build/osxfrom
fix/settings-scroll-align

Conversation

@pdjdev

@pdjdev pdjdev commented Oct 21, 2026

Copy link
Copy Markdown
Owner

No description provided.

niksedk and others added 30 commits October 19, 2026 15:48
qwen3-asr.cpp v0.1.9 forces the spoken language from the prompt when -l is
given, the same way the qwen-asr Python package does. Auto-detection is
unreliable on short clips (Danish came out as Swedish or Chinese). "auto"
keeps detection; older engine builds only used -l for Korean word splitting,
so the flag is harmless there.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
v0.1.9 (niksedk/qwen3-asr.cpp#11, SubtitleEdit#12) fixes the runtime-generated mel
filterbank: it used the HTK mel scale sampled at integer bins while the
Whisper feature extractor uses Slaney-scale filters, so the log-mel input
was off by up to 1.6 and the model mis-detected languages on short clips.
On 600 held-out Danish clips the stock 0.6B GGUF goes from 49.5 to 43.1
WER, and a Danish fine-tune from 26.3 to 18.8 (transformers: 18.6). The
release also pads the trailing conv chunk like the reference and forces the
language from the prompt when -l is given (the forced aligner shares the
fixed filterbank, so timestamps improve as well).

New archive and executable hashes prepended for all seven platforms so
existing installs are offered the update.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds qwen3-asr-0.6b-da-q8_0.gguf (https://huggingface.co/niksedk/qwen3-asr-0.6b-danish),
a LoRA fine-tune of Qwen3-ASR-0.6B on 399 h of CoRal, NST and FTSpeech, merged
and quantised to q8_0. On 600 held-out Danish clips through qwen3-asr-cli
v0.1.9 it scores 18.8 WER versus 43.1 for the stock 0.6B model. Needs the
v0.1.9 engine (SubtitleEdit#16244); older engines run it but lose ~7 WER points to the
mel filterbank bug.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…asr-pass-language

Qwen3 ASR: pass the selected language to qwen3-asr-cli
…asr-cpp-v019

Qwen3 ASR: bump qwen3-asr.cpp to v0.1.9 (mel filterbank fix)
…asr-danish-model

Qwen3 ASR: add Danish fine-tuned 0.6B model
…umeric-field-border

Fix compact numeric field borders in EditorChrome
…titleEdit#16031)

PR SubtitleEdit#16207 taught the fix engine that a slash standing alone is a slanted
italic "I". The fix engine runs on every OCR engine's output, so the
title card "PILOTEN / OMGEKOMEN" read by llama.cpp (GLM-OCR) came out as
"PILOTEN I OMGEKOMEN" in 5.4.0-beta2.

- New IOcrFixEngine.FixImageMatcherMisreads flag, set by the OCR window
  for nOCR and binary image compare only (next to FillUnknownCharacters).
  Text engines (Tesseract, Paddle, Ollama, llama.cpp) never fit a glyph
  to "/" or "#", so the slash and hash misread rules stay off for them.
- Even for image matchers a lone slash next to a number ("1 / 2") or
  between two all-caps words ("PILOTEN / OMGEKOMEN", "AC / DC") is kept
  as a separator.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
nOCR reads the sans-serif capital I as "l" ("PlLOTEN / OMGEKOMEN"), and
the all-caps l->I rule only runs after the slash rule, so the guard saw a
lowercase letter and still turned the slash into "I". Verified on nl.sup:
the title card now keeps its slash, no other line changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tchers (SubtitleEdit#16031)

nOCR fits the sans-serif capital I and lowercase l to the same bar, so on
the Dutch Blu-ray names came out as "CowsIip", "HeinkeIs", "FIight" and
all-caps words as "JUNl", "lFF", "WAARSCHlJNLlJK". No dictionary knows the
names, so for a word that is unknown anyway the letters around the bar
decide (TryFixBarMisreadByCase): an I after a lowercase letter, or between
the capital and the first lowercase letter, is an l; an l among capitals
(two, or one with the bar in front) is an I. Mc/Mac, "Il" and words with
another lowercase letter are left alone. Only the English replace list had
the all-caps rule; this covers every language.

Two italic spacing artifacts are repaired on the line: "20. 000" ->
"20.000" (one-to-three digit group, never after a year) and the space
before a closing quote after a sentence end ("voorbij. '").

All four run only for image-matcher output (FixImageMatcherMisreads).
nl.sup: 45 -> 18 lines differing from the GLM reference, 9 of them GLM's
own errors. Before/after on 19 other discs (English, Danish, Polish):
every changed line is a repair (RIDDICK, DIDN'T, FBI-enhed, Statler,
mathlete, Allenwood, trailing quotes).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…j/v/w

An overhanging f, r or t leans over the j, v or w next to it, so nOCR's
space detector swallows the word space: "Hoorje", "kentje", "achterje",
"Vijfvan", "ofwe". For a word the dictionary does not know, split at that
boundary when both halves are words and the right half is a function word
of at most three letters - without the cap "Getverdikkeme" (not in the
dictionary) became "Get verdikkeme". Image-matcher output only.

nl.sup: 18 -> 13 lines differing from the GLM reference; the other discs
gain one repair ("Alt vel") and lose nothing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
v0.1.10 (niksedk/qwen3-asr.cpp#13) adds beam search. Subtitle Edit now
passes --beam-size 3, which took a Danish fine-tune from 25.2 to 23.4 WER
on 300 held-out clips for about twice the decode time (beam 5: 23.1 at
four times). Older engine builds reject unknown arguments, so the flag is
only passed when the installed qwen3-asr-cli advertises it in --help; the
probe runs once per executable.

New archive and executable hashes prepended for all seven platforms.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…asr-cpp-v0110-beam

Qwen3 ASR: bump qwen3-asr.cpp to v0.1.10 and use beam search (3)
…-issue-analysis-eaf387

OCR fix engine: image-matcher I/l and spacing repairs, lone slash kept (SubtitleEdit#16031)
The model prefixes its output with "language <Name><asr_text>". qwen3-asr.cpp
v0.1.9+ strips the marker, but older engine builds leak "<asr_text>" into the
aligned word list for GGUFs that store the token as an ordinary token (the
Danish fine-tune does), so it appeared at the start of subtitle lines. Strip
it in the JSON parser regardless of engine version and drop empty tokens.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…asr-strip-marker

Qwen3 ASR: strip the <asr_text> marker from engine output
…izable lists (SubtitleEdit#16251)

- The saved styles list gets its category picker back, with new/rename/
  delete category beside it. Saved styles are kept per series in
  categories; with hundreds of them a flat list with a category column
  was unusable, and the filter and commands were still in the view model.
- Both style lists show the font name and a color sample ("Aa" in the
  primary color on the outline color, italic when the style is), so the
  colors of every style are visible without selecting it - as SE 5.3.0
  and SE4's advanced styles list showed them.
- A splitter between the lists and the preview/editor lets the lists
  pane grow; its width is remembered (SeAssa.StylesListsWidth, default
  480 instead of a fixed 360) and shared by the ASSA and SSA windows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Updated the Japanese translation for Subtitle Edit 5.4.0 Beta2, in preparation for Beta3.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…leedit-issue-16251-08f77e

ASSA/SSA styles: category picker back, font name + color columns, resizable lists (SubtitleEdit#16251)
…ian by their letters

Natural Macedonian text was reported as Bulgarian (or Russian): the South
Slavic languages share their short words (не, да, за, нас, може, така, беше,
...), so the Bulgarian and Russian word lists won, and the Macedonian list
was mostly words from one space film plus OCR misreads with Latin letters.

The spelling is unambiguous: ј/љ/њ/џ are written only in Macedonian and
Serbian, ќ/ѓ/ѕ only in Macedonian, ћ/ђ only in Serbian, and none of them
has ъ/ы/э/ё/й/щ/ь/ю/я. One letter scan per detection now decides "mk" or
"sr" in the Russian and Bulgarian blocks and in the letter-statistics
fallback (which answered "ru" for every Cyrillic text). Bulgarian/Russian
keep winning when their letters outnumber the misread ones in an OCR file.

The Macedonian word list is rebuilt from everyday words that Bulgarian
and Serbian spell differently.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nian-language-detection-87cfc8

Language auto-detect: tell Macedonian and Serbian from Bulgarian/Russian by their letters
…ings

Zoom in/out tooltips were inverted, "Colora le righe" for the custom
error rules toggle, "Elenco elenco", "uan", "delal", "fotgramma",
"colroe", "Analisi in corso...", double spaces, Disinstalla, "un tuo
modello", Cornice for the Frame background box, and the Sync to audio
hint now names the real menu items.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Updated the Japanese translation for Subtitle Edit 5.4.0 Beta2, in preparation for Beta3.
"Save as iTunes Timed Text" produced a different header for every source
format: an ITT source kept its own styling (e.g. tts:color="#EBEBEB"), a
TTML source kept its header, and an SRT got the built-in one with white
styles, a <body> without a default region and region="bottom" on every
line. There was no way to get the same header for every file (SubtitleEdit#16257).

File > Properties for iTunes Timed Text now has:
- Presets: a named copy of the whole setup (combo + save/delete like
  batch convert), stored in Settings.Formats.TimedTextItunesPresets.
- Header source: "Current file" (as before) or "Template file" - an
  .itt/.xml whose head (styles, regions, metadata) and body attributes
  are used for every saved file; the window lists the template's styles
  and regions and shows a summary or why the file is rejected. The UI
  reads the file and hands libse the text (TimedTextItunesHeaderTemplate).
- Default color: the color of the built-in header's styles; in current
  file mode OK recolors the styles that carried the old default color.
- Default style/region are persisted and put on the built-in <body>.

libse ItunesTimedText.ToText: a template header replaces the source
header (frame rate/drop mode follow the current frame rate, the language
setting wins when set, unknown paragraph styles are dropped), and a line
only names its region when it differs from the body's - with
<body region="bottom"> only top-aligned lines get region="top".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…leedit-discussion-16257-7f3414

iTunes Timed Text: export presets with a template-file header source
A fixed-palette dark theme (polar night background, snow storm text, frost
blue accents). It shares the dark Fluent variant, icons and syntax colors
with Dark, so IsDarkThemeEnabled covers both, and the dark background and
foreground lookups return Nord's colors instead of the user's dark-mode
settings. The editor palette and plugin theme colors follow it too.

Switching between Dark and Nord keeps the dark variant, so the Fluent
region color never reached the windows: dark themes now set the window
background through a style, and Settings OK refreshes the grid's
alternating row color, which has its own Nord shade.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…or Cyrillic, Baltic, Afrikaans/Dutch and Arabic-script

A probe with natural dialogue and narration in all 46 supported languages
missed 31 of 230 clips, almost all of them two to five lines long: a lone
shared word handed the clip to another language, or no word matched and the
letter fallback answered from its four Latin alphabets (Catalan as Czech,
Romanian as French, Polish as Spanish, Lithuanian as Latvian, Albanian as
French, Slovene as Serbian, Ukrainian as Russian, Afrikaans as Dutch, ...).

Word lists: everyday words added for English, Danish, Norwegian, Swedish,
Finnish, Estonian, Latvian, Catalan, Romanian, Polish, Czech, Slovak,
Slovene, Croatian, Serbian (both scripts), Macedonian, Ukrainian, Portuguese,
Afrikaans, Dutch, German, Italian, Hungarian, Greek, Albanian, Farsi,
Hebrew, Indonesian, Vietnamese and Tagalog, preferring the spellings the
neighbouring languages do not share; Lithuanian and Albanian rebuilt (the
old lists were names and lines from one film). Words another language also
uses (Danish "sig", Dutch "is", Italian "li", Portuguese "nem", ...) kept out.

Letter rules, each a single pass and only when the blocks need them:
- Cyrillic: і/ї/є/ґ Ukrainian, ы/э/ё Russian, ъ Bulgarian, on top of the
  Macedonian/Serbian rule; the letter fallback refines its "ru" answer.
- Baltic: ą/ę/ė/į/ų Lithuanian vs ā/ē/ī/ģ/ķ/ļ/ņ/ō Latvian.
- Afrikaans/Dutch: y vs z and ij.
- Arabic script: پ/چ/ژ/گ/ی/ک Persian, ٹ/ڈ/ڑ/ں/ے/ھ/ہ Urdu, ي/ك/ة/ذ/ض/ظ Arabic.
- Letter fallback: languages with letters of their own (pl, cs, sk, hu, ro,
  tr, lt, lv, is, vi, pt, es, sq) are answered before the four-alphabet score.

Decision blocks: Czech and Slovak get blocks of their own and score with
their own counts; the Danish/Norwegian "only" lists break ties instead of
vetoing both; Greek in the ANSI code-page check must beat the Cyrillic
count; the right-to-left letter set is letters only (phrases added spaces).

LanguageAutoDetectNaturalTextTest: 460 cases from four sample sets, all
languages, at one to ten lines and everything together.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
niksedk and others added 27 commits October 20, 2026 20:14
- Remove unused private methods/fields/constants flagged by IDE0051/IDE0052
  (write-only fields, dead helpers, unused libvlc delegates)
- Remove public/internal methods in ui and libuilogic with no references
  (UiUtil helpers, FfmpegGenerator, WhisperHelper, etc.); drop the now
  empty TimeSpanFormatter and SplitHelper files
- Drop constructor-injected services that were never used and the
  IDoSpell parameter of SpellCheckWordLists; update tests accordingly
- Remove usings that became unused in the touched files

libse public API and the netstandard-only CharLookup paths are untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New syntax coloring setting "Color if gap is in range" (off by default) with
a min/max gap range (defaults 3-12 frames / 120-480 ms, inclusive). It marks
mid-sized gaps for the broadcast rule that a gap is either closed (about 2
frames) or at least about 12 frames. Follows ms/frames time code mode like
the minimum gap; in frame mode the gap is rounded to whole frames first.

Grid gap cell, screen-reader text, HasErrors and the error list (new
"Gap in range" class) all use the same check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…leanup-71a4b7

Code cleanup: remove unused methods, fields and dependencies
Removes using directives flagged by IDE0005 in ui, libuilogic, seconv
and the test projects. libse is left alone: it multi-targets
netstandard2.1 and net10.0, so a using unused in one target can still be
needed by the other.

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

# Conflicts:
#	src/libuilogic/AudioToText/WhisperHelper.cs
#	src/libuilogic/Translate/Formatting.cs
#	src/ui/Features/Shared/PickRuleProfile/PickRuleProfileViewModel.cs
#	src/ui/Features/Video/TextToSpeech/TextToSpeechViewModel.cs
#	tests/UI/Features/SpellCheck/HyphenatedNameSpellCheckTests.cs
#	tests/UI/Features/SpellCheck/SpanishSeWordListTests.cs
#	tests/UI/Features/SpellCheck/UserDictionaryNormalizationTests.cs
#	tests/UI/Features/Sync/PointSync/PointSyncWindowTests.cs
#	tests/UI/Features/Video/EmbeddedSubtitlesEditTests.cs
#	tests/UI/Features/Video/TextToSpeechWindowTests.cs
…gap-in-range

Color the grid gap when it falls inside a user-defined range
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-unused-usings

Remove unused usings outside libse
Japanese translation for Subtitle Edit 5.4.0 Beta3
Update Japanese.json for Subtitle Edit 5.4.0 Beta4
Grid copy/cut and waveform copy wrote the video-relative row times to the
clipboard, while the grid shows and a save writes them with the video
offset added. Copy now adds the offset and the subtitle-format paste
takes it off again, so copy + paste inside SE keeps the timing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remember the last copied text and its video offset; when the clipboard
still holds that copy, paste subtracts that offset instead of the current
one, so copy, change offset, paste keeps the original times.

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

New Settings > Tools switch "Split at video and text box position: cursor at
the end keeps all text in the first line (second line empty)". On, the
"split at video and text box position" commands (and their "... and play"
variants) with the caret at the end keep all the text in the first half and
leave the second empty, like SE 4. Off (default) keeps the SubtitleEdit#14962 fallback to
the line break. Plain "split at cursor" and the original text box are not
affected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…offset-grid-copy-73e306

Include video offset when copying from the grid
…leedit-issue-16095-0c0fe3

Setting: split at video and text box position keeps text at caret end (SubtitleEdit#16095)
Hunspell knows rare words like Dutch "weetje", "watje", "wasje" and
"moetje", so an OCR'd "weet je" with the space lost was never flagged by
spell check, and the OCR fix rules that only fire on unknown words left
it alone. Options > Word lists now has a "Removed from dictionary" list:
those words count as misspelled whatever Hunspell says, are not offered
as suggestions, and the OCR fix pronoun-split rule can fix them.

Stored in a <removed> section of <lang>_user.xml (also read from the
shipped _se.xml lists; the user's own file wins). Adding a word to the
user dictionary takes it off the removed list and the other way round.
Writing the user word list no longer drops the rest of the file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shows the current speed (e.g. 1.0x) in the video controls; a click opens a
menu with the speeds. Hidden by default, configurable in Video controls.
Goes through SelectedSpeed, so the waveform toolbar speed follows, and the
full-screen player now gets the speed on open and hands it back on close.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…heck-rejected-words

Spell check: remove words from the dictionary (SubtitleEdit#16031)
…ck-speed-video-player-900687

Video player: optional playback speed button (SubtitleEdit#16306)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T08:40:25.873773Z 9c80b58 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pdjdev
pdjdev merged commit 0a4f152 into build/osx Oct 21, 2026
4 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c80b58b8a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

internal static byte[] ReadPayload(System.IO.Stream fs, ulong length)
{
var bytesLeft = fs.Length > fs.Position ? (ulong)(fs.Length - fs.Position) : 0UL;
var buffer = new byte[Math.Min(length, bytesLeft + 8)];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the minimum payload size expected by MP4 parsers

When a truncated MP4 ends immediately after a child-box header, bytesLeft is zero and this returns only eight bytes even if the declared payload is much larger. Callers then immediately read beyond that buffer—for example, Stbl reads GetUInt(8) for stsz, while Mdia reads the handler type at offset 8—so opening such a malformed file now throws ArgumentOutOfRangeException instead of safely rejecting it. Either pad to each caller's required header size as before or make callers validate the returned length before indexing.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants