MCPcopy Create free account
hub / github.com/Breakthrough/PySceneDetect / test_vfr_otio_export

Function test_vfr_otio_export

tests/test_vfr.py:300–354  ·  view source on GitHub ↗

OTIO export for VFR video should have no spurious float precision and correct timecodes. Regression test for the float precision bug where seconds * frame_rate could produce values like 90.00000000000001 instead of 90.0 for CFR video.

(test_vfr_video: str, backend: str, tmp_path)

Source from the content-addressed store, hash-verified

298
299@pytest.mark.parametrize("backend", ["pyav", "opencv"])
300def test_vfr_otio_export(test_vfr_video: str, backend: str, tmp_path):
301 """OTIO export for VFR video should have no spurious float precision and correct timecodes.
302
303 Regression test for the float precision bug where seconds * frame_rate could produce
304 values like 90.00000000000001 instead of 90.0 for CFR video.
305 """
306 exit_code, _ = invoke_cli(
307 [
308 "-i",
309 test_vfr_video,
310 "-b",
311 backend,
312 "-o",
313 str(tmp_path),
314 "detect-content",
315 "time",
316 "--end",
317 "10s",
318 "save-otio",
319 ]
320 )
321 assert exit_code == 0
322
323 otio_path = next(tmp_path.glob("*.otio"))
324 data = json.loads(otio_path.read_text())
325 frame_rate = data["global_start_time"]["rate"]
326 one_frame_secs = 1.0 / frame_rate
327
328 clips = data["tracks"]["children"][0]["children"]
329 assert len(clips) >= len(EXPECTED_SCENES_VFR)
330
331 for i, (clip, (exp_start_tc, exp_end_tc)) in enumerate(
332 zip(clips, EXPECTED_SCENES_VFR, strict=False)
333 ):
334 sr = clip["source_range"]
335 start_val = sr["start_time"]["value"]
336 dur_val = sr["duration"]["value"]
337
338 # No spurious float precision: values should have at most 6 decimal places.
339 assert round(start_val, 6) == start_val, (
340 f"[{backend}] Clip {i + 1} start_time.value has excess precision: {start_val!r}"
341 )
342 assert round(dur_val, 6) == dur_val, (
343 f"[{backend}] Clip {i + 1} duration.value has excess precision: {dur_val!r}"
344 )
345
346 # Values should round-trip to the expected timecodes within 1 frame.
347 start_secs = start_val / frame_rate
348 end_secs = (start_val + dur_val) / frame_rate
349 assert abs(start_secs - _tc_to_secs(exp_start_tc)) < one_frame_secs, (
350 f"[{backend}] Clip {i + 1} start: {start_secs:.4f}s vs expected {exp_start_tc}"
351 )
352 assert abs(end_secs - _tc_to_secs(exp_end_tc)) < one_frame_secs, (
353 f"[{backend}] Clip {i + 1} end: {end_secs:.4f}s vs expected {exp_end_tc}"
354 )
355
356
357def test_vfr_edl_export(test_vfr_video: str, tmp_path):

Callers

nothing calls this directly

Calls 2

invoke_cliFunction · 0.90
_tc_to_secsFunction · 0.85

Tested by

no test coverage detected