Skip to content

Add visual waveform split lanes for ASS/SSA metadata#10706

Open
Ironship wants to merge 5 commits intoSubtitleEdit:mainfrom
Ironship:pr/A-multi-track-ui
Open

Add visual waveform split lanes for ASS/SSA metadata#10706
Ironship wants to merge 5 commits intoSubtitleEdit:mainfrom
Ironship:pr/A-multi-track-ui

Conversation

@Ironship
Copy link
Copy Markdown
Contributor

@Ironship Ironship commented Apr 26, 2026

Summary

Replaces the earlier ASS/SSA multi-track editing prototype with a smaller visual-only waveform split mode.

This keeps the subtitle model and saved ASS/SSA data unchanged. Instead of adding real TrackIndex state, the waveform can be visually split into lanes based on existing subtitle metadata:

  • none
  • actor
  • style
  • layer
  • ASS position/alignment

The intent is to make complex ASS/SSA files easier to inspect in the waveform without introducing generated track styles or changing tools such as Fix Common Errors, merge, bridge gaps, or duration adjustment.

Behavior

  • Adds a Split: None menu button to the waveform toolbar.
  • Draws subtitle blocks in visual lanes for the selected split mode.
  • Shows lightweight lane dividers and labels.
  • Keeps hit testing within the clicked lane.
  • Keeps movement/resizing constrained to neighboring subtitles in the same visual lane.
  • Does not change actor/style/layer/positioning metadata when dragging. Moving between virtual lanes is not a data-editing operation.

Why this direction

This follows the feedback that ASS/SSA already has actors, styles, layers, and positioning, so a visual grouping mode fits the format better than adding real multi-track state to Paragraph.

The previous larger prototype is preserved in my fork at:

backup/pr-10706-multitrack-original-20260427

Verification

  • dotnet build .\src\ui\UI.csproj -c Debug -v minimal
  • dotnet test .\tests\UI\UITests.csproj -c Debug -v minimal (94 passed)
  • Manual smoke test of the waveform split menu and visual lanes.

Notes

Compared to previous more complex change we modify 3x less code.

@Ironship Ironship force-pushed the pr/A-multi-track-ui branch from 686d428 to 3807eee Compare April 27, 2026 10:09
@Ironship Ironship marked this pull request as ready for review April 27, 2026 10:10
Copilot AI review requested due to automatic review settings April 27, 2026 10:10
@Ironship Ironship force-pushed the pr/A-multi-track-ui branch from 3807eee to e299e97 Compare April 27, 2026 10:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds experimental multi-track subtitle editing for ASS/SSA by introducing track state into the core subtitle model and updating waveform editing + multiple tools/validators to operate on same-track neighbors only.

Changes:

  • Introduces TrackIndex in the subtitle model (Paragraph) and propagates it through UI view models and conversion paths.
  • Updates “neighbor-aware” operations (Fix Common Errors, bridge gaps, merge tools, duration tools, batch checks) to use previous/next paragraphs on the same track.
  • Adds waveform multi-row rendering and a track header UI, plus regression tests for same-track behavior.

Reviewed changes

Copilot reviewed 44 out of 44 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/libse/Forms/FixCommonErrorsTrackTests.cs Regression: FixShortGaps shouldn’t adjust across tracks.
tests/libse/Core/MergeShortLinesUtilsTest.cs Regression: merge-short-lines should not merge across tracks.
tests/UI/Logic/SplitManagerTests.cs Regression: split preserves TrackIndex.
tests/UI/Logic/InsertServiceTests.cs Regression: insert-after inherits TrackIndex and ignores next different-track neighbor.
tests/UI/Logic/DurationsBridgeGaps2Tests.cs Regression: bridge gaps uses same-track neighbor and doesn’t bridge across tracks.
tests/UI/Features/Tools/MergeShortLines/MergeShortLinesHelperTests.cs Regression: UI merge helper doesn’t merge across tracks.
tests/UI/Features/Tools/AdjustDuration/AdjustDurationViewModelTests.cs Regression: duration cap uses next subtitle on same track.
src/libse/Forms/FixCommonErrors/Helper.cs Fix Common Errors: previous paragraph checks now same-track.
src/libse/Forms/FixCommonErrors/FixUnnecessaryLeadingDots.cs Fix Common Errors: previous paragraph now same-track with null handling.
src/libse/Forms/FixCommonErrors/FixStartWithUppercaseLetterAfterParagraph.cs Fix Common Errors: previous paragraph now same-track.
src/libse/Forms/FixCommonErrors/FixSpanishInvertedQuestionAndExclamationMarks.cs Fix Common Errors: previous/next now same-track.
src/libse/Forms/FixCommonErrors/FixShortGaps.cs Fix Common Errors: next paragraph now same-track with null handling.
src/libse/Forms/FixCommonErrors/FixShortDisplayTimes.cs Fix Common Errors: prev/next/next-next now same-track.
src/libse/Forms/FixCommonErrors/FixOverlappingDisplayTimes.cs Fix Common Errors: prev/next now same-track with null handling.
src/libse/Forms/FixCommonErrors/FixMissingPeriodsAtEndOfLine.cs Fix Common Errors: next paragraph now same-track.
src/libse/Forms/FixCommonErrors/FixHyphensInDialog.cs Fix Common Errors: previous paragraph now same-track.
src/libse/Forms/FixCommonErrors/FixContinuationStyle.cs Fix Common Errors: next paragraph now same-track with null handling.
src/libse/Forms/FixCommonErrors/AddMissingQuotes.cs Fix Common Errors: prev/next neighbors now same-track (incl. lookahead).
src/libse/Forms/DurationsBridgeGaps.cs Bridge gaps: uses next subtitle on same track.
src/libse/Common/Utilities.cs Utility display-time fix: next paragraph now same-track.
src/libse/Common/TextSplit.cs Sentence splitting: next paragraph now same-track.
src/libse/Common/SubtitleTrack.cs New model type for UI track metadata (name/color/index).
src/libse/Common/Subtitle.cs Adds same-track neighbor helpers and uses them in duration adjustment paths.
src/libse/Common/Paragraph.cs Adds TrackIndex and ensures copy ctor preserves it.
src/libse/Common/MergeShortLinesUtils.cs Core merge-short-lines: require same TrackIndex to merge.
src/libse/Common/MergeLinesSameTextUtils.cs Core merge-same-text: require same TrackIndex to merge.
src/libse/Common/FixDurationLimits.cs Duration limits: next paragraph now same-track.
src/UI/Logic/NetflixQualityCheck/NetflixCheckDialogHyphenSpace.cs Netflix QC: previous paragraph now same-track.
src/UI/Logic/Media/MpvReloader.cs Ensures mpv refresh updates paused frame after reload.
src/UI/Logic/InsertService.cs Insert logic: same-track prev/next + inherit TrackIndex for new subtitles.
src/UI/Logic/DurationsBridgeGaps2.cs UI bridge gaps: uses next subtitle on same track.
src/UI/Logic/Config/Language/Waveform/LanguageWaveform.cs Adds UI strings for track controls.
src/UI/Features/Tools/MergeSubtitlesWithSameText/MergeSameTextViewModel.cs Preview merge-same-text now preserves and checks TrackIndex.
src/UI/Features/Tools/MergeShortLines/MergeShortLinesHelper.cs UI merge-short-lines: stop merge group when track changes.
src/UI/Features/Tools/BatchConvert/BatchErrorList/BatchErrorListViewModel.cs Batch error prev/next context now same-track.
src/UI/Features/Tools/BatchConvert/BatchConverter.cs Same-timecode merging: avoid cross-track merges.
src/UI/Features/Tools/ApplyDurationLimits/ApplyDurationLimitsViewModel.cs Apply duration limits: next subtitle now same-track.
src/UI/Features/Tools/AdjustDuration/AdjustDurationViewModel.cs Adjust duration: next subtitle now same-track.
src/UI/Features/Main/SubtitleLineViewModel.cs Adds TrackIndex and round-trips it to/from Paragraph.
src/UI/Features/Main/MainViewModel.cs Adds track state, injects per-track ASS styles, track-aware paste/errors/insert/seek behavior.
src/UI/Features/Main/Layout/InitWaveform.cs Adds track header panel + “Add Track” UI and wires active-track syncing.
src/UI/Controls/VideoPlayer/VideoPlayerControl.cs Adds explicit seeking API (SetPosition) and property update tweaks.
src/UI/Controls/TrackHeaderControl/TrackHeaderPanel.cs New control: renders track list and supports selecting/renaming tracks.
src/UI/Controls/AudioVisualizerControl/AudioVisualizer.cs Multi-row rendering, hit testing, resizing/moving restricted to selected track; supports cross-track drag.

Comment thread src/UI/Features/Main/MainViewModel.cs Outdated
Comment thread src/UI/Logic/DurationsBridgeGaps2.cs Outdated
Comment thread src/libse/Forms/DurationsBridgeGaps.cs Outdated
Comment thread src/UI/Controls/AudioVisualizerControl/AudioVisualizer.cs Outdated
@niksedk
Copy link
Copy Markdown
Member

niksedk commented Apr 27, 2026

I'm not really sure ASSA/SSA makes sense for multi-track - the mostly have 1 or like 20+ styles/actors.
Multi-track does make sense for when translating with two tracks - or when using Video - more - open secondary subtitle.

(sorry, renamed the "UI" folder to "ui")

@Ironship Ironship force-pushed the pr/A-multi-track-ui branch from 7e0db6d to 23e2848 Compare April 27, 2026 20:40
@Ironship Ironship changed the title feat: multi-track subtitle support for ASS/SSA Add visual waveform split lanes for ASS/SSA metadata Apr 27, 2026
@Ironship
Copy link
Copy Markdown
Contributor Author

Ironship commented Apr 27, 2026

@niksedk Good point. I had also been considering a smaller visual-only variant with fake tracks in parallel, and this was the kind of feedback I needed to decide which direction made more sense.

I have replaced this PR with that second prototype: Now the subtitle model is unchanged, and ASS/SSA is split only visually in the waveform by existing metadata (actor, style, layer, or ASS position/alignment). Dragging/resizing still edits timing only; moving between virtual lanes is not a metadata-editing operation, so actor/style/layer/position should still be edited in the normal text/style UI as it was dane before :)

The previous larger TrackIndex-based prototype is preserved in my fork as backup/pr-10706-multitrack-original-20260427 in case we want to compare or recover anything from it.

New / simplier version adds simple splitting view

mcmrsJAFQQ

This should make multi actors editing much easier. At least in my cases where I have 1 to 6 actors. I had lots of trouble when i had to add notes on top of video, and two actors were trying to speak at once. Posibility to change view improves readability.

@Ironship Ironship requested a review from Copilot April 27, 2026 20:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Introduces a visual-only “waveform split lanes” mode for ASS/SSA-style metadata so subtitle blocks can be displayed in separate lanes without changing the underlying subtitle model/data.

Changes:

  • Adds a new waveform toolbar “Split” menu with multiple split modes (None/Actor/Style/Layer/ASS position+alignment).
  • Adds WaveformSplitMode and wires it into AudioVisualizer rendering and hit-testing.
  • Updates movement/resizing constraints to consider only neighboring subtitles within the same visual lane.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
src/ui/Features/Main/Layout/InitWaveform.cs Adds a Split menu button and menu items to control the visual lane split mode.
src/ui/Controls/AudioVisualizerControl/WaveformSplitMode.cs Introduces the enum backing the split modes.
src/ui/Controls/AudioVisualizerControl/AudioVisualizer.cs Implements lane mapping, lane-aware rendering, hit-testing, and neighbor constraints based on selected split mode.
Comments suppressed due to low confidence (1)

src/ui/Controls/AudioVisualizerControl/AudioVisualizer.cs:1674

  • When WaveformSplitMode is enabled, existing paragraphs are rendered inside lane bounds, but DrawNewParagraph is still invoked and (currently) draws the new selection across the full height. This makes the “new selection” visual inconsistent with the lane split and can overlap multiple lanes. Consider making the new-selection rendering lane-aware (e.g., use the clicked lane or a computed lane for NewSelectionParagraph) or suppress lane dividers/labels while creating a new selection.
            DrawSpectrogram(context, ref renderCtx);
            DrawTimeLine(context, ref renderCtx);
            DrawVisualLaneDividers(context, ref renderCtx);
            DrawParagraphs(context, ref renderCtx);
            DrawShotChanges(context, ref renderCtx);
            DrawCurrentVideoPosition(context, ref renderCtx);
            DrawNewParagraph(context, ref renderCtx);

Comment thread src/ui/Controls/AudioVisualizerControl/AudioVisualizer.cs
Comment thread src/ui/Controls/AudioVisualizerControl/AudioVisualizer.cs
Comment thread src/ui/Features/Main/Layout/InitWaveform.cs
Comment thread src/ui/Features/Main/Layout/InitWaveform.cs Outdated
Comment thread src/ui/Controls/AudioVisualizerControl/AudioVisualizer.cs Outdated
@Ironship
Copy link
Copy Markdown
Contributor Author

Addressed the active Copilot review feedback in 49cf52e: cached the visual lane map for pointer-move/hit-test paths, moved Split waveform labels into Se.Language.Waveform, made Split button ordering deterministic, and changed Style splitting to use SubtitleLineViewModel.Style without falling back to Extra.

@niksedk
Copy link
Copy Markdown
Member

niksedk commented Apr 30, 2026

OK, I tried this a bit and it looks cool, but I was unable to see anything useful for the ASSA files I tried with... either a lot of styles/actors/effects or just one style and zero actors.

It could probably be useful for "Open second subitle" or subtitles with more than one language.

@Ironship
Copy link
Copy Markdown
Contributor Author

Ironship commented May 2, 2026

@niksedk

It could probably be useful for "Open second subitle" or subtitles with more than one language.

Well in my use case with translations from war in Ukraine or translations for charities its usefull when I have 2-3 actors + additional notes.

Another niche is Fansubs for anime. Usually they have 2-6 actors + double subs.

Update:

I’ve added logic so that the Split button in the waveform only appears when:

  • the current format supports styled/metadata subtitles (HasStyleSupport)
    and at least one split mode actually provides more than one lane
  • I have hidden individual menu options if they are not relevant for the current file
  • I reset the split to None if the selected mode becomes unavailable after a change in format or data

@Ironship Ironship force-pushed the pr/A-multi-track-ui branch from 7ec87bf to 3d7059e Compare May 2, 2026 19:36
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.

3 participants