Metadata-Version: 2.4
Name: title-fx
Version: 0.1.0
Summary: 44 cinematic title effects plus 15 stubs for v0.2 3D. Composes text-fx + optional cut-fx.
Project-URL: Homepage, https://github.com/tomastimelock/title-fx
Project-URL: Issues, https://github.com/tomastimelock/title-fx/issues
Author-email: Trollfabriken AITrix AB <dev@trollfabriken.se>
License: MIT
Keywords: animation,cinematic,end-credits,ffmpeg,lower-thirds,motion-graphics,titles,video
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Multimedia :: Video
Requires-Python: >=3.10
Requires-Dist: ffmpeg-python>=0.2
Requires-Dist: numpy>=1.24
Requires-Dist: opencv-python-headless>=4.8
Requires-Dist: pillow>=10.0
Requires-Dist: pydantic>=2.5
Requires-Dist: pyyaml>=6.0
Requires-Dist: text-fx-engine>=0.1
Provides-Extra: all
Requires-Dist: cut-fx>=0.1; extra == 'all'
Provides-Extra: blender
Provides-Extra: cuts
Requires-Dist: cut-fx>=0.1; extra == 'cuts'
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: pytest-cov>=4; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: masks
Requires-Dist: rembg>=2.0; extra == 'masks'
Description-Content-Type: text/markdown

# title-fx

59 cinematic title effects for video — 44 ready, 15 coming in v0.2

[![PyPI version](https://img.shields.io/pypi/v/title-fx)](https://pypi.org/project/title-fx/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![CI](https://github.com/tomastimelock/title-fx/actions/workflows/ci.yml/badge.svg)](https://github.com/tomastimelock/title-fx/actions/workflows/ci.yml)

---

`title-fx` renders cinematic title effects onto video frames: trailer slams, lower thirds,
end-credit rolls, chapter cards, and typographic layouts. It does not perform audio alignment,
beat detection, or transition editing — those are handled by `caption-cast`, `audio-arrange`,
and `cut-fx` respectively.

The 15 `advanced_3d` effects (Blender-rendered extruded text, camera-tracked labels,
depth-of-field focus pulls, and related) are stubbed in v0.1 and will ship fully in v0.2.
Each stub raises `TitleDeferredError` with a clear message so callers can handle or skip
deferred effects deterministically.

This library exists because the Trollfabriken post-production stack needed a reusable,
catalog-driven title engine that could be composed with `cut-fx` for slam cuts and with
`text-fx` for lower-level glyph rendering. It is a first-class package, not a folder
of scripts.

---

## What it solves

| Problem | What title-fx does |
|---|---|
| Trailer titles require material effects (gold, stone, fire) that are awkward to rig per project | 24 named cinematic effects, each with a documented compositing strategy, exposed through a single `apply_title()` call |
| Lower thirds and documentary labels need consistent layout and animation without manual keyframing | `lower_third()` accepts a name/title/role dict and returns a composited frame sequence |
| End credits and chapter cards are copy-pasted per production | `end_credits()` and `chapter_card()` accept plain text lists and render scroll or card sequences with sensible defaults |

---

## Installation

```bash
pip install title-fx
```

With `cut-fx` integration for slam-cut composition:

```bash
pip install "title-fx[cuts]"
```

With subject-segmentation mask support (for `text_behind_subject`, `text_around_object`):

```bash
pip install "title-fx[masks]"
```

Full extras (cuts only — `blender` extra is reserved for v0.2 and is empty in v0.1):

```bash
pip install "title-fx[all]"
```

`ffmpeg` must be available on `PATH`. Install it separately:

- Linux: `sudo apt-get install ffmpeg`
- macOS: `brew install ffmpeg`
- Windows: `choco install ffmpeg` or download from https://ffmpeg.org/download.html

---

## Quick start

### Apply a cinematic trailer title

```python
import title_fx

# Apply "Hero Title Slam" effect — title slams into center with motion blur
result = title_fx.apply_title(
    input_video="scene.mp4",
    text="KINGDOM FALLS",
    effect="hero_title_slam",
    output="out.mp4",
)
```

### Render a lower third

```python
import title_fx

# Documentary lower third for a name/role callout
frames = title_fx.lower_third(
    input_video="interview.mp4",
    name="Dr. Anna Lindqvist",
    role="Marine Biologist",
    effect="documentary_lower_third",
    output="interview_lt.mp4",
    start_sec=4.0,
    duration_sec=3.5,
)
```

### Render a chapter card

```python
import title_fx

# Full-screen chapter card with fade in/out
title_fx.chapter_card(
    chapter_number=2,
    chapter_title="The Long Night",
    duration_sec=3.0,
    output="chapter_02.mp4",
    effect="chapter_card",
)
```

---

## The 59 effects

### Active effects — v0.1 (44)

#### cinematic_trailer (24)

| Slug | Description |
|---|---|
| `trailer_gold_title` | Large metallic gold title with cinematic glow |
| `epic_stone_title` | Heavy stone-textured title with cracks |
| `metal_bevel_title` | Chrome or steel beveled title |
| `fire_ember_title` | Title glows with embers and heat |
| `smoke_title` | Title appears through cinematic smoke |
| `dust_reveal_title` | Trailer title revealed by drifting dust |
| `light_ray_title` | Volumetric rays behind text |
| `lens_flare_title` | Title appears with horizontal anamorphic flare |
| `anamorphic_flare_sweep` | Light sweep travels across text |
| `cinematic_fade_up` | Slow fade-in with subtle zoom and grain |
| `epic_push_in` | Title slowly pushes toward camera |
| `hero_title_slam` | Title slams into center with bass impact |
| `trailer_flash_cut` | Text appears for very short flash frames |
| `dark_prestige_title` | Minimal title over black with subtle glow |
| `horror_scratch_title` | Uneven horror typography with scratches |
| `blood_drip_text` | Letters drip downward |
| `ice_title` | Frozen crystalline text |
| `lava_title` | Hot molten text with glowing cracks |
| `space_title` | Title filled with starfield/nebula |
| `superhero_emblem_title` | Bold title with emblematic bevel and shine |
| `documentary_lower_third` | Clean lower-third title for names/locations |
| `news_headline_strap` | Broadcast-style headline bar |
| `festival_laurel_title` | Film-festival styled text with laurels |
| `chapter_card` | Full-screen chapter title card |

#### typographic_layout (20)

| Slug | Description |
|---|---|
| `stacked_title` | Words stacked vertically with alignment |
| `split_typography` | Large word split around subject area |
| `text_behind_subject` | Title appears behind a person/object (requires `masks` extra) |
| `text_around_object` | Text wraps or positions around subject |
| `vertical_text` | Text arranged vertically |
| `circular_badge_text` | Text on circular badge/logo |
| `grid_text` | Repeating words in a grid pattern |
| `poster_title_lockup` | Structured film-poster title layout |
| `credit_block` | Movie poster credit block |
| `end_credits_roll` | Credits scroll upward |
| `title_crawl` | Perspective text crawl like sci-fi intro |
| `split_screen_labels` | Labels attached to panels in split-screen |
| `map_label_text` | Animated map labels or place names |
| `data_label_overlay` | Text labels attached to chart elements |
| `infographic_text` | Structured explanatory labels and numbers |
| `number_counter` | Numeric value counts up/down |
| `percentage_counter` | Percentage increments with suffix |
| `big_quote_title` | Pull quote appears in editorial style |
| `legal_citation_caption` | Structured citation/case reference overlay |
| `document_stamp_text` | Stamped label such as APPROVED/DRAFT |

---

### Deferred effects — v0.2 (15)

These effects are stubbed. Calling them raises `title_fx.TitleDeferredError`. They will be
implemented in v0.2 using Blender Python scripting and/or OpenCV homography.

| Slug | Description | Notes |
|---|---|---|
| `extruded_3d_text` | Text has real 3D depth | v0.2, Blender |
| `beveled_3d_text` | Text has chamfered edges | v0.2, Blender |
| `3d_fly_through_text` | Camera moves through large 3D letters | v0.2, Blender |
| `3d_flip_board` | Text appears on flipping panels | v0.2, Blender/OpenCV |
| `3d_cube_text` | Text printed on rotating cube faces | v0.2, Blender/OpenCV |
| `parallax_title` | Multiple text layers move with depth | v0.2 |
| `depth_of_field_title` | Foreground/background text with focus pull | v0.2 |
| `ar_floating_label` | Text appears attached to tracked scene position | v0.2, OpenCV tracking |
| `perspective_road_text` | Text lies on ground plane in perspective | v0.2, OpenCV homography |
| `curved_surface_text` | Text wraps around cylinder/sphere | v0.2, Blender/remap |
| `book_page_text` | Text sits on flipping page | v0.2, Blender/perspective warp |
| `glass_refraction_text` | Text distorted through glass pane | v0.2, displacement shader |
| `shadow_catcher_text` | 3D title integrated with real footage shadows | v0.2, Blender |
| `camera_tracked_title` | Text sticks to real camera movement | v0.2, tracking data |
| `3d_lower_third` | Lower third with depth and extrusion | v0.2, Blender |

Listing deferred effects:

```python
import title_fx

all_titles = title_fx.list_titles(include_deferred=True)   # 59
active_only = title_fx.list_titles()                        # 44

deferred = [t for t in all_titles if t not in active_only]
for t in deferred:
    print(t["slug"], t["status"])
```

---

## Composition with cut-fx

`title-fx` is designed to compose with `cut-fx` for slam-cut sequences. Install the `cuts`
extra and use `cut-fx` to produce a timed cut list, then render titles at each cut point.

```python
from cut_fx import CutSequence
import title_fx

# Build a cut sequence from a source clip
cuts = CutSequence.from_video("trailer_source.mp4", beat_cuts=[1.2, 2.4, 3.1, 4.8])

# Apply hero_title_slam at the first cut, then dark_prestige_title at the fourth
for i, cut in enumerate(cuts):
    if i == 0:
        title_fx.apply_title(
            input_video=cut.clip_path,
            text="IN A WORLD",
            effect="hero_title_slam",
            output=f"out_{i:02d}.mp4",
        )
    elif i == 3:
        title_fx.apply_title(
            input_video=cut.clip_path,
            text="COMING SOON",
            effect="dark_prestige_title",
            output=f"out_{i:02d}.mp4",
        )
```

Refer to the `cut-fx` documentation for `CutSequence` API details — the cut list interface
is owned by `cut-fx`, not `title-fx`.

---

## v0.2 roadmap — advanced 3D effects

The 15 deferred effects all require one of two rendering backends that are not bundled in v0.1:

**Blender (headless)** — `extruded_3d_text`, `beveled_3d_text`, `3d_fly_through_text`,
`3d_cube_text`, `curved_surface_text`, `book_page_text`, `glass_refraction_text`,
`shadow_catcher_text`, `camera_tracked_title`, `3d_lower_third`.

These will use `bpy` scripted from Python via a subprocess call to a headless Blender
installation. The `blender` extra will pin a helper package that locates the Blender binary.

**OpenCV homography / tracking** — `3d_flip_board`, `parallax_title`, `depth_of_field_title`,
`ar_floating_label`, `perspective_road_text`.

These require tracking data or homography estimation from the input video. They will use
`opencv-python-headless` (already a required dependency) plus optional per-frame tracking
logic.

To receive v0.2 updates, watch the repository releases page:
https://github.com/tomastimelock/title-fx/releases

---

## CLI reference

```
title-fx list
```
Lists all 44 active effects, one slug per line.

```
title-fx list --include-deferred
```
Lists all 59 effects, one slug per line.

```
title-fx info <slug>
```
Prints JSON metadata for one effect including description, category, and status.

```
title-fx apply --input scene.mp4 --text "CHAPTER ONE" --effect chapter_card --output out.mp4
```
Applies a named effect from the command line.

```
title-fx lower-third --input interview.mp4 --name "Erik Strand" --role "Director" \
    --effect documentary_lower_third --start 3.0 --duration 4.0 --output out.mp4
```
Renders a lower third onto an interview clip.

```
title-fx end-credits --input final.mp4 --credits credits.txt --output final_credits.mp4
```
Scrolls a plain-text credits file over the final clip using `end_credits_roll`.

Full flag reference:

```
title-fx --help
title-fx apply --help
title-fx lower-third --help
```

---

## Package structure

```
title-fx/
  src/
    title_fx/
      __init__.py        # public surface: apply_title, lower_third, end_credits, chapter_card,
                         #                 list_titles, get_title_info
      api.py             # top-level orchestration
      cli.py             # click/argparse CLI entry point
      config.py          # TitleConfig pydantic model
      schema/            # pydantic schemas for effects and layouts
      styles/            # per-effect render logic (one module per category)
      composite/         # frame compositing helpers
      layouts/           # typographic layout engines
      crew/              # ffmpeg assembly and codec config
      data/
        title_catalog.json   # shipped in wheel via force-include
  tests/
```

---

## License and links

MIT License. Copyright 2026 Trollfabriken AITrix AB.

- GitHub: https://github.com/tomastimelock/title-fx
- PyPI: https://pypi.org/project/title-fx/
- Issues: https://github.com/tomastimelock/title-fx/issues
- Trollfabriken stack: `text-fx` · `caption-cast` · `title-fx` · `cut-fx` · `audio-arrange` · `lyric-sync`

Maintained by [Trollfabriken AITrix AB](https://github.com/tomastimelock).
