Source code for braidio

"""braidio — weave narration with extracted media segments into productions.

Braid two kinds of strand into one production: authored **narration** (TTS —
single voice or a cycled pool) and extracted **segments** of source media (song
clips, audiobook passages, news, SFX). The result renders to an audiovisual
object.

This is the **functional core** (pure Python over files + numbers; deps:
``mixing``, ``elevenlabs``, and ``ffmpeg`` on PATH). An optional nw-app layer
(graph bodies, transforms, provenance / partial re-render) will be added on top
and imported only when ``nw`` is available — ``import braidio`` never requires
it.

Extracted from the Hamilton lyrics-podcast; the extraction is designed in
Hamilton#18 (the epic) and Hamilton#28 (placement + naming). Those numbers are
in the *Hamilton* repo — braidio has its own #18 about something else.
"""

from __future__ import annotations

# --- composition model ---
from braidio.script import (  # noqa: F401
    Script,
    Narration,
    SegmentBeat,
    Dialogue,
    SceneBreak,
    SCENE_MARKERS,
    Beat,
    narration_segments,
)

# --- rights profiles ---
from braidio.rights import (  # noqa: F401
    Profile,
    DEFAULT_PROFILE,
    RightsPolicy,
    RenderPlan,
    PlannedBeat,
    plan_production,
    clip_plays_under,
    rights_are_publishable,
    RightsViolation,
    find_verbatim_text,
    content_violations,
    segment_is_publishable,
    PUBLISHABLE_CLIP_RIGHTS,
)

# --- segment sources (reference -> cuttable window) ---
from braidio.sources import (  # noqa: F401
    SegmentSource,
    ResolvedSegment,
    Segment,
    TimedLine,
    TimedLineSegmentSource,
    find_segment,
    load_timing,
    cut_quote,
)

# --- narration synthesis ---
from braidio.tts import (  # noqa: F401
    narrate,
    text_to_dialogue,
    resolve_voice_id,
    DEFAULT_VOICE_ID,
    DEFAULT_MODEL_ID,
    DEFAULT_VOICE_SETTINGS,
    VOICE_ENV_VAR,
)

# --- cost model (ElevenLabs TTS spend) ---
from braidio.cost import (  # noqa: F401
    estimate_cost,
    tts_cost_usd,
    billable_chars,
    usd_per_1k_chars,
    CostRollup,
    CostLine,
    RATE_ENV_VAR,
    DEFAULT_USD_PER_1K_CHARS,
)
from braidio.conversation import (  # noqa: F401
    ConversationCast,
    DEFAULT_CAST,
    render_dialogue,
    render_turns_sequential,
)
from braidio.delivery import (  # noqa: F401
    Delivery,
    DELIVERIES,
    BASELINE,
    V2_TUNED,
    V2_AGGRESSIVE,
    V2_PRESENTER,
    V2_NARRATOR,
    V3_NATURAL,
    V3_CREATIVE,
    NARRATION,
    CONVERSATIONAL,
)

# --- multi-voice casting ---
from braidio.multivoice import (  # noqa: F401
    Voice,
    POOL_4,
    POOL_MANY,
    POOLS,
    strip_markup,
    split_segments,
    assign_voices,
    group_turns,
    render_multivoice,
)

# --- configuration ---
from braidio.weave_config import WeaveConfig, PRESETS  # noqa: F401

# --- music bed (instrumental underscore) ---
from braidio.music import (  # noqa: F401
    MusicBed,
    bed_for_intensity,
    BED_GAIN_BY_INTENSITY,
)

# --- structural music (stings at scene breaks, fade-to-spotlight) ---
from braidio.structure import (  # noqa: F401
    Sting,
    MusicStructure,
    DEFAULT_STRUCTURE,
)

# --- ready-made format templates (standard-named presets) ---
from braidio.formats import (  # noqa: F401
    Format,
    render_format,
    describe_asset_application,
    FORMATS,
    SOLO_EXPLAINER,
    DEEP_DIVE,
    INTERVIEW,
    SONG_EXPLODER,
    PANEL,
    DEBATE,
    DOCUMENTARY_VO,
)

# --- composition + weaving (audio) ---
from braidio.compose import compose_narration  # noqa: F401
from braidio.render import render_production  # noqa: F401
from braidio.timeline import (  # noqa: F401
    BeatSpan,
    TimelineBreakdown,
    build_timeline,
)

# --- captions (pure: authored text + the render's own timeline, no ASR) ---
from braidio.captions import (  # noqa: F401
    Cue,
    captions_for,
    cues_for,
    format_srt,
)

# --- text prep + style audit (reusable script helpers) ---
from braidio.textprep import clean_ocr, strip_speaker_labels  # noqa: F401
from braidio.style import (  # noqa: F401
    Finding,
    PLATITUDE_PATTERNS,
    audit_platitudes,
    platitude_rate,
)
from braidio.weave import (  # noqa: F401
    TimelineItem,
    extract_padded,
    weave_timeline,
    layout_starts,
    duration_s,
)

# --- production kinds (pure) ---
from braidio.kinds import WeaveKind  # noqa: F401

# --- version ---------------------------------------------------------------
# Read from installed distribution metadata rather than written literally here:
# CI bumps the version in pyproject.toml and pushes back, so a literal in this
# file would silently drift from the released version. `"unknown"` is the honest
# answer for a source tree that was never installed (not even editable).
from importlib.metadata import PackageNotFoundError, version as _dist_version

try:
    __version__ = _dist_version("braidio")
except PackageNotFoundError:  # pragma: no cover - source tree, not installed
    __version__ = "unknown"

# --- optional nw-app layer (graph bodies + provenance) --------------------
# Registers braidio's domain/render body schemas with lacing and exposes the
# provenance / partial-re-render helpers. Guarded: `import braidio` never needs
# lacing/nw. `HAS_GRAPH` / `HAS_NW` report what's available.
HAS_GRAPH = False
HAS_NW = False
try:  # needs lacing
    from braidio import bodies  # noqa: F401  (registers schemas)
    from braidio.provenance import (  # noqa: F401
        record_render,
        stale_after,
        descendants_of,
    )

    HAS_GRAPH = True
except ImportError:  # pragma: no cover - optional dep
    pass
try:  # needs nw
    from braidio.project import Project  # noqa: F401
    from braidio import transforms  # noqa: F401  (registers braidio's nw.Transforms)
    from braidio.transforms import weave_project  # noqa: F401
    from braidio.genre import COMMENTARY_WEAVE  # noqa: F401  (registers the nw.Genre)

    HAS_NW = True
except ImportError:  # pragma: no cover - optional dep
    pass


[docs] def skills_dir(): """Path to the agent skills that ship with braidio. They install with the package, so an agent host can be pointed at them without cloning the repo:: ln -s "$(python -c 'import braidio; print(braidio.skills_dir())')/braidio" \\ ~/.claude/skills/braidio """ from pathlib import Path return Path(__file__).parent / "data" / "skills"
# --- optional video layer (Ken Burns film over stills) -------------------- # `braidio.video` itself imports cleanly with nothing extra installed — its # dependencies (burns, pillow) are imported inside the functions that need them, # so the pure planners stay usable. `HAS_VIDEO` reports whether the *render* path # is actually available; `braidio.video.missing_dependencies()` names what's absent. from braidio.video import HAS_VIDEO # noqa: F401,E402 __all__ = [ "__version__", # production kinds "WeaveKind", "HAS_GRAPH", "HAS_NW", "HAS_VIDEO", "skills_dir", # captions "Cue", "captions_for", "cues_for", "format_srt", # script "Script", "Narration", "SegmentBeat", "Dialogue", "SceneBreak", "SCENE_MARKERS", "Sting", "MusicStructure", "DEFAULT_STRUCTURE", "Beat", "narration_segments", # rights "Profile", "DEFAULT_PROFILE", "RightsPolicy", "RenderPlan", "PlannedBeat", "plan_production", "clip_plays_under", "rights_are_publishable", "RightsViolation", "find_verbatim_text", "content_violations", "segment_is_publishable", "PUBLISHABLE_CLIP_RIGHTS", # render "render_production", # sources "SegmentSource", "ResolvedSegment", "Segment", "TimedLine", "TimedLineSegmentSource", "find_segment", "load_timing", "cut_quote", # tts "narrate", "resolve_voice_id", "DEFAULT_VOICE_ID", "DEFAULT_MODEL_ID", "DEFAULT_VOICE_SETTINGS", "VOICE_ENV_VAR", # cost (ElevenLabs TTS spend) "estimate_cost", "tts_cost_usd", "billable_chars", "usd_per_1k_chars", "CostRollup", "CostLine", "RATE_ENV_VAR", "DEFAULT_USD_PER_1K_CHARS", # delivery "Delivery", "DELIVERIES", "BASELINE", "V2_TUNED", "V2_AGGRESSIVE", "V2_PRESENTER", "V2_NARRATOR", "V3_NATURAL", "V3_CREATIVE", "NARRATION", "CONVERSATIONAL", # multivoice "Voice", "POOL_4", "POOL_MANY", "POOLS", "strip_markup", "split_segments", "assign_voices", "group_turns", "render_multivoice", # config "WeaveConfig", "PRESETS", # music bed "MusicBed", "bed_for_intensity", "BED_GAIN_BY_INTENSITY", # formats (ready-made templates) "Format", "render_format", "describe_asset_application", "FORMATS", "SOLO_EXPLAINER", "DEEP_DIVE", "INTERVIEW", "SONG_EXPLODER", "PANEL", "DEBATE", "DOCUMENTARY_VO", # compose + weave "compose_narration", "TimelineItem", "extract_padded", "weave_timeline", "layout_starts", "duration_s", # timeline breakdown "BeatSpan", "TimelineBreakdown", "build_timeline", # text prep + style audit "clean_ocr", "strip_speaker_labels", "Finding", "PLATITUDE_PATTERNS", "audit_platitudes", "platitude_rate", ]