Source code for camtasia.timing
"""Camtasia timing system: tick conversions, rational scalars, and duration formatting.
Camtasia uses an editRate of 705,600,000 ticks per second — chosen to be evenly
divisible by common frame rates (30, 60 fps) and audio sample rates (44100, 48000 Hz).
"""
from __future__ import annotations
from fractions import Fraction
EDIT_RATE: int = 705_600_000
"""Ticks per second in Camtasia's timing system."""
[docs]
def seconds_to_ticks(seconds: float) -> int:
"""Convert seconds to editRate ticks.
Args:
seconds: Duration in seconds.
Returns:
Integer tick count.
"""
return round(seconds * EDIT_RATE)
[docs]
def ticks_to_seconds(ticks: int) -> float:
"""Convert editRate ticks to seconds.
Args:
ticks: Tick count.
Returns:
Duration in seconds.
"""
return ticks / EDIT_RATE
[docs]
def parse_scalar(value: int | float | str | Fraction) -> Fraction:
"""Parse a scalar value from Camtasia JSON into a Fraction.
Camtasia stores speed scalars as integers (1), floats, or string
fractions ('51/101').
Args:
value: Scalar as int, float, string fraction, or Fraction.
Returns:
Exact rational representation.
"""
if isinstance(value, Fraction):
return value
if isinstance(value, str):
return Fraction(value)
return Fraction(value).limit_denominator(10_000)
[docs]
def scalar_to_string(scalar: Fraction) -> str | int:
"""Format a scalar Fraction for Camtasia JSON serialization.
Args:
scalar: Rational scalar value.
Returns:
Integer 1 if the scalar is exactly 1, otherwise 'numerator/denominator'.
"""
if scalar == 1:
return 1
return f"{scalar.numerator}/{scalar.denominator}"
[docs]
def speed_to_scalar(speed: float) -> Fraction:
"""Convert a human-readable speed multiplier to a Camtasia scalar.
A scalar represents timeline_duration / source_duration. Faster playback
(speed > 1) means less timeline per source, so scalar = 1/speed.
Args:
speed: Human speed multiplier (e.g. 2.0 for 2x playback).
Returns:
Rational scalar for Camtasia JSON.
"""
return Fraction(1, 1) / Fraction(speed).limit_denominator(10_000)
[docs]
def scalar_to_speed(scalar: Fraction) -> float:
"""Convert a Camtasia scalar to a human-readable speed multiplier.
Args:
scalar: Rational scalar from Camtasia JSON.
Returns:
Speed multiplier (e.g. 2.0 for 2x playback).
"""
return float(Fraction(1, 1) / scalar)