# mmagdyelsafty/faceless-video-pipeline architecture

> Architecture diagram of the GitHub repository mmagdyelsafty/faceless-video-pipeline, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-22). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/mmagdyelsafty/faceless-video-pipeline
- Repository: https://github.com/mmagdyelsafty/faceless-video-pipeline

## Overview

1. **Overall shape**
   - This is a local, file-driven production pipeline for faceless YouTube videos.
   - The main orchestration point is `pipeline.py`, which runs the workflow in four phases: TTS prep, patch build, final assembly, and deliverables.
   - The repo is organized by pipeline stage: `core/`, `tts/`, `video/`, and `post/`.

2. **Primary data model**
   - The source inputs are an episode script and a slide plan, stored per episode under `episodes/<channel>/<episode>/`.
   - The slide plan is JSON, with `examples/sample_plan.json` showing the expected structure.
   - Generated artifacts flow through the episode folder: formatted TTS text, slide HTML, exported PNGs, audio, subtitles, patch videos, then a final assembled video.

3. **Orchestration boundary**
   - `pipeline.py` is the system integrator, not the business logic holder.
   - It sequences validation, slide generation, export, audio/video assembly, watermarking, subtitle generation, thumbnail generation, and metadata creation.
   - The phase split makes each stage independently rerunnable, which is a key architectural decision: patch-level outputs are treated as durable checkpoints.

4. **Script and TTS preparation**
   - `tts/format_script_tts.py` prepares the raw script for voice recording or TTS rendering.
   - `tts/tts_patch_splitter.py` divides the episode into smaller patches, adding recording instructions per patch.
   - This subsystem isolates narration preparation from visual production, enabling review and re-recording without rebuilding the whole episode.

5. **Slide generation core**
   - `core/slide_builder.py` converts the JSON slide plan into HTML slides using a built-in design system.
   - The slide system supports multiple slide types such as headers, stats, comparisons, timelines, and closing cards.
   - `core/validate_script.py` and `core/validate_slides.py` act as quality gates before export, enforcing content and structure expectations.

6. **Rendering boundary**
   - `core/export_slides.py` is the HTML-to-image bridge.
   - The README indicates Playwright/Chromium is used to export slides as PNGs, so this stage depends on a browser runtime even though the output is static media.
   - This is the main handoff from content/layout logic into renderable assets for video assembly.

7. **Video assembly**
   - `video/build_video.py` is the core compositor that combines slide images and audio into a patch video.
   - `video/audio_mixer.py` handles voiceover plus background music, including automatic ducking so narration stays dominant.
   - `video/watermark.py` overlays branding, and `video/intro_outro_builder.py` generates branded opening and closing segments.

8. **Subtitle and timing layer**
   - `video/subtitle_generator.py` generates SRT subtitles and merges subtitles across patch outputs.
   - This indicates the pipeline treats narration timing as part of the video product, not as a separate afterthought.
   - Subtitle generation sits downstream of TTS/audio preparation and upstream of final assembly.

9. **Post-production deliverables**
   - The `post/` subsystem handles publishing prep rather than video content creation.
   - `post/thumbnail_generator.py` creates A/B thumbnail variants.
   - `post/metadata_generator.py` builds YouTube-facing metadata such as title, description, chapters, tags, and hashtags.
   - These outputs are designed for upload readiness, but the repo does not include the upload step itself.

10. **Branding and configuration**
   - Local brand assets live under `brand/` and are intentionally git-ignored: logos, audio cues, and fonts.
   - `config.example.json` defines the expected configuration shape, while a local `config.json` provides channel-specific settings and paths.
   - The architecture supports multi-language channels, including RTL layouts, by separating language/channel configuration from episode content.

11. **Execution model**
   - The pipeline is patch-based, typically splitting an episode into five independently produced segments.
   - This reduces risk: each segment can be reviewed, corrected, and regenerated without redoing the entire episode.
   - Final assembly stitches intro + patches + outro into the finished video, then merges subtitles and produces deliverables.

12. **External tooling and runtime dependencies**
   - The pipeline is Python-based and relies on `ffmpeg` for audio/video processing.
   - Playwright Chromium is required for HTML rendering and thumbnail generation.
   - These tools materially define the architecture because the system is a content pipeline built on static asset generation plus local media processing, not a server application.

Main entry points: [`video/build_video.py`](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/build_video.py) (Video Builder), [`pipeline.py`](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/pipeline.py) (Pipeline), [`core/export_slides.py`](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/export_slides.py) (Export Slides), [`core/validate_script.py`](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/validate_script.py) (Script Check)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_orchestration["Orchestration"]
  node_pipeline["Pipeline<br/>orchestrator<br/>[pipeline.py]"]
end

subgraph group_content["Content Prep"]
  node_validate_script["Script Check<br/>validator<br/>[validate_script.py]"]
  node_validate_slides["Slide Check<br/>validator<br/>[validate_slides.py]"]
  node_slide_builder["Slide Builder<br/>html generator<br/>[slide_builder.py]"]
  node_format_script_tts["TTS Script<br/>narration prep"]
  node_tts_patch_splitter["Patch Splitter<br/>narration splitter"]
end

subgraph group_render["Rendering"]
  node_export_slides["Export Slides<br/>html-to-image<br/>[export_slides.py]"]
  node_playwright(("Browser Runtime<br/>runtime dependency"))
  node_audio_mixer["Audio Mixer<br/>[audio_mixer.py]"]
  node_build_video["Video Builder<br/>compositor<br/>[build_video.py]"]
  node_intro_outro_builder["Intro/Outro<br/>segment builder"]
  node_subtitle_generator["Subtitles<br/>caption pipeline"]
  node_watermark["Watermark<br/>branding overlay<br/>[watermark.py]"]
  node_ffmpeg(("FFmpeg<br/>media runtime"))
end

subgraph group_publish["Post"]
  node_thumbnail_generator["Thumbnails<br/>image generator"]
  node_metadata_generator["Metadata<br/>publish prep"]
end

subgraph group_assets["Assets"]
  node_episode_workspace[("Episode Files<br/>workspace")]
  node_config["Config<br/>settings"]
  node_sample_plan["Sample Plan<br/>schema example<br/>[sample_plan.json]"]
end

node_config -->|"settings"| node_pipeline
node_sample_plan -->|"plan shape"| node_slide_builder
node_episode_workspace -->|"script"| node_validate_script
node_episode_workspace -->|"script"| node_format_script_tts
node_validate_script -->|"approved script"| node_tts_patch_splitter
node_format_script_tts -->|"tts text"| node_tts_patch_splitter
node_episode_workspace -->|"slide plan"| node_validate_slides
node_validate_slides -->|"validated plan"| node_slide_builder
node_slide_builder -->|"html slides"| node_export_slides
node_export_slides -->|"render"| node_playwright
node_export_slides -->|"pngs"| node_build_video
node_tts_patch_splitter -->|"patch audio"| node_audio_mixer
node_audio_mixer -->|"mixing"| node_ffmpeg
node_build_video -->|"composition"| node_ffmpeg
node_intro_outro_builder -->|"segments"| node_build_video
node_watermark -->|"branding"| node_build_video
node_subtitle_generator -->|"captions"| node_build_video
node_build_video -->|"patch video"| node_pipeline
node_build_video -->|"timing"| node_subtitle_generator
node_build_video -->|"frames"| node_thumbnail_generator
node_build_video -->|"episode output"| node_metadata_generator
node_pipeline -->|"deliverables"| node_thumbnail_generator
node_pipeline -->|"deliverables"| node_metadata_generator
node_pipeline -->|"read/write"| node_episode_workspace
node_pipeline -->|"phase 1"| node_validate_script
node_pipeline -->|"phase 2"| node_validate_slides
node_pipeline -->|"phase 3"| node_export_slides
node_pipeline -->|"phase 4"| node_build_video

click node_pipeline "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/pipeline.py"
click node_config "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/config.example.json"
click node_sample_plan "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/examples/sample_plan.json"
click node_validate_script "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/validate_script.py"
click node_validate_slides "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/validate_slides.py"
click node_slide_builder "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/slide_builder.py"
click node_format_script_tts "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/tts/format_script_tts.py"
click node_tts_patch_splitter "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/tts/tts_patch_splitter.py"
click node_export_slides "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/export_slides.py"
click node_audio_mixer "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/audio_mixer.py"
click node_build_video "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/build_video.py"
click node_intro_outro_builder "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/intro_outro_builder.py"
click node_subtitle_generator "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/subtitle_generator.py"
click node_watermark "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/watermark.py"
click node_thumbnail_generator "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/post/thumbnail_generator.py"
click node_metadata_generator "https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/post/metadata_generator.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_pipeline toneBlue
class node_validate_script,node_validate_slides,node_slide_builder,node_format_script_tts,node_tts_patch_splitter toneAmber
class node_export_slides,node_playwright,node_audio_mixer,node_build_video,node_intro_outro_builder,node_subtitle_generator,node_watermark,node_ffmpeg toneMint
class node_thumbnail_generator,node_metadata_generator toneRose
class node_episode_workspace,node_config,node_sample_plan toneIndigo
```

## Components

### Orchestration

Top-level workflow and execution boundary.

- [Pipeline](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/pipeline.py): orchestrator · Main entrypoint that runs the episode workflow through staged checkpoints. · `pipeline.py`

### Content Prep

Script, slide plan, and slide generation.

- [Script Check](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/validate_script.py): validator · Validates the episode script before narration and slide generation. · `core/validate_script.py`
- [Slide Check](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/validate_slides.py): validator · Validates slide structure and content before rendering. · `core/validate_slides.py`
- [Slide Builder](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/slide_builder.py): html generator · Converts slide plans into HTML slides using the built-in design system. · `core/slide_builder.py`
- [TTS Script](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/tts/format_script_tts.py): narration prep · Formats raw script text for voice recording or TTS rendering. · `tts/format_script_tts.py`
- [Patch Splitter](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/tts/tts_patch_splitter.py): narration splitter · Breaks the episode into recording patches and adds patch-level instructions. · `tts/tts_patch_splitter.py`

### Rendering

HTML export and media assembly.

- [Export Slides](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/core/export_slides.py): html-to-image · Renders HTML slides into PNG assets for video assembly. · `core/export_slides.py`
- **Browser Runtime**: runtime dependency · Chromium/Playwright runtime used for slide and thumbnail rendering.
- [Audio Mixer](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/audio_mixer.py): audio mix · Combines narration and music with ducking so voice stays dominant. · `video/audio_mixer.py`
- [Video Builder](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/build_video.py): compositor · Builds patch videos from slide images, audio, and timing information. · `video/build_video.py`
- [Intro/Outro](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/intro_outro_builder.py): segment builder · Creates branded opening and closing segments for the final assembly. · `video/intro_outro_builder.py`
- [Subtitles](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/subtitle_generator.py): caption pipeline · Generates SRT subtitles and merges subtitles across patch outputs. · `video/subtitle_generator.py`
- [Watermark](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/video/watermark.py): branding overlay · Adds brand watermarking to video outputs. · `video/watermark.py`
- **FFmpeg**: media runtime · External media processing tool used for audio and video composition.

### Post

Thumbnail and metadata deliverables.

- [Thumbnails](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/post/thumbnail_generator.py): image generator · Creates A/B thumbnail variants for upload readiness. · `post/thumbnail_generator.py`
- [Metadata](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/post/metadata_generator.py): publish prep · Builds title, description, chapters, tags, and hashtags for the episode. · `post/metadata_generator.py`

### Assets

Episode workspace and shared inputs.

- **Episode Files**: workspace · Per-episode folder holding script, plan, rendered assets, audio, subtitles, and final outputs.
- [Config](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/config.example.json): settings · Local channel and path configuration used across the pipeline. · `config.example.json`
- [Sample Plan](https://github.com/mmagdyelsafty/faceless-video-pipeline/blob/main/examples/sample_plan.json): schema example · Example slide plan showing the expected episode plan structure. · `examples/sample_plan.json`

## Connections

- Config → Pipeline: settings · Provides channel, language, and path configuration to the workflow.
- Sample Plan → Slide Builder: plan shape · Defines the expected structure for episode slide plans.
- Episode Files → Script Check: script · Supplies the episode script as the first validation input.
- Episode Files → TTS Script: script · Feeds the raw episode script into narration preparation.
- Script Check → Patch Splitter: approved script · Allows split-and-patch narration preparation after script validation.
- TTS Script → Patch Splitter: tts text · Provides cleaned narration text for patch segmentation.
- Episode Files → Slide Check: slide plan · Supplies the episode plan for structural validation.
- Slide Check → Slide Builder: validated plan · Allows HTML slide generation after plan validation.
- Slide Builder → Export Slides: html slides · Hands off generated slides for browser-based export.
- Export Slides → Browser Runtime: render · Uses the browser runtime to rasterize slides to images.
- Export Slides → Video Builder: pngs · Provides rendered slide images to the compositor.
- Patch Splitter → Audio Mixer: patch audio · Feeds narration segments into audio mixing.
- Audio Mixer → FFmpeg: mixing · Relies on ffmpeg for audio processing and ducking.
- Video Builder → FFmpeg: composition · Uses ffmpeg for video assembly and patch rendering.
- Intro/Outro → Video Builder: segments · Supplies branded intro and outro segments for final assembly.
- Watermark → Video Builder: branding · Adds watermark overlays during video composition.
- Subtitles → Video Builder: captions · Provides subtitles for patch and final outputs.
- Video Builder → Pipeline: patch video · Returns durable patch-level video checkpoints to orchestration.
- Video Builder → Subtitles: timing · Supplies timing context used to generate subtitles.
- Video Builder → Thumbnails: frames · Provides visual assets that can support thumbnail creation.
- Video Builder → Metadata: episode output · Feeds completed episode context into publish-prep metadata generation.
- Pipeline → Thumbnails: deliverables · Triggers thumbnail generation as part of the final phase.
- Pipeline → Metadata: deliverables · Triggers metadata generation as part of the final phase.
- Pipeline → Episode Files: read/write · Reads inputs and writes staged artifacts back into the episode folder.
- Pipeline → Script Check: phase 1 · Starts the workflow with script validation and TTS preparation.
- Pipeline → Slide Check: phase 2 · Validates slide structure before rendering.
- Pipeline → Export Slides: phase 3 · Runs slide export and downstream media assembly.
- Pipeline → Video Builder: phase 4 · Assembles patch videos and final video deliverables.
