Source code for camtasia.types

"""Strong types for the pycamtasia library."""
from __future__ import annotations
from enum import Enum, IntEnum
from typing import Literal

__all__ = [
    'ClipType', 'EffectName', 'TransitionType', 'BehaviorPreset',
    'BehaviorInnerName', 'BlendMode', 'ValidationLevel', 'MediaType',
    'MaskShape', 'CalloutShape', 'CalloutKind', 'InterpolationType',
    'TrackType', 'EffectCategory', 'Alignment', 'ReportFormat',
    '_RGBADict', 'DropShadowParams', 'RoundCornersParams', 'ColorAdjustmentParams',
    'EffectDict', 'TransitionDict', 'ClipSummary', 'HealthCheckResult',
    'CompactResult', 'TimelineSummary', 'ScreenplayBuildResult',
]

# Effect categories
EffectCategory = Literal['', 'categoryVisualEffects', 'categoryAudioEffects', 'categoryCursorEffects', 'categoryClickEffects']

# Alignment values for CaptionAttributes
Alignment = Literal[0, 1, 2]  # 0 = center, 1 = left, 2 = right

# Export formats
ReportFormat = Literal['markdown', 'json']


[docs] class ClipType(str, Enum): """Camtasia clip types.""" AUDIO = 'AMFile' VIDEO = 'VMFile' IMAGE = 'IMFile' SCREEN_VIDEO = 'ScreenVMFile' SCREEN_IMAGE = 'ScreenIMFile' CALLOUT = 'Callout' GROUP = 'Group' UNIFIED_MEDIA = 'UnifiedMedia' STITCHED_MEDIA = 'StitchedMedia' PLACEHOLDER = 'PlaceholderMedia'
[docs] class EffectName(str, Enum): """Known Camtasia effect names.""" DROP_SHADOW = 'DropShadow' ROUND_CORNERS = 'RoundCorners' GLOW = 'Glow' MOTION_BLUR = 'MotionBlur' MASK = 'Mask' COLOR_ADJUSTMENT = 'ColorAdjustment' SPOTLIGHT = 'Spotlight' LUT_EFFECT = 'LutEffect' EMPHASIZE = 'Emphasize' MEDIA_MATTE = 'MediaMatte' BLEND_MODE = 'BlendModeEffect' SOURCE_EFFECT = 'SourceEffect' CURSOR_MOTION_BLUR = 'CursorMotionBlur' CURSOR_SHADOW = 'CursorShadow' CURSOR_PHYSICS = 'CursorPhysics' LEFT_CLICK_SCALING = 'LeftClickScaling' VST_NOISE_REMOVAL = 'VSTEffect-DFN3NoiseRemoval'
[docs] class TransitionType(str, Enum): """Known Camtasia transition types.""" CARD_FLIP = 'CardFlip' FADE = 'Fade' FADE_THROUGH_BLACK = 'FadeThroughBlack' GLITCH3 = 'Glitch3' LINEAR_BLUR = 'LinearBlur' PAINT_ARCS = 'PaintArcs' SLIDE_LEFT = 'SlideLeft' SLIDE_RIGHT = 'SlideRight' SPHERICAL_SPIN = 'SphericalSpin' STRETCH = 'Stretch'
[docs] class BehaviorPreset(str, Enum): """Known behavior animation presets.""" REVEAL = 'reveal' SLIDING = 'sliding' FADE = 'fade' FLY_IN = 'flyIn' POP_UP = 'popUp' PULSATING = 'pulsating' SHIFTING = 'shifting'
[docs] class BehaviorInnerName(str, Enum): """Inner animation names used in GenericBehaviorEffect in/center/out phases.""" # In-phase animations FADE_IN = 'fadeIn' REVEAL = 'reveal' SLIDING = 'sliding' FLY_IN = 'flyIn' GROW = 'grow' HINGE = 'hinge' # Out-phase animations FADE_OUT = 'fadeOut' FLY_OUT = 'flyOut' SHRINK = 'shrink' SHIFTING = 'shifting' # Center-phase animations NONE = 'none' TREMBLE = 'tremble' PULSATE = 'pulsate'
[docs] class BlendMode(IntEnum): """Blend mode values for BlendModeEffect.""" NORMAL = 16 MULTIPLY = 3
# Add more as discovered from Camtasia projects
[docs] class MaskShape(IntEnum): """Mask shape values.""" RECTANGLE = 0 ELLIPSE = 1
# Add more as discovered
[docs] class CalloutShape(str, Enum): """Callout annotation shapes (verified against 93 TechSmith samples).""" EMPTY = '' TEXT = 'text' TEXT_RECTANGLE = 'text-rectangle' TEXT_ARROW2 = 'text-arrow2' ARROW = 'arrow' SHAPE_RECTANGLE = 'shape-rectangle' SHAPE_ELLIPSE = 'shape-ellipse' SHAPE_TRIANGLE = 'shape-triangle'
[docs] class InterpolationType(str, Enum): """Keyframe interpolation types.""" LINEAR = 'linr' EASE_IN_OUT = 'eioe' SPRING = 'sprg' BOUNCE = 'bnce'
[docs] class CalloutKind(str, Enum): """Callout kind identifiers.""" REMIX = 'remix' WIN_BLUR = 'TypeWinBlur'
[docs] class TrackType(str, Enum): """Track content types (for future use).""" AUDIO = 'audio' VIDEO = 'video' ANNOTATION = 'annotation' MIXED = 'mixed'
[docs] class ValidationLevel(str, Enum): """Validation issue severity levels.""" ERROR = 'error' WARNING = 'warning'
[docs] class MediaType(IntEnum): """Media source types (matches existing MediaType in media_bin).""" Video = 0 Image = 1 Audio = 2
# --------------------------------------------------------------------------- # Internal TypedDicts – raw JSON data shapes (total=False: all keys optional) # --------------------------------------------------------------------------- from typing import Any, TypedDict import sys if sys.version_info >= (3, 11): # pragma: no cover from typing import NotRequired else: # pragma: no cover from typing_extensions import NotRequired from fractions import Fraction class _ClipData(TypedDict, total=False): """Internal structure of a clip's raw JSON data.""" _type: str id: int start: int duration: int mediaStart: int | float | str mediaDuration: int | float | str src: Any scalar: int | float | str parameters: dict[str, Any] effects: list[dict[str, Any]] metadata: dict[str, Any] attributes: dict[str, Any] animationTracks: dict[str, Any] tracks: list[dict[str, Any]] channelNumber: str video: dict[str, Any] audio: dict[str, Any] medias: list[dict[str, Any]] minMediaStart: int | float sourceEffect: dict[str, Any] # 'def' key exists at runtime but can't be declared (Python keyword); # accesses use type: ignore[typeddict-item]. class _EffectData(TypedDict, total=False): """Internal structure of an effect's raw JSON data.""" effectName: str _type: str bypassed: bool category: str parameters: dict[str, Any] metadata: dict[str, Any] start: int duration: int leftEdgeMods: list[dict[str, Any]] rightEdgeMods: list[dict[str, Any]] class _TransitionData(TypedDict, total=False): """Internal structure of a transition's raw JSON data.""" name: str duration: int leftMedia: int rightMedia: int attributes: dict[str, Any] class _BehaviorPhaseData(TypedDict, total=False): """Internal structure of a behavior phase dict.""" attributes: dict[str, Any] parameters: dict[str, Any] class _BehaviorEffectData(TypedDict, total=False): """Internal structure of a GenericBehaviorEffect dict.""" _type: str effectName: str bypassed: bool start: int duration: int metadata: dict[str, Any] # 'in', 'center', 'out' keys exist at runtime but can't be declared # (Python keywords); accesses use type: ignore[typeddict-item]. class _CaptionData(TypedDict, total=False): """Internal structure of caption attributes.""" enabled: bool fontName: str fontSize: int backgroundColor: list[int] foregroundColor: list[int] lang: str alignment: int opacity: float backgroundEnabled: bool # --------------------------------------------------------------------------- # TypedDicts – structured data returned / consumed by the library # --------------------------------------------------------------------------- class _RGBADict(TypedDict): """RGBA color as 0.0-1.0 floats.""" red: float green: float blue: float alpha: NotRequired[float]
[docs] class DropShadowParams(TypedDict, total=False): """Parameters for DropShadow effect.""" angle: float offset: float blur: float opacity: float
[docs] class RoundCornersParams(TypedDict, total=False): """Parameters for RoundCorners effect.""" radius: float
[docs] class ColorAdjustmentParams(TypedDict, total=False): """Parameters for ColorAdjustment effect.""" brightness: float contrast: float saturation: float channel: int shadowRampStart: float shadowRampEnd: float highlightRampStart: float highlightRampEnd: float
[docs] class EffectDict(TypedDict): """Structure of an effect entry in the effects array.""" effectName: str bypassed: bool category: NotRequired[str] parameters: NotRequired[dict]
[docs] class TransitionDict(TypedDict): """Structure of a transition entry.""" name: str duration: int leftMedia: NotRequired[int] rightMedia: NotRequired[int] attributes: NotRequired[dict]
[docs] class ClipSummary(TypedDict): """Summary dict returned by BaseClip.to_dict().""" id: int type: str start_seconds: float duration_seconds: float end_seconds: float source_id: NotRequired[int] effects: NotRequired[list[str]]
[docs] class HealthCheckResult(TypedDict): """Result of Project.health_check().""" healthy: bool errors: list[str] warnings: list[str] structural_issues: list[str] statistics: dict
[docs] class CompactResult(TypedDict): """Result of compact_project().""" orphaned_media_removed: int empty_tracks_removed: int
[docs] class TimelineSummary(TypedDict): """Result of Timeline.to_dict().""" track_count: int total_clip_count: int duration_seconds: float has_clips: bool track_names: list[str]
[docs] class ScreenplayBuildResult(TypedDict): """Result of build_from_screenplay().""" clips_placed: int pauses_added: int total_duration: float