Skip to content

Conversation

@x15sr71
Copy link
Contributor

@x15sr71 x15sr71 commented Dec 23, 2025

In raising this pull request, I confirm the following (please check boxes):

  • I have read and understood the contributors guide.
  • I have checked that another pull request for this purpose does not exist.
  • I have considered, and confirmed that this submission will be valuable to others.
  • I accept that this submission may not be used, and the pull request closed at the will of the maintainer.
  • I give this submission freely, and claim no ownership to its content.
  • I have mentioned this change in the changelog.

My familiarity with the project is as follows (check one):

  • I have never used CCExtractor.
  • I have used CCExtractor just a couple of times.
  • I absolutely love CCExtractor, but have not contributed previously.
  • I am an active contributor to CCExtractor.

[FEATURE] - Add ASS/SSA \pos positioning for CEA-608 captions (feature request #1726)

Summary

Implements precise positioning for ASS/SSA subtitle export using \pos(x,y) tags, replacing whitespace-based layout where sufficient positioning information is available.

Fixes #1726

Changes

  • Added ass_position_from_row() function to map CEA-608 rows to ASS coordinates
  • Applied {\an2\pos(x,y)} positioning tags for single-region captions (1-2 rows)
  • Added PlayResX/PlayResY declarations to Script Info header (384×288)
  • Maintained backward compatibility via conservative guards

Design Decisions

Positioning is intentionally conservative:

  • Applied only when 1-2 caption rows are active to avoid layout conflicts
  • Mapped to lower-third region (60-95% of PlayResY) to preserve readability and
    avoid unsafe display areas
  • Falls back to legacy whitespace behavior when layout is ambiguous (>2 rows)

Resolution choice:

  • Uses SSA default 384×288 resolution (standard for libass/Aegisub/VSFilter)
  • Now explicitly declared in header for spec compliance

This improves visual consistency without changing caption semantics or risking regressions on complex roll-up layouts.

Testing

  • Verified output using a sample from the CCExtractor sample platform:
  • Comparison of output: Before.assAfter.ass
  • Position tags correctly map CEA-608 rows into lower-third ASS coordinates
  • Legacy SSA whitespace-based layout is preserved for multi-region captions

Future Enhancements

Fuller grid-based positioning and horizontal placement derived from CEA-608 semantics; however, this involves additional
interpretation of PAC data and roll-up behavior and is intentionally out of scope for this change.

Copy link
Contributor

@cfsmp3 cfsmp3 left a comment

Choose a reason for hiding this comment

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

Review Summary

Thanks for this feature! The implementation is well-designed with good safeguards. Testing confirms it works correctly.

✅ What's Good

  • Conservative guard: only applies positioning for 1-2 row captions
  • Falls back gracefully to legacy behavior for complex layouts (>2 rows)
  • Uses standard SSA resolution (384×288) with explicit header declaration
  • Positioning math is correct: Row 0 → y=172 (60%), Row 14 → y=273 (95%)
  • Doesn't affect SRT or other output formats
  • All CI checks pass, all 248 Rust tests pass

Testing Results

Tested with sample 56c9f345... from Sample Platform:

  • 118 dialogues correctly received {\an2\pos(x,y)} tags
  • 1 dialogue with >2 rows correctly fell back to legacy behavior
  • Compared with master: changes are purely additive

📋 One Minor Fix Needed

CHANGES.TXT entry is truncated:

- New: Added ASS/SSA \pos-based positioning for CEA-608 captions when layout

Please complete the sentence, e.g.:

- New: Added ASS/SSA \pos-based positioning for CEA-608 captions when layout is simple (1-2 rows) (#1726)

Once fixed, this is ready to merge! 🎉

@cfsmp3
Copy link
Contributor

cfsmp3 commented Dec 23, 2025

Note: The approval above is conditional on the Sample Platform CI tests passing. The tests were still queued at the time of review:

  • CI - linux: pending
  • CI - windows: pending

Please wait for these to complete before merging. If any tests fail, the issues should be addressed first.

@x15sr71
Copy link
Contributor Author

x15sr71 commented Dec 23, 2025

Thanks for the review. I’ve fixed the truncated changelog entry and updated the loops to use scoped variables, and pushed the updated commit.

@x15sr71 x15sr71 force-pushed the feat/ssa-ass-precise-positioning branch from 34cd891 to 9ad9155 Compare December 27, 2025 01:18
Copy link
Contributor

@cfsmp3 cfsmp3 left a comment

Choose a reason for hiding this comment

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

The implementation looks good! The positioning is working correctly and the guard for 1-2 row captions is a sensible approach to avoid regressions.

The Windows CI failure is expected since the ASS output format changed - we'll need to update the test baselines.

One small fix needed: the CHANGES.TXT entry appears incomplete:

- New: Added ASS/SSA \pos-based positioning for CEA-608 captions when layout

Please complete this sentence (e.g., "...when layout information is available" or similar).

Once that's fixed, we can merge and update the test baselines.

@x15sr71 x15sr71 force-pushed the feat/ssa-ass-precise-positioning branch from 50a8540 to 5dd1961 Compare December 30, 2025 08:43
@x15sr71
Copy link
Contributor Author

x15sr71 commented Dec 30, 2025

@cfsmp3, I've completed the CHANGES.TXT entry as discussed and resolved the merge conflict by keeping both entries. Please let me know if anything else needs adjustment.

@cfsmp3
Copy link
Contributor

cfsmp3 commented Jan 3, 2026

Hi @x15sr71, the CHANGES.TXT entry appears to be cut off mid-sentence. Could you complete it?

@x15sr71
Copy link
Contributor Author

x15sr71 commented Jan 3, 2026

Hi @cfsmp3, thanks for checking again.
The current 0.96.2 changelog entry now reads:

Please let me know if you’d prefer any wording changes, as I might be misunderstanding something.

@x15sr71
Copy link
Contributor Author

x15sr71 commented Jan 10, 2026

Hi @cfsmp3, quick ping in case this got buried, no rush on my side. Happy to help with any adjustments or test updates if that helps move this forward.

@x15sr71 x15sr71 requested a review from cfsmp3 January 10, 2026 20:21
Copy link
Contributor

@cfsmp3 cfsmp3 left a comment

Choose a reason for hiding this comment

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

Deep Review of PR #1885

I've thoroughly analyzed the math, built the PR, and tested with multiple CEA-608 samples.

What Works

  1. PlayResX/PlayResY header: Correctly added (384×288, SSA default)
  2. Single-line captions: Positioning is correct
  3. Guard for 3+ rows: Falls back to legacy behavior appropriately

Issue 1: Math Error for 2-Line Captions

The code uses first_row with \an2 (bottom-center alignment), which is incorrect for multi-row captions.

The problem:

  • \an2 places the bottom of the text block at the specified Y coordinate
  • For a 2-line caption at rows 13-14:
    • first_row = 13, y = 265
    • The bottom line (row 14's text) ends at y=265
    • But row 14 should be at y=273
    • Error: 8 pixels (2.8% of screen)

Evidence from test output:

Dialogue: 0,00:00:21.98,00:00:24.23,Default,,0000,0000,0000,,{\an2\pos(192,265)}(both)\NWOW!

With \an2, "WOW!" (the bottom line, row 14) has its bottom at y=265, but row 14's calculated position is y=273.

Fix: Use the last used row instead of the first:

// Current (lines 254-260):
for (i = 0; i < 15; i++)
    if (data->row_used[i]) { first_row = i; break; }

// Should be:
int last_row = -1;
for (i = 14; i >= 0; i--)
    if (data->row_used[i]) { last_row = i; break; }

Issue 2: Non-Adjacent Rows Would Be Catastrophically Wrong

The code assumes used_row_count <= 2 means a "single logical caption region" but doesn't verify the rows are adjacent.

Worst case: Rows 3 and 14 both used (rare but possible):

  • first_row = 3, y = 193
  • BOTH lines positioned with bottom at y=193
  • Row 14 text would be misplaced by 80 pixels (27.8% of screen)

Suggested fix: Either:

  1. Check that the two rows are adjacent before applying positioning, OR
  2. Only apply positioning when used_row_count == 1

Issue 3: Changelog Entry in Wrong Version

The changelog entry is added under 0.96.2 (2025-12-26) which is a past release. It should be moved to the current development version section (0.96.5 or whatever is current at merge time).

Row-to-Y Mapping Reference

For reviewers, here's the complete mapping with PlayResY=288:

row 0  → y=172 (59.7%)    row 8  → y=229 (79.5%)
row 1  → y=179 (62.2%)    row 9  → y=236 (81.9%)
row 2  → y=186 (64.6%)    row 10 → y=244 (84.7%)
row 3  → y=193 (67.0%)    row 11 → y=251 (87.2%)
row 4  → y=200 (69.4%)    row 12 → y=258 (89.6%)
row 5  → y=208 (72.2%)    row 13 → y=265 (92.0%)
row 6  → y=215 (74.7%)    row 14 → y=273 (94.8%)
row 7  → y=222 (77.1%)

Summary

The feature concept is good and addresses issue #1726, but the positioning math needs correction before merging. The error is small for adjacent rows (~3%) but could be severe for edge cases.

@x15sr71
Copy link
Contributor Author

x15sr71 commented Jan 13, 2026

Thanks for the detailed review and for the helpful fix suggestions.

I’ve applied the suggested fixes to the ASS positioning logic (anchor correction + row adjacency guard) and did a small cleanup around variable initialization. I validated the changes using this sample from the Sample Platform. I’ve attached the newly generated .ass file here for review and moved the changelog entry to the correct section. Let me know if anything else needs adjusting!

@x15sr71 x15sr71 requested a review from cfsmp3 January 13, 2026 18:55
@x15sr71 x15sr71 force-pushed the feat/ssa-ass-precise-positioning branch from faa8444 to ac22206 Compare January 13, 2026 18:59
@x15sr71 x15sr71 force-pushed the feat/ssa-ass-precise-positioning branch from e20497d to 4f6a832 Compare January 13, 2026 19:47
@ccextractor-bot
Copy link
Collaborator

CCExtractor CI platform finished running the test files on linux. Below is a summary of the test results, when compared to test for commit 2028754...:
Report Name Tests Passed
Broken 13/13
CEA-708 14/14
DVB 7/7
DVD 3/3
DVR-MS 2/2
General 25/27
Hardsubx 1/1
Hauppage 3/3
MP4 3/3
NoCC 10/10
Options 81/86
Teletext 21/21
WTV 13/13
XDS 34/34

Your PR breaks these cases:

  • ccextractor --autoprogram --out=ttxt --latin1 --ucla dab1c1bd65...
  • ccextractor --out=srt --latin1 --autoprogram 29e5ffd34b...
  • ccextractor --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsnotbefore 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsnotafter 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsforatleast 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsforatmost 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...

Congratulations: Merging this PR would fix the following tests:

  • ccextractor --autoprogram --out=srt --latin1 --quant 0 85271be4d2..., Last passed: Never
  • ccextractor --out=spupng c83f765c66..., Last passed: Never

It seems that not all tests were passed completely. This is an indication that the output of some files is not as expected (but might be according to you).

Check the result page for more info.

@ccextractor-bot
Copy link
Collaborator

CCExtractor CI platform finished running the test files on windows. Below is a summary of the test results, when compared to test for commit 2028754...:
Report Name Tests Passed
Broken 13/13
CEA-708 14/14
DVB 6/7
DVD 3/3
DVR-MS 2/2
General 25/27
Hardsubx 1/1
Hauppage 3/3
MP4 3/3
NoCC 10/10
Options 81/86
Teletext 21/21
WTV 13/13
XDS 34/34

Your PR breaks these cases:

  • ccextractor --autoprogram --out=srt --latin1 --quant 0 85271be4d2...
  • ccextractor --autoprogram --out=ttxt --latin1 --ucla dab1c1bd65...
  • ccextractor --out=srt --latin1 --autoprogram 29e5ffd34b...
  • ccextractor --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsnotbefore 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsnotafter 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsforatleast 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsforatmost 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...

Congratulations: Merging this PR would fix the following tests:


It seems that not all tests were passed completely. This is an indication that the output of some files is not as expected (but might be according to you).

Check the result page for more info.

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.

[Feature Request] Precise positioning when exporting to Substation Alpha (ASS/SSA)

3 participants