Skip to content

EBU STL / Teletext workflow with Flow Editing and optional ARTE validation - #15185

Closed
Triathlon-rally wants to merge 62 commits into
SubtitleEdit:mainfrom
Triathlon-rally:arte-teletext-workflow
Closed

Triathlon-rally wants to merge 62 commits into
SubtitleEdit:mainfrom
Triathlon-rally:arte-teletext-workflow

Conversation

@Triathlon-rally

Copy link
Copy Markdown
Contributor

This branch contains a set of related improvements that grew out of practical work with professional EBU STL / Teletext subtitles, particularly ARTE files.

The main goal was to reuse Subtitle Edit's existing EBU STL and editing architecture wherever possible, rather than creating a separate subtitle editor or parallel implementation.

The work can roughly be divided into three layers:

1. General EBU STL / Teletext improvements

  • Teletext-aware editing that preserves positions, colors, boxing and double-height information.
  • Cell counting based on the actual EBU STL control cells written by the encoder, rather than simply counting visible characters or HTML/SE tags.
  • Validation of the real 40-cell Teletext limit before writing an STL file.
  • Invalid rows are blocked both in EBU STL export / Save As and when saving an already opened Teletext STL.
  • Double-height subtitles take their physical display rows into account.
  • Improvements to EBU STL preview, positioning and editing behaviour.

2. Optional Flow Editing

Flow Editing provides a more word-processor-like way of editing subtitles across subtitle boundaries while retaining the underlying subtitle structure.

It includes handling for split/merge, Return, Backspace, paste, navigation, inline Teletext colors and Teletext width constraints.

Importantly, opening an EBU STL file does not automatically force the user into Flow Editing. An STL file still opens in Subtitle Edit's normal Text mode, and Flow can be enabled or disabled manually.

We deliberately kept this distinction because Flow Editing should be an optional editing workflow, not a mandatory interface for all STL users.

3. Optional ARTE Check and Fix workflow

Some workflow-specific functionality is intentionally attached to Check and Fix ARTE Errors, rather than being imposed on every EBU STL file.

Running the ARTE checks activates Flow Editing and exposes the relevant working parameters. This keeps normal EBU STL editing unchanged while providing a more specialized environment when the user explicitly chooses the ARTE workflow.

The checker covers, among other things:

  • EBU STL header requirements
  • the initial ARTE control/blank subtitle
  • source frame-rate to 25 fps conversion
  • subtitle timing and minimum gaps
  • reading-duration limits and configurable tolerance
  • Teletext cell limits
  • Teletext positions
  • colors and other Teletext attributes
  • fixable versus non-fixable issues

Corrections can be selected and applied, while cases that cannot safely be corrected automatically remain explicit alarms.

The minimum gap deliberately uses Subtitle Edit's existing minimum-gap setting as the single source of truth instead of introducing a second independent ARTE gap setting.

For missing gaps, the correction logic can distribute the required adjustment between the preceding subtitle's out-time and the following subtitle's in-time where sufficient timing capacity exists.

The working Teletext limit is configurable. ARTE normally works with 37 visible characters because mandatory Teletext control cells also consume part of the 40-cell row. The actual STL safety check, however, is always based on the encoded 40-cell limit.

The ARTE header handling deliberately avoids silently rewriting header data merely by opening or exporting a file. Existing informative metadata is preserved where possible, and corrections are made explicitly through the check/fix workflow.

The checker integrates its findings with the existing EBU STL error display and can also produce an error report.

Additional improvements

The branch also contains some smaller editing improvements developed along the way, including the ability to use the existing Fit selected subtitles to time range... function for directly consecutive selected subtitles.

Current status

The current branch builds with 0 errors and 0 warnings.

The main workflows have been tested with EBU STL files and targeted test cases covering Teletext colors, positions, double height, 40-cell overflow, gap correction, frame-rate conversion, Save and Save As.

This work evolved over several Subtitle Edit beta versions and was last reconciled with Subtitle Edit 5.2.0.

Subtitle Edit main has moved considerably since then. I have deliberately not merged the latest main into this tested branch immediately before sharing it, because that would mix a large number of unrelated upstream changes into a working and tested implementation.

Some changes that were originally developed here have also since appeared independently upstream, for example parts of the video-offset handling. I therefore do not expect the complete commit history to be merged as-is.

The intention of sharing this branch is primarily to make the complete working implementation available for review, so that the generally useful EBU STL / Teletext parts, Flow Editing ideas, and ARTE-specific workflow can be evaluated separately and adapted to the current Subtitle Edit codebase where appropriate.

Rally and others added 30 commits August 22, 2026 20:12
# Conflicts:
#	src/ui/Features/Main/Layout/InitToolbar.cs
"Split/re-balance long lines" skipped the split whenever re-wrapping the
text happened to make it fit, even when the existing line break ended a
sentence. A question and its answer were pulled onto one line instead of
becoming two events:

    Und, war ich in der Kantine?        Und, war ich in der Kantine? Nein.
    Nein. Ich konnte Sie dort     ->    Ich konnte Sie dort nicht finden.
    nicht finden.

SE4 suppressed the auto-break in exactly this case and split at the
author's line break instead. Restore that rule: rebalancing no longer
counts as a fix when a line break follows sentence-ending punctuation.

Split() already produced SE4's result for this input - it was just never
reached. Batch convert is unaffected: it has no such gate and always
splits first.

Fixes SubtitleEdit#11476

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pull Bot pushed a commit to A-Archives-and-Forks/subtitleedit that referenced this pull request Sep 23, 2026
The "Save as" dialog listed only text-based formats, so EBU STL could be reached only by
switching the toolbar format first. EBU STL saves through the same path (SaveBinarySubtitle),
so it now sits in the list with the text formats. Other binary formats stay export-only.

Adapted from PR SubtitleEdit#15185 by Triathlon-rally.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Triathlon-rally

Copy link
Copy Markdown
Contributor Author

Small update on this PR
I have continued testing and refining this workflow with Subtitle Edit 5.2, and it is now working reliably in practical use.
I also noticed that several of the more general EBU STL / Teletext improvements have meanwhile been implemented upstream in the 5.3 betas, so I do not expect the complete branch in its current form to be merged as-is.
The two parts that may still be useful as separate additions are:

  1. Check and Fix ARTE Errors
    The main benefit is the workflow for adapting existing subtitle files to ARTE requirements. An existing file can be checked and the unambiguous technical issues corrected automatically, while remaining editorial issues are left for manual review.
    We have also just improved the frame-rate conversion: an ARTE programme start timecode such as 01:00:00:00 or 10:00:00:00 remains fixed as the reference. Only the timing relative to that reference is converted, which avoids shifting the programme start when converting 23.976/24/30 fps material to 25 fps.
  2. Flow Editing
    This complements the checker by allowing the remaining textual problems to be edited continuously across subtitle boundaries. Splitting, merging and rebalancing can then be done in a more natural editing workflow while retaining the underlying subtitle timing and structure.
    In practice, the workflow becomes:
    existing subtitle → Check and Fix ARTE Errors → remaining editorial corrections in Flow Editing → finished EBU STL
    If either of these two parts would be useful for Subtitle Edit, I would be happy to prepare them separately against the current 5.3 codebase rather than asking you to review this complete development branch.
    Please let me know which part, if any, you would be interested in.

@Triathlon-rally

Copy link
Copy Markdown
Contributor Author

Hi Nikolaj,

One more thing: we've also made our browser-based SubtitleWebEditor available online:

https://subtile-web.synology.me/

It demonstrates our workflow for adapting existing subtitle files to broadcast requirements using Check and Fix ARTE Errors, as well as making quick corrections and inserting subtitles with Flow Editing.

The website is password-protected, and we'd be happy to give you access so you can try it yourself.

What's the best way to send you the login details privately?

Best regards,
Ralph

@niksedk

niksedk commented Oct 4, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

Thanks a lot for this, and for the detailed write-up. It made it easy to understand the ARTE workflow.

I decided not to merge the branch as-is. The ARTE rules are specific to one broadcaster, so they fit better as a plugin than in Subtitle Edit's core, where every rule has to be maintained and translated for all users. Your checker is now available as a Subtitle Edit 5 plugin:

  • ARTE check plugin: SubtitleEdit/plugins - se5/ArteCheck (Add ARTE check plugin (SE5) plugins#297), release se5-arte-check-v1.1. Install it via Options → Settings → Appearance → Show Plugins menu, then Plugins → Manage plugins → Get plugins online.
  • It's a port of your CheckArteErrorsViewModel rules: header/language for STA/STF/HG DEU/HG FRA, the blank control subtitle, conversion to 25 fps with the programme start kept fixed, an optional programme-start shift (updates TCP), frame-accurate time codes, durations with reading tolerance and short durations, rebalance/split within the time range, teletext rows 22/20 for double height, colors (yellow or uncolored, SDH mapped to the 8 teletext colors), italics, spaces, and minimum gaps split between the out and in times. Corrections can be selected and applied; everything else is shown as an alarm. "Apply and re-check" runs another pass, and there's a text report.

To make this possible, the plugin interface was extended in #15658. Plugins now receive and can return the EBU header and every line with its teletext row (MarginV), plus a read-only snapshot of the user's rules (durations, CPS, minimum gap, double height). Before that, a plugin only saw SRT, so an EBU STL file lost its header and rows. The full check needs a Subtitle Edit build that includes #15658, so the next beta or a current build from main. Older versions still run the plugin, but only on the text, without the header and row checks.

The minimum gap is now the plugin's own setting (default 5 frames, the ARTE preset) rather than SE's minimum-gap setting, because a plugin can't write SE settings back. The limits are remembered between runs.

Some questions:

  1. Could you test it on real ARTE files and tell me what's wrong or missing? You know the delivery spec much better than I do. Issues and PRs in the plugins repo are very welcome, and you're welcome to take over maintaining the plugin there.
  2. Teletext rows: the plugin follows your rule (stored row = first physical row, so one line on 22 and two lines on 20 with double height). SE's own TeletextRowHelper on main still uses 23/21. Is 22/20 how all EBU STL teletext is meant to be stored, or is that ARTE-specific?
  3. Splitting text that has colors isn't automatic yet (it's reported as an alarm), and line breaks are chosen by a simpler algorithm than SE's AutoBreakLine. Let me know if the proposals don't look right.

Flow Editing is a bigger, separate question. If you'd like to pursue it, please open an issue with a short description and a few screenshots, so we can discuss how it might fit before any code.

Thanks again!

@Triathlon-rally

Copy link
Copy Markdown
Contributor Author

Hi Nikolaj,
I’ve now finished the testing and opened the three PRs we discussed:

  • Subtitle Edit Fix structured plugin response timing #15738 – structured plugin response timing
  • Subtitle Edit Fix EBU STL import frame-rate race #15739 – EBU STL import frame-rate race
  • Plugins Wrong dialog splitting #299 – updated ArteCheck corrections and teletext handling
    Both Subtitle Edit issues were reproduced and retested against the current main. The relevant combined test set passed 149/149 tests, and the EBU race test gives 0 off-grid subtitles after the fix.
    The updated ArteCheck passes 85/85 tests. I also tested the combined beta23 integration earlier with 2708/2708 tests and the real MadMan file (721 → 723 subtitles, then 0 remaining ArteCheck findings).
    The isolated beta23 GUI test also worked correctly. The only test I have not completed yet is the full manual save/reload GUI roundtrip.
    Best,
    Ralph

@niksedk

niksedk commented Oct 6, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

Thanks for the testing and the PRs!

ARTE check v1.2.0 is released: se5-arte-check-v1.2. It contains your SubtitleEdit/plugins#299 changes, plus two small additions on top:

  • Normal (non-SDH) subtitles still have <box> removed (as you confirmed), now as a separate step so other formatting is kept. SDH boxing is untouched.
  • Near-yellow colors (e.g. #fefe00) count as Yellow in the majority vote and are normalized to Yellow.

The plugin index is updated (SubtitleEdit/plugins#300), so Plugins → Manage plugins → Get plugins online shows an Update badge for ARTE check.

Tip: you can give the plugin its own keyboard shortcut in Options → Shortcuts → Plugins (Subtitle Edit 5.3 beta).

#15739 (EBU frame-rate race) is merged, and thanks for rechecking #15738 - a separate PR with the named undo step and skipping identical responses sounds good.

One open question from #299: when a two-speaker dialog is split, each new subtitle keeps its leading dash (e.g. -Ja, liebend gern. on its own). Is that what ARTE wants, or should the dash be removed when only one speaker is left?

Best,
Nikolaj

@Triathlon-rally

Triathlon-rally commented Oct 6, 2026 via email

Copy link
Copy Markdown
Contributor Author

@Triathlon-rally

Copy link
Copy Markdown
Contributor Author

Hi Nikolaj,
I found one more issue while testing the released ArteCheck with the Subtitle Edit integration. I think this may be on the SE/plugin integration side rather than in ArteCheck itself.
With SE 5.3 beta22 I can reproduce this with a 25 fps EBU STL:

  1. Open the STL and run ArteCheck.
  2. It reports 12 minimum-gap corrections (4 → 5 frames).
  3. Apply and re-check → ArteCheck reports 0 corrections / “Ready for ARTE”.
  4. Close with OK and save/export as EBU STL.
  5. Reopen the saved STL and run ArteCheck again.
  6. The same 12 minimum-gap corrections are back.
    For one concrete example, the corrected gap should be 5 frames. After the SE save/reopen roundtrip the stored values are again:
    previous TCO 10:05:16:08, next TCI 10:05:16:12 → 4 frames.
    As a comparison, when the same correction is applied and the STL is written by our web implementation, the previous TCO is stored as 10:05:16:07, so the 5-frame gap survives the save/reopen roundtrip.
    I also tested our older customized SE 5.2 build. The old plugin integration loses much more structured information (header/teletext positions), which is probably due to the old plugin contract, so I don't think that part is relevant to current main.
    I can't share the original STL because it contains production material, but if needed I can make a small synthetic STL that reproduces the issue.
    I haven't changed anything yet, as this looks worth checking on the SE integration side first.
    Best,
    Ralph

@niksedk

niksedk commented Oct 6, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

Thanks for the detailed steps! I could not reproduce it yet - here is what I checked:

  1. ArteCheck fixes a 1-frame shortfall differently than your web tool. It moves the in time of the next subtitle one frame later (TCI 12 → 13) instead of the out time of the previous one (the missing frames are shared half/half, and half of one frame rounds to 0 for the previous line). Running ArteCheck v1.2's analyze + apply on your example gives 10:05:16:08 → 10:05:16:13 (plus the blank 10:00:00:00 subtitle). So TCO 08 is expected after the SE save - it's TCI 12 that shows the fix was lost.
  2. SE's EBU STL writer keeps it. A save + reload of exactly that plugin output keeps TCI 13, TCO 08 and the blank subtitle (also an out time moved one frame earlier, 08 → 07, survives).
  3. SE's plugin apply + save/export paths take the returned paragraphs as-is - I found nothing that rounds or reverts times.

So something in the actual workflow must differ. Could you help with:

  • The small synthetic STL you offered :)
  • Right after OK (before saving): does the SE grid show the new times, e.g. the line that should start at 10:05:16:13?
  • Which save you used: Ctrl+S, Save as, or File > Export > EBU STL?
  • Is a video loaded (and what frame rate)?
  • Is the blank 10:00:00:00 subtitle in the saved file? If it is missing too, the plugin result never reached the file.
  • Note the blank subtitle shifts all subtitle numbers by one - maybe the pair compared after reopening is not the same pair?

If you prefer ArteCheck to match your web implementation (take the frame from the previous out time), that is a small change in the plugin - just say so.

Best regards,
Nikolaj

@niksedk

niksedk commented Oct 7, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

ArteCheck v1.3 is out (release, SubtitleEdit/plugins#302) and available via Plugins > Manage plugins.

Minimum gaps now take an odd missing frame off the previous out time, like your web implementation: a 4-frame gap is fixed by moving the out time one frame earlier (e.g. TCO 10:05:16:08 → 10:05:16:07), and the next in time stays. Larger shortfalls are still shared between out and in time, with the odd frame on the out time.

This should make the SE output match your web tool for the gap fixes. The save/reopen question from my previous comment is still open, though - if the corrections still come back after a save with v1.3, the synthetic STL would be very helpful.

Best regards,
Nikolaj

@Triathlon-rally

Triathlon-rally commented Oct 7, 2026 via email

Copy link
Copy Markdown
Contributor Author

@niksedk

niksedk commented Oct 8, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

Thanks - the "no save needed" repro was the key! Found it, and you were right all along with #15738 - I closed it too early, sorry about that.

Cause: After ArteCheck returns, SE puts the lines in the grid as new rows. A second later the frame-mode change check sees them as "edited" and snaps all times to the current frame rate (EBU STL is always in frame mode). ArteCheck returns 25 fps time codes, so:

  • at 25 fps nothing moves (why I could not reproduce it),
  • with an STL30 file or a 30 / 29.97 / 23.976 fps video, every time code moves to a different frame (e.g. 13 frames = 520 ms becomes 533 ms at 30 fps). Next ArteCheck run: off-grid times and 4-frame gaps again - plus the odd durations you saw.

Fix: #15791 - your change from #15738 (plugin results applied as one undo step named "ARTE check", identical results skipped), with you as co-author, plus a 30 fps regression test.

Your attachments did not arrive (email replies drop them) - if you can attach the 721/723 STL files here on GitHub, I'll verify with the real file. Also: was a video loaded, and what frame rate does SE show in the toolbar?

Nice work on the WebEditor split + the 21-frame tolerance boundary - I'll check that ArteCheck uses the same rounding.

Best regards,
Nikolaj

@niksedk

niksedk commented Oct 8, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

ArteCheck v1.4 is out (Manage plugins → update), with the same duration-tolerance fix you made in the WebEditor: the tolerated minimum is now rounded to whole frames, so at 25 fps with a 25-frame minimum and 15% tolerance, 21 frames is accepted and 20 is reported. The shown limit, the check, dialog splits and gap fixes now all use that value (SubtitleEdit/plugins#304).

One detail: an exact half frame rounds up (21.5 → 22 frames). Does the WebEditor do the same?

The fix for the corrections coming back after OK (#15791) is merged too and will be in the next SE beta - until then the issue remains at non-25 fps frame rates.

Best regards,
Nikolaj

@niksedk

niksedk commented Oct 8, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

One more SE fix for the STL30 case: #15793 (merged). When ArteCheck converts to 25 fps and sets the header to STL25.01, SE's toolbar frame rate now switches to 25 as well - before, the file was saved at 25 fps but the grid still showed 30 fps frame numbers and later manual edits were snapped to 30 fps frames. If a video is loaded, its frame rate still wins.

Together with #15791 this will be in the next SE beta.

Best regards,
Nikolaj

@Triathlon-rally

Triathlon-rally commented Oct 8, 2026 via email

Copy link
Copy Markdown
Contributor Author

@niksedk

niksedk commented Oct 8, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

Thanks again for this branch - it has been very valuable. As discussed above, the ARTE rules now live in the ArteCheck plugin (v1.4 released), and several of the general EBU STL / Teletext improvements and integration fixes have gone into SE separately (#15739, #15791, #15793 and others). So I'll close this PR now, as the work has been landed in other ways.

Please keep reporting anything you find - a new issue (or on the plugins repo for ArteCheck) is the best place going forward. Thanks for all the great testing!

@niksedk niksedk closed this Oct 8, 2026
@Triathlon-rally

Triathlon-rally commented Oct 8, 2026 via email

Copy link
Copy Markdown
Contributor Author

@niksedk

niksedk commented Oct 8, 2026

Copy link
Copy Markdown
Member

Hi Ralph,

Thanks - good catch! ArteCheck v1.5 is released and in the plugin list now (SubtitleEdit/plugins#311).

If the original header has fewer rows than 23 (e.g. MNR 11), the header fix still sets MNR 23, and now the bottom subtitles move with it:

  • one line on VP 11 → 22
  • two lines on VP 10 → 20
  • higher rows (VP 1 at the top, or anything in the middle) are left as they are

"Bottom" means the last line of the subtitle reaches the original MNR row. These show up as normal row corrections in the Teletext line position group, so you can untick single ones if needed.

Please let me know if it matches what your SubtitleWebEditor does.

@Triathlon-rally

Triathlon-rally commented Oct 8, 2026 via email

Copy link
Copy Markdown
Contributor Author

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.

2 participants