# Data flow — harry0703/MoneyPrinterTurbo

> Canonical page: https://codevetter.com/unpack/moneyprinterturbo/data-flow

# Data flow — harry0703/MoneyPrinterTurbo

Scanned commit 3d5f4e421927d61f3eac729cf4b711ac0b69d688 (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

A request becomes a pydantic VideoParams, gets a UUID task_id, a state record, and a storage/tasks/<task_id> workspace. The pipeline transforms subject→script→terms→audio→subtitle→materials→final MP4, writing intermediate files (script.json, audio.mp3, subtitle.srt, combined-N.mp4, final-N.mp4) into the task dir and progress/state into MemoryState or RedisState. Outputs leave via the /tasks static mount, /stream, /download, or cross-posting to upload-post.com. Configuration flows the other direction: config.toml → section dicts, with WebUI runtime writes funneled through a non-blocking pending-update queue and atomic file saves.
- Ingress: TaskVideoRequest (a VideoParams subclass) is validated by pydantic, dumped into a task record {task_id, request_id, params}, persisted via sm.state.update_task, then tm.start is scheduled through task_manager.add_task — with rollback of the state record if scheduling throws. — [app/controllers/v1/video.py#L202-238](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/controllers/v1/video.py#L202-L238) [app/models/schema.py#L91-161](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/models/schema.py#L91-L161)
- Script/terms stage: generate_script uses params.video_script verbatim or calls llm.generate_script; generate_terms calls llm.generate_terms (5 terms, or 8 in match-script-order mode) and optionally reranks through twelvelabs.rerank_terms_by_subject; results are persisted to <task_dir>/script.json via task_artifacts.write_script_data's atomic temp-file+os.replace write. — [app/services/task.py#L292-361](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L292-L361) [app/services/task_artifacts.py#L21-61](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task_artifacts.py#L21-L61)
- Audio stage: resolve_custom_audio_file confines submitted paths to the task directory unless allow_server_file_input=True (CLI only); otherwise voice.tts writes audio.mp3 and returns an edge-tts SubMaker timeline; audio_duration is measured from the written file, not cue end times. — [app/services/task.py#L364-577](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L364-L577) [app/services/voice.py#L995-1040](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/voice.py#L995-L1040)
- Subtitle stage: 'edge' provider serializes SubMaker cues to subtitle.srt (never auto-falling back to Whisper, to avoid surprise multi-GB model downloads); 'whisper' transcribes the audio file with faster-whisper and runs subtitle.correct() against the script. — [app/services/task.py#L580-645](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L580-L645) [app/services/subtitle.py#L23-80](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/subtitle.py#L23-L80)
- Materials stage: stock sources go through _search_videos_with_cache (24h per-term cache in material_cache, double-checked locking) then download_videos; paid generation sources take _download_videos_*_on_demand paths that generate clips one at a time and stop once audio_duration*video_count is covered; 'local' preprocesses user files; 'loomloom' executes a confirmed SkillBot run and persists run_id immediately since billing has already started. — [app/services/material.py#L1593-1805](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/material.py#L1593-L1805) [app/services/task.py#L648-728](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L648-L728) [app/services/material_cache.py](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/material_cache.py)
- Render stage: generate_final_videos loops video_count times calling video.combine_videos (→ combined-N.mp4), optionally calls the AI music provider's generate_bgm, then video.generate_video (muxing narration, subtitles, BGM → final-N.mp4); progress is written to state at ~5/10/20/30/40/50→100 milestones. — [app/services/task.py#L883-1029](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L883-L1029) [app/services/task.py#L1388-1630](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1388-L1630) [app/services/video.py#L744-1209](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/video.py#L744-L1209)
- Egress: task state stores absolute file paths; GET /tasks/{id} converts them to /tasks/* URLs via _task_file_to_uri (which re-validates each path inside the task dir), and the StaticFiles mount plus /stream//download endpoints serve bytes from storage/tasks. — [app/controllers/v1/video.py#L107-129](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/controllers/v1/video.py#L107-L129) [app/controllers/v1/video.py#L258-287](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/controllers/v1/video.py#L258-L287) [app/asgi.py#L284-288](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/asgi.py#L284-L288)
- Config read path: load_config() → _cfg TOML dict → section dicts (app, azure, whisper, proxy, ui, and per-TTS sections); reads anywhere use config.<section>.get(...); app.redis_host is overridable via MPT_APP_REDIS_HOST/REDIS_HOST env vars. — [app/config/config.py#L460-586](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/config/config.py#L460-L586)
- Config write path (WebUI): controls call update_config_nonblocking/delete_config_nonblocking which enqueue into _pending_config_updates keyed by id(section); a background 'mpt-config-flush' thread applies them when runtime_config_lock is free; save_config writes config.toml atomically. — [app/config/config.py#L91-271](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/config/config.py#L91-L271)
- In Redis mode the task queue is a Redis list of JSON payloads; enqueue serializes VideoParams via model_dump and stores the function name, and dequeue re-validates against FUNC_MAP and current VideoParams — dropping stale entries while marking their tasks failed so they never appear stuck in 'processing'. — [app/controllers/manager/redis_manager.py#L14-130](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/controllers/manager/redis_manager.py#L14-L130)
- Cross-post flow: on success the task is marked COMPLETE with cross_post_state='pending' and cross_post_owner='hostname:pid:uuid'; _schedule_cross_post submits to a bounded ThreadPoolExecutor(max_workers=2) gated by a BoundedSemaphore, and terminal state is written via patch_task so a deleted task is never resurrected. — [app/services/task.py#L43-65](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L43-L65) [app/services/task.py#L1321-1375](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1321-L1375) [app/services/task.py#L1644-1700](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L1644-L1700)
- Failure propagation: every stage funnels into _mark_task_failed(state=-1, failed_stage, error) which preserves remote IDs (volcengine_seedance_task_id, ofox_task_id, metaso_minimax_task_id, muapi_task_id, loomloom_run_id) so paid remote jobs remain recoverable from provider dashboards. — [app/services/task.py#L243-289](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L243-L289) [app/services/task.py#L718-806](https://github.com/harry0703/MoneyPrinterTurbo/blob/3d5f4e421927d61f3eac729cf4b711ac0b69d688/app/services/task.py#L718-L806)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
