You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
BUG: SCC timecodes use hardcoded 29.97 FPS instead of actual stream frame rate #2145
print_scc_time() in src/lib_ccx/ccx_common_timing.c computes SCC timecode frame numbers using a hardcoded literal 29.97, completely ignoring the current_fps global that exists in the same file and is dynamically updated from stream NAL data at runtime.
Any SCC output from a 24fps, 25fps, 30fps, or 50/60fps source will have incorrect frame numbers in every timecode, making the output non-standard and potentially rejected by downstream validators.
Technically, the only true SCC (EIA-608) framerate is 29.97, and even if you delivered a SCC file to be used to accompany a 23.98fps movie, you were still expected to deliver the SCC at 29.97... because back in the day, SCC had one job and one job only - authoring NTSC DVDs for Sonic Solutions SCENARIST DVD authoring software for Region 1 - and the Picture User Data headers for both soft and hard telecine end up as 29.97 on disc.
Now, two decades later, a lot has changed and the use cases for SCC have expanded beyond the original DVD-Video remit, but there is still an industry practice that SCCs can use a 29.97 timecode even if the base media uses other frame rates, unless specifically overridden and communicated between parties. Telestream, who know a lot about pro-workflows for closed captioning claim...
"For best compatibility, SCC files should almost always be exported in 29.97 time code mode. The main consideration is whether to choose 29.97 drop frame (DF) or 29.97 non-drop frame (NDF) time code. As long as the recipient knows which mode the SCC is, it should work fine regardless of whether the video itself is DF or NDF. Trouble can arise if you export the SCC in one mode, but the recipient assumes it is in the opposite mode. This trouble can manifest as timing issues, such as the captions drifting out of sync (slowly becoming earlier or later).
When someone asks for a "23.98 fps SCC" file, most of the time, what they really want is a 29.97 NDF (non-drop frame) .scc file. Likewise, if they provide to you a so called "23.98 fps SCC file", it's probably a 29.97 NDF .scc file. Standard industry best practice is to combine a 29.97 NDF .scc file with a 23.98 fps video file. Captioning systems are equipped to internally handle this conversion properly."
That doesn't mean that ccextractor should not support other framerates, but it does muddy the waters a little. Thus there are two camps "29.97-only-let-the-next-system-deal-with-it" and "same-as-media" camps... and that leaves a challenge for ccextractor's expected default behavior (including potential DF, NDF). I also appreciate that Telestream's FAQ may be one focused on pro-deliveries to DVD authoring systems, and is likely US-centric.
Non-29.97 is a perfectly reasonable modern SCC use-case, especially now DVD-Video mastering is kinda solved, film is now transported progressive, non-NTSC markets do exist and for the support of video players that are unaware of the legacy convention.
It is the age-old question of convention vs technical frame-level accuracy. The two downsides if you get it wrong are:
+/- 4 frame accuracy for the start frame of a caption cue
cue starting in the {25...29} range being treated as out-of-range
Sophisticated authoring systems (and IIRC maybe even mediainfo run agains an SCC input?) can include heuristic checks, sometimes using maximum known frame number or even statistical frequency analysis to count the number of timecodes that fit only into one of {0..23}, {0..24} and {0..29} to make a reasonable guess as to the actual frame rate of an SCC input files. With enough video frames, if no frames land in the {25-29} range, you can guess it is likely to be film or PAL.
I offer no opinion, other than quoting Telestream's statement on 29.97 and highlighting that there are complexities around choosing a sensible default behavior, while still offering flexibility for those requiring "same-as-media" workflows.
Thank you for the detailed context — that Telestream reference is really helpful and I wasn't
aware of the historical convention around 29.97 as the universal SCC delivery standard.
That said, I think we agree on the core: the hardcoded literal is still a problem, the question
is just what the default behavior should be and whether the user should have control over it.
A reasonable middle ground might be:
Keep 29.97 as the default (honoring the industry convention you described)
Add a flag like --scc-fps or respect current_fps when explicitly set by the user
This way "29.97-only-let-the-next-system-deal-with-it" workflows are unchanged, while
"same-as-media" users get an opt-in path
Would that direction make sense to the maintainers? Happy to draft a PR along those lines
if there's appetite for it.
Thanks for digging that up! Looks like --scc-framerate from #1916 already covers the
use case I was describing. I'll test it against a 25fps source to verify the output
timecodes are correct end-to-end.
If the flag works as documented, I'll close this issue. Apologies for the noise —
I was looking at the source and missed that the CLI option existed.
current_fps = auto-detected from stream (used by this fix)
This ensures correct SCC timecodes when the stream frame rate is detected, while --scc-framerate remains available for explicit control.
Note: As noted in the comments, industry convention is to use 29.97 for SCC regardless of source frame rate. This fix provides the same-as-media behavior for users who need it, while the default (when --scc-framerate is not used and stream fps is not detected) remains 29.97.
Thanks @Atul-Chahar for the quick PR! Glad the issue was worth fixing.
@bbgdzxng1 your breakdown of the --scc-framerate path vs the print_scc_time()
path was really clarifying — good to know they're separate code paths and both
now covered.
@Atul-Chahar and @Varadraj75 I do love hate to nit-pick. What do people feel about updating the online help from...
$ ccextractor --help | grep "scc-framerate"
--scc-framerate <fps>
Set the frame rate for SCC (Scenarist Closed Caption) input files.
Valid values: 29.97 (default), 24, 25, 30
Example: --scc-framerate 25
- Set the frame rate for SCC (Scenarist Closed Caption) input files.
+ Set the frame rate for Scenarist Closed Captioning (SCC) input and/or output encoding.
...given that "the --scc-framerate option now affects both input parsing AND output encoding"
Just a thought / doc update. Feels like the command line help suggests it is input specific only, and thus potentially misleading given the #2146 update.
Anyone got any better phrasing?
And if we are I am getting really nit-picky, should 23.98 be an alias for 24 as an enumerated "Valid value"? 23.98 is notable by its absence, but 29.97 and 30 are both explicitly specified, but probably result in the same eventual timing, give or take a 1000/1001 frame sync?
Feel free to ignore this pedant. I'm just a dumb user.
On the help text, agree it's misleading. Something like:
--scc-framerate <fps>
Set the frame rate for Scenarist Closed Captioning (SCC) input parsing
and output encoding.
Valid values: 23.98, 29.97 (default), 24, 25, 30
Example: --scc-framerate 25
On the 23.98 alias — definitely worth adding. 29.97 and 30 are both listed
explicitly so 23.98 deserves the same treatment. Under the hood 23.98 = 24000/1001
just as 29.97 = 30000/1001, so it's a natural pair.
I can put together a small follow-up PR covering both — updated help text and
23.98 as a valid --scc-framerate value. Would that be welcome?
@cfsmp3 I looked into this issue and found that the hardcoded 29.97 is still present on the current master.
I’d like to work on this, but before starting I wanted to confirm the expected behaviour around current_fps vs --scc-framerate.
Would it be okay if I take this up and work on the fix once the expected precedence is confirmed?
Opened #2406. It uses the detected current_fps in the C and Rust 708 SCC writers, which is what the review on #2146 asked for. --scc-framerate is unchanged and still covers the 608 encoder and SCC input parsing. The PR has a 25 fps sample and the before/after SCC output.
Activity
bbgdzxng1 commentedon Feb 26, 2026
This one is a bit of a tricky one.
Technically, the only true SCC (EIA-608) framerate is 29.97, and even if you delivered a SCC file to be used to accompany a 23.98fps movie, you were still expected to deliver the SCC at 29.97... because back in the day, SCC had one job and one job only - authoring NTSC DVDs for Sonic Solutions SCENARIST DVD authoring software for Region 1 - and the Picture User Data headers for both soft and hard telecine end up as 29.97 on disc.
Now, two decades later, a lot has changed and the use cases for SCC have expanded beyond the original DVD-Video remit, but there is still an industry practice that SCCs can use a 29.97 timecode even if the base media uses other frame rates, unless specifically overridden and communicated between parties. Telestream, who know a lot about pro-workflows for closed captioning claim...
https://support.telestream.net/s/article/SCC-Files-and-23-98-fps-or-Other-Frame-Rates
That doesn't mean that ccextractor should not support other framerates, but it does muddy the waters a little. Thus there are two camps "29.97-only-let-the-next-system-deal-with-it" and "same-as-media" camps... and that leaves a challenge for ccextractor's expected default behavior (including potential DF, NDF). I also appreciate that Telestream's FAQ may be one focused on pro-deliveries to DVD authoring systems, and is likely US-centric.
Non-29.97 is a perfectly reasonable modern SCC use-case, especially now DVD-Video mastering is kinda solved, film is now transported progressive, non-NTSC markets do exist and for the support of video players that are unaware of the legacy convention.
It is the age-old question of convention vs technical frame-level accuracy. The two downsides if you get it wrong are:
Sophisticated authoring systems (and IIRC maybe even mediainfo run agains an SCC input?) can include heuristic checks, sometimes using maximum known frame number or even statistical frequency analysis to count the number of timecodes that fit only into one of {0..23}, {0..24} and {0..29} to make a reasonable guess as to the actual frame rate of an SCC input files. With enough video frames, if no frames land in the {25-29} range, you can guess it is likely to be film or PAL.
I offer no opinion, other than quoting Telestream's statement on 29.97 and highlighting that there are complexities around choosing a sensible default behavior, while still offering flexibility for those requiring "same-as-media" workflows.
Varadraj75 commentedon Feb 26, 2026
Thank you for the detailed context — that Telestream reference is really helpful and I wasn't
aware of the historical convention around 29.97 as the universal SCC delivery standard.
That said, I think we agree on the core: the hardcoded literal is still a problem, the question
is just what the default behavior should be and whether the user should have control over it.
A reasonable middle ground might be:
--scc-fpsor respectcurrent_fpswhen explicitly set by the user"same-as-media" users get an opt-in path
Would that direction make sense to the maintainers? Happy to draft a PR along those lines
if there's appetite for it.
bbgdzxng1 commentedon Feb 26, 2026
BTW - I have not tested #1916
"SCC Output Frame Rate: The --scc-framerate option now affects both input parsing AND output encoding (was hardcoded to 29.97fps)"
Varadraj75 commentedon Feb 26, 2026
Thanks for digging that up! Looks like --scc-framerate from #1916 already covers the
use case I was describing. I'll test it against a 25fps source to verify the output
timecodes are correct end-to-end.
If the flag works as documented, I'll close this issue. Apologies for the noise —
I was looking at the source and missed that the CLI option existed.
fix: use dynamic current_fps instead of hardcoded 29.97 in SCC timecodes
Atul-Chahar commentedon Feb 26, 2026
PR Submitted
I've created a PR that addresses this issue: #2146
Verification:
How they work together:
This ensures correct SCC timecodes when the stream frame rate is detected, while --scc-framerate remains available for explicit control.
Note: As noted in the comments, industry convention is to use 29.97 for SCC regardless of source frame rate. This fix provides the same-as-media behavior for users who need it, while the default (when --scc-framerate is not used and stream fps is not detected) remains 29.97.
Varadraj75 commentedon Feb 27, 2026
Thanks @Atul-Chahar for the quick PR! Glad the issue was worth fixing.
@bbgdzxng1 your breakdown of the --scc-framerate path vs the print_scc_time()
path was really clarifying — good to know they're separate code paths and both
now covered.
bbgdzxng1 commentedon Feb 27, 2026
@Atul-Chahar and @Varadraj75 I do
lovehate to nit-pick. What do people feel about updating the online help from......given that "the --scc-framerate option now affects both input parsing AND output encoding"
Just a thought / doc update. Feels like the command line help suggests it is input specific only, and thus potentially misleading given the #2146 update.
Anyone got any better phrasing?
And if
we areI am getting really nit-picky, should 23.98 be an alias for 24 as an enumerated "Valid value"? 23.98 is notable by its absence, but 29.97 and 30 are both explicitly specified, but probably result in the same eventual timing, give or take a 1000/1001 frame sync?Feel free to ignore this pedant. I'm just a dumb user.
Varadraj75 commentedon Feb 28, 2026
Both are great points @bbgdzxng1 —
On the help text, agree it's misleading. Something like:
On the 23.98 alias — definitely worth adding. 29.97 and 30 are both listed
explicitly so 23.98 deserves the same treatment. Under the hood 23.98 = 24000/1001
just as 29.97 = 30000/1001, so it's a natural pair.
I can put together a small follow-up PR covering both — updated help text and
23.98 as a valid
--scc-frameratevalue. Would that be welcome?feat: add 23.98fps as valid --scc-framerate value and fix help text
feat: add 23.98fps as valid --scc-framerate value and fix help text
bbgdzxng1 commentedon Feb 28, 2026
@Varadraj75, from an end-user perspective, I think your proposal in the PR covers both nits. Thank-you.
✅ Good catch on
"23.98" | "23.976"too.Varadraj75 commentedon Feb 28, 2026
#2150 has been merged, covering the two follow-up improvements raised by
@bbgdzxng1 — 23.98 as a valid
--scc-frameratealias and clarified help text.The original fix (replacing hardcoded
29.97withcurrent_fpsinprint_scc_time()) is tracked in #2146. I'll close this issue once that merges.fix: use dynamic current_fps instead of hardcoded 29.97 in SCC timecodes
NaitikVerma6776 commentedon Oct 8, 2026
@cfsmp3 I looked into this issue and found that the hardcoded
29.97is still present on the current master.I’d like to work on this, but before starting I wanted to confirm the expected behaviour around
current_fpsvs--scc-framerate.Would it be okay if I take this up and work on the fix once the expected precedence is confirmed?
harshalsp07 commentedon Oct 20, 2026
Opened #2406. It uses the detected
current_fpsin the C and Rust 708 SCC writers, which is what the review on #2146 asked for.--scc-framerateis unchanged and still covers the 608 encoder and SCC input parsing. The PR has a 25 fps sample and the before/after SCC output.