Skip to content

ALE adapter fails to parse files with standard truncated decimal framerates in v0.18.1 #1983

@tomviner

Description

@tomviner

Problem

The ALE adapter fails to parse ALE files with trucated decimal framerates (e.g., 23.976, 29.97) in OpenTimelineIO v0.18.1, while the same files parse successfully in v0.17.0. I believe this is quite common for ALEs, as seen in the ALE adapter sample files.

Reproduction

Using uvx to execute OpenTimelineIO's otiocat command against the otio-ale-adapter plugin's test file:

Fails in v0.18.1:

$ uvx --with OpenTimelineIO-Plugins==0.18.1 --from OpenTimelineIO==0.18.1 \
  otiocat ./otio-ale-adapter/tests/sample_data/sampleUHD.ale

ValueError: SMPTE timecode does not support this rate
ALEParseError: Invalid Start timecode: 14:40:02:11

Works in v0.17.0:

$ uvx --with OpenTimelineIO-Plugins==0.17 --from OpenTimelineIO==0.17 \
  otiocat ./otio-ale-adapter/tests/sample_data/sampleUHD.ale

{"OTIO_SCHEMA": "SerializableCollection.1", ...}

Sample file:

$ grep FPS ./otio-ale-adapter/tests/sample_data/sampleUHD.ale
FPS	23.976

Using the exact fractional value works:

$ grep FPS sampleUHD-long-fps.ale
FPS	23.976023976023978
$ uvx --with OpenTimelineIO-Plugins==0.18.1 --from OpenTimelineIO==0.18.1 \
  otiocat sampleUHD-long-fps.ale

{"OTIO_SCHEMA": "SerializableCollection.1", ...}

Root Cause

Introduced by #1477. In rationalTime.cpp:195, from_timecode() validates rates using exact floating-point comparison:

RationalTime::from_timecode(std::string const& timecode, double rate, ...)
{
    if (!RationalTime::is_smpte_timecode_rate(rate))  // Line 195
        // Throws error

bool RationalTime::is_smpte_timecode_rate(double fps)
{
    return std::find(smpte_timecode_rates.begin(), smpte_timecode_rates.end(), fps) != end;
}

Since 23.976 != 24000.0/1001.0 (23.976023976...), validation fails. This exact equality check is fragile given the well-known issues with floating-point representation and comparison.

The codebase includes nearest_smpte_timecode_rate() for tolerance-based matching, but it's not used in from_timecode() and other helpers.

Proposed Solution

I think the best approach would be to modify from_timecode() and other helpers to go back to using tolerance-based matching instead of exact comparison.

The alternative is that every usage of from_timecode() (like these calls, and other plugins, and thirdparty code) needs to first call nearest_smpte_timecode_rate() and get a precise fps value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions