MoneyPrinterTurbo Video Generation Pipeline: 6-Stage Modular Architecture Explained

MoneyPrinterTurbo uses a deterministic six-stage pipeline orchestrated by app/services/task.py that progresses from LLM script generation through keyword extraction, TTS audio synthesis, subtitle creation, stock video acquisition, and final clip composition with transitions.

MoneyPrinterTurbo is an open-source automated video creation tool that transforms text subjects into short-form videos through a modular Python-based workflow. The entire process is defined in the harry0703/MoneyPrinterTurbo repository and centers on the task.py orchestrator, which chains discrete processing stages into a single cohesive rendering pipeline.

The Six Stages of the Video Generation Pipeline

The pipeline executes sequentially within task.start(), with each stage calling specialized service modules. Every function is a pure-Python implementation that can be invoked independently or as part of the end-to-end workflow.

Stage 1: Script Generation

The pipeline begins at app/services/task.py lines 16-34 with the generate_script function. This stage invokes the LLM service (app/services/llm.py) to create a video script based on the user-provided subject, optionally respecting parameters for language and paragraph count. The generated text serves as the narrative foundation for all subsequent stages.

Stage 2: Keyword Extraction

Immediately following script creation, generate_terms (lines 36-58 in task.py) processes the script to extract search terms and keywords. These terms drive the visual material search in Stage 5, ensuring the downloaded footage semantically aligns with the narration content.

Stage 3: Audio Synthesis

The generate_audio function (lines 73-122 in task.py) handles text-to-speech conversion via the voice service module. If no custom audio file is provided, the system synthesizes narration using supported providers such as Azure or ElevenLabs. This stage returns a sub_maker object—an internal data structure used later for subtitle timing—and calculates the total audio duration required for video timing synchronization.

Stage 4: Subtitle Creation

Subtitles are generated in generate_subtitle (lines 124-161 in task.py) through two possible paths: the Edge-API (using the TTS result from Stage 3) or a fallback to Whisper for transcription. The resulting subtitle file undergoes cleaning and correction against the original script to ensure accuracy before overlay rendering.

Stage 5: Visual Material Acquisition

The get_video_materials function (lines 162-192 in task.py) acquires footage through two distinct paths:

  • Remote sources: material.download_videos (from app/services/material.py) pulls short clips from Pexels, Pixabay, Douyin, Bilibili, and Xiaohongshu, filtered by the requested aspect ratio and constrained to match the total audio duration.
  • Local sources: video.preprocess_video converts user-uploaded images into short zoom-in video clips for custom visuals.

Stage 6: Clip Composition and Final Rendering

The final stage splits into two operations within app/services/video.py:

  1. Clip chopping and shuffling: combine_videos (lines 17-130) segments source clips into pieces of max_clip_duration or less, optionally shuffles their order, resizes them to the target aspect ratio, and applies the selected transition effect (fade, slide, or shuffle modes).
  2. Final assembly: generate_video (lines 363-426) loads the combined clip sequence, overlays the narration audio (with optional background music), burns in the subtitle clips, and writes the finalized MP4 to disk.

Pipeline Orchestration and Entry Points

The task.py module exposes multiple interfaces for executing the pipeline, ranging from high-level automation to granular debugging.

High-Level API: End-to-End Execution

For standard usage, the start function in app/services/task.py provides a single entry point that accepts a VideoParams configuration object and a stop_at parameter for partial execution.

from app.services.task import start
from app.models.schema import VideoParams

# Configure generation parameters

params = VideoParams(
    video_subject="The impact of money",
    voice_name="zh-CN-XiaoyiNeural-Female",
    voice_rate=1.0,
)

# Execute full pipeline; stop_at can be "script", "terms", "audio", etc.

task_id = "my-task-001"
result = start(task_id, params, stop_at="video")
print(result["videos"][0])  # Final MP4 path

The stop_at parameter enables partial pipeline execution for debugging or iterative content creation, terminating after the specified stage.

Manual Step-by-Step Execution

For development or custom workflows, individual service functions can be invoked directly without the orchestrator:

from app.services import task, video, voice, subtitle, material, llm

# 1. Generate content

script = llm.generate_script(video_subject="Future of finance", language="en")
terms = llm.generate_terms(video_subject="Future of finance", video_script=script)

# 2. Create audio and subtitles

audio_file, audio_dur, sub_maker = voice.tts(
    text=script,
    voice_name="en-US-JennyNeural",
    voice_rate=1.0,
)
subtitle_path = subtitle.create(audio_file=audio_file, subtitle_file="sub.srt")
subtitle.correct(subtitle_path, script)

# 3. Download stock footage

materials = material.download_videos(
    task_id="debug",
    search_terms=terms,
    source="pexels",
    video_aspect="portrait",
    video_contact_mode="random",
    audio_duration=audio_dur,
    max_clip_duration=4,
)

# 4. Combine clips with transitions

video.combine_videos(
    combined_video_path="combined.mp4",
    video_paths=materials,
    audio_file=audio_file,
    video_aspect="portrait",
    video_concat_mode="random",
    video_transition_mode="fade_in",
    max_clip_duration=4,
)

# 5. Render final video with overlays

video.generate_video(
    video_path="combined.mp4",
    audio_path=audio_file,
    subtitle_path=subtitle_path,
    output_file="final.mp4",
    params=VideoParams(),
)

Web UI Integration

The Streamlit interface in webui/Main.py (around lines 500-540) wraps the high-level API for end-user interaction:

if st.button("Generate Video", key="run_video"):
    with st.spinner("Generating video..."):
        task_id = utils.random_id()
        params = VideoParams(
            video_subject=user_subject,
            video_script=user_script,
            # ... additional UI parameters

        )
        result = task.start(task_id, params, stop_at="video")
        st.video(result["videos"][0])

Core Service Architecture

The pipeline relies on six primary service modules, each isolated to a specific domain:

  • app/services/task.py: Central orchestrator implementing start() and the six-stage coordination logic.
  • app/services/video.py: Low-level video manipulation including combine_videos for clip assembly and generate_video for final rendering with subtitle/BGM overlay.
  • app/services/material.py: Stock footage acquisition via download_videos, supporting Pexels, Pixabay, and Chinese platforms (Douyin, Bilibili, Xiaohongshu).
  • app/services/voice.py: TTS provider abstraction and audio duration calculations.
  • app/services/llm.py: LLM API wrapper (OpenAI, Claude, DeepSeek) for script and keyword generation.
  • app/models/schema.py: Data models including VideoParams, aspect ratio enums, and transition mode definitions shared across the pipeline.

Summary

  • MoneyPrinterTurbo implements a six-stage linear pipeline orchestrated by app/services/task.py: Script → Keywords → Audio → Subtitles → Visuals → Composition.
  • Each stage is modular and independently callable, allowing partial execution via the stop_at parameter or direct service function invocation.
  • Visual sourcing is multi-platform, supporting both international stock libraries (Pexels, Pixabay) and Chinese social platforms (Douyin, Bilibili, Xiaohongshu).
  • Rendering supports configurable transitions (fade, slide, shuffle) and automatic subtitle burning via video.combine_videos and video.generate_video.
  • The entry point task.start() accepts a VideoParams schema object, making the pipeline compatible with both API integrations and the provided Streamlit web interface.

Frequently Asked Questions

Can I execute individual pipeline stages without running the full workflow?

Yes. The start() function accepts a stop_at parameter that accepts stage names including "script", "terms", "audio", "subtitle", "material", or "video". Alternatively, you can import individual functions from app/services/llm.py, voice.py, or video.py to execute specific stages manually for debugging or custom workflows.

What video sources does MoneyPrinterTurbo use for stock footage?

According to app/services/material.py, the system downloads clips from Pexels, Pixabay, Douyin, Bilibili, and Xiaohongshu. The download_videos function filters results by aspect ratio and ensures the total downloaded duration matches the audio length. For custom content, video.preprocess_video converts local images into animated clips.

How does the subtitle generation handle different languages?

The generate_subtitle function in task.py (lines 124-161) prioritizes the Edge-API when using Azure TTS voices, deriving timing directly from the sub_maker object returned during audio synthesis. If this fails or for non-Azure voices, it falls back to Whisper for transcription. The subtitle.correct() function then aligns the generated text against the original script to fix transcription errors.

What transition effects are available during clip composition?

The combine_videos function in app/services/video.py supports multiple video_transition_mode values including "fade_in", slide transitions, and shuffle modes. The max_clip_duration parameter controls segment length, while video_concat_mode (set to "random" or sequential) determines clip ordering before transitions are applied.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →