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(fromapp/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_videoconverts 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:
- Clip chopping and shuffling:
combine_videos(lines 17-130) segments source clips into pieces ofmax_clip_durationor less, optionally shuffles their order, resizes them to the target aspect ratio, and applies the selected transition effect (fade, slide, or shuffle modes). - 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 implementingstart()and the six-stage coordination logic.app/services/video.py: Low-level video manipulation includingcombine_videosfor clip assembly andgenerate_videofor final rendering with subtitle/BGM overlay.app/services/material.py: Stock footage acquisition viadownload_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 includingVideoParams, 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_atparameter 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_videosandvideo.generate_video. - The entry point
task.start()accepts aVideoParamsschema 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →