Skip to content

lachlanchen/LazyEdit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

536 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

English · العربية · Español · Français · 日本語 · 한국어 · Tiếng Việt · 中文 (简体) · 中文(繁體) · Deutsch · Русский

LazyingArt banner

LazyEdit

AI-assisted video workflow for generation, subtitle processing, metadata, and optional publishing.
Upload or generate -> transcribe -> translate/polish -> burn subtitles -> caption/keyframes -> metadata -> publish

License: Apache-2.0 Python 3.10+ Backend: Tornado Frontend: Expo Platform: Linux FFmpeg required PostgreSQL supported Stage A/B/C enabled AutoPublish optional i18n: 11 languages Last commit Contributors

LazyEdit Studio publish workflow demo
Studio publish workflow with platform selection, live preview, process status, and queue tracking.

📌 Quick Facts

LazyEdit is an end-to-end AI-assisted video workflow for creation, processing, and optional publishing. It combines prompt-based generation (Stage A/B/C), media processing APIs, subtitle rendering, keyframe captioning, metadata generation, and AutoPublish handoff.

Quick fact Value
📘 Canonical README README.md (this file)
🌐 Language variants i18n/README.*.md (single language bar is intentionally kept at top)
🧠 Backend entrypoint app.py (Tornado)
🖥️ Frontend app app/ (Expo web/mobile)
🧩 Runtime styles python app.py (manual), ./start_lazyedit.sh (tmux), optional lazyedit.service
🎯 Primary references README.md, references/QUICKSTART.md, references/API_GUIDE.md, references/APP_GUIDE.md
🛠️ Ops references references/DEPLOYMENT_SYSTEMS.md, references/TMUX_SESSIONS.md, references/LAZYEDIT_DATABASE_SPLIT_FROM_ECHOMIND.md, references/LOCAL_DNS_HOST_CACHE.md, references/XIAOHONGSHU_AUTOPUBLISH_LAYOUT_CHANGE_2026_03.md

🧭 Contents

✨ Overview

LazyEdit is built around a Tornado backend (app.py) and an Expo frontend (app/).

Note: If repo/runtime details differ by machine, preserve existing defaults and override via environment variables instead of deleting machine-specific fallbacks.

Why teams use it Practical result
Unified operator flow Upload/generate/remix/publish from one workflow
API-first design Easy to script and integrate with other tools
Local-first runtime Works with tmux + service-based deployment patterns
Step What happens
1 Upload or generate video
2 Transcribe and optionally translate subtitles
3 Burn multilingual subtitles with layout controls
4 Generate keyframes, captions, and metadata
5 Package and optionally publish via AutoPublish

Pipeline focus

  • Upload, generation, remix, and library management from a single operator UI.
  • API-first processing flow for transcription, subtitle polish/translation, burn-in, and metadata.
  • Optional generation-provider integrations (Veo / Venice / A2E / Sora helpers in agi/).
  • Optional publish handoff through AutoPublish.

🎯 At a Glance

Area Included in LazyEdit Status
Core app Tornado API backend + Expo web/mobile frontend
Media pipeline ASR, subtitle translation/polish, burn-in, keyframes, captions, metadata
Generation Stage A/B/C and provider helper routes (agi/)
Distribution Optional AutoPublish handoff 🟡 Optional
Runtime model Local-first scripts, tmux workflows, optional systemd service

🏗️ Architecture Snapshot

The repository is organized as an API-first media pipeline with a UI layer:

  • app.py is the Tornado entrypoint and route orchestrator for upload, processing, generation, publish handoff, and media serving.
  • lazyedit/ contains modular pipeline building blocks (DB persistence, translation, subtitle burn-in, captions, metadata, provider adapters).
  • app/ is an Expo Router app (web/mobile) that drives upload, processing, preview, and publishing flows.
  • config.py centralizes environment loading and default/fallback runtime paths.
  • start_lazyedit.sh and lazyedit_config.sh provide reproducible tmux-based local/deployed run modes.
Layer Main paths Responsibility
API & orchestration app.py, config.py Endpoints, routing, env resolution
Processing core lazyedit/, agi/ Subtitle/caption/metadata pipeline + providers
UI app/ Operator experience (web/mobile via Expo)
Runtime scripts start_lazyedit.sh, lazyedit_config.sh, install_lazyedit.sh Local/service startup and ops

High-level flow:

Upload/Generate -> Transcribe -> Translate/Polish -> Burn Subtitles -> Keyframes/Captions -> Metadata -> Optional AutoPublish

🎬 Demos

Screens below show the main operator path from ingestion to metadata generation.

Home upload
Home · Upload
Home generate
Home · Generate
Home remix
Home · Remix
Library list
Library
Video overview
Video overview
Translation preview
Translation preview
Burn slots
Burn slots
Burn layout
Burn layout
Keyframes and captions
Keyframes + captions
Metadata generator
Metadata generator

🧩 Features

  • ✨ Prompt-based generation workflow (Stage A/B/C) with Sora and Veo integration paths.
  • 🧵 Full processing pipeline: transcription -> subtitle polish/translation -> burn-in -> keyframes -> captions -> metadata.
  • 🌏 Multilingual subtitle composition with furigana/IPA/romaji-related support paths.
  • 🔌 API-first backend with upload, processing, media serving, and publish queue endpoints.
  • 🚚 Optional AutoPublish integration for social-platform handoff.
  • 🖥️ Combined backend + Expo workflow supported via tmux launch scripts.

🌍 Documentation & i18n

  • Canonical source: README.md
  • Language variants: i18n/README.*.md
  • Language navigation: keep a single language-options line at the top of each README (no duplicate language bars)
  • Current languages in this repo: Arabic, German, English, Spanish, French, Japanese, Korean, Russian, Vietnamese, Simplified Chinese, Traditional Chinese

If there is ever a mismatch between translations and English docs, treat this English README as source of truth, then update each language file one-by-one.

i18n policy Rule
Canonical source Keep README.md as source of truth
Language bar Exactly one language-options line at top

🗂️ Project Structure

LazyEdit/
├── app.py                           # Tornado backend entrypoint and API orchestration
├── app/                             # Expo frontend (web/mobile)
├── lazyedit/                        # Core pipeline modules (translation, metadata, burner, DB, templates)
├── agi/                             # Generation provider abstraction (Sora/Veo/A2E/Venice routes)
├── DATA/                            # Runtime media input/output (symlink in this workspace)
├── translation_logs/                # Translation logs
├── temp/                            # Temporary runtime files
├── install_lazyedit.sh              # systemd installer (expects config/start/stop scripts)
├── start_lazyedit.sh                # tmux launcher for backend + Expo
├── stop_lazyedit.sh                 # tmux stop helper
├── lazyedit_config.sh               # Deployment/runtime shell config
├── config.py                        # Environment/config resolution (ports, paths, autopublish URL)
├── .env.example                     # Environment override template
├── references/                      # Additional docs (API guide, quickstart, deployment notes)
├── AutoPublish/                     # Submodule (optional publishing pipeline)
├── AutoPubMonitor/                  # Submodule (monitor/sync automation)
├── whisper_with_lang_detect/        # Submodule (ASR/VAD)
├── vit-gpt2-image-captioning/       # Submodule (primary captioner)
├── clip-gpt-captioning/             # Submodule (fallback captioner)
└── furigana/                        # External dependency in workflow (tracked submodule in this checkout)

Submodule/external dependency note:

  • Git submodules in this repository include AutoPublish, AutoPubMonitor, whisper_with_lang_detect, vit-gpt2-image-captioning, clip-gpt-captioning, and furigana.
  • Operational guidance treats furigana and echomind as external/read-only in this repo workflow. If uncertain, preserve upstream and avoid editing in place.

✅ Prerequisites

Dependency Notes
Linux environment systemd/tmux scripts are Linux-oriented
Python 3.10+ Use Conda env lazyedit
Node.js 20+ + npm Required for Expo app in app/
FFmpeg Must be available on PATH
PostgreSQL Local peer auth or DSN-based connection
Git submodules Required for key pipelines

🚀 Installation

  1. Clone and initialize submodules:
git clone git@github.com:lachlanchen/LazyEdit.git
cd LazyEdit
git submodule update --init --recursive
  1. Activate Conda environment:
source ~/miniconda3/etc/profile.d/conda.sh
conda activate lazyedit
  1. NPM-managed setup (recommended for a fresh machine):
npm install
npm run setup

npm run setup installs the Expo app dependencies, creates missing Conda envs for lazyedit, whisper, and caption, installs CUDA-aware PyTorch wheels using LAZYEDIT_TORCH_INDEX_URL (default cu128), writes machine-local .env path defaults, and runs a runtime doctor check.

Useful variants:

npm run setup -- --install-system   # also checks/installs tmux, ffmpeg, HandBrakeCLI
npm run setup -- --update-envs      # update existing Conda envs from env files
npm run doctor                      # verify Node, Conda, CUDA/PyTorch, Whisper, captioning

NPM runtime commands:

npm start       # starts the tmux backend + Expo profile
npm run backend # backend only
npm run web     # Expo web only
  1. Optional system-level install (service mode):
chmod +x install_lazyedit.sh
sudo ./install_lazyedit.sh --start /path/to/lazyedit

Service install notes:

  • install_lazyedit.sh installs ffmpeg and tmux, validates the lazyedit conda env plus Node/npm/npx, then creates or updates lazyedit.service.
  • Use --start to restart the service immediately after install/update.
  • Re-running the installer is safe; already-installed packages are skipped and the service file is refreshed in place.
  • It does not generate lazyedit_config.sh, start_lazyedit.sh, or stop_lazyedit.sh; these must already exist and be correct.

⚡ Quick Start

Backend + frontend local run (minimal path):

source ~/miniconda3/etc/profile.d/conda.sh
conda activate lazyedit
python app.py

In a second shell:

cd app
npm install
EXPO_PUBLIC_API_URL="http://localhost:8787" npx expo start --web --port 8091

Optional local database bootstrap:

createdb lazyedit_db || true
psql -d lazyedit_db -tAc "SELECT 'ok'"

Or use the repeat-safe helper:

sudo ./scripts/prepare_lazyedit_db.sh

Runtime profiles

Profile Start command Default backend Default frontend
Local dev (manual) python app.py + Expo command 8787 8091 (example command)
Tmux orchestrated ./start_lazyedit.sh 18787 18791
systemd service sudo systemctl start lazyedit.service Config/env-driven N/A

🧭 Command Cheat Sheet

Task Command
Initialize submodules git submodule update --init --recursive
Fresh machine setup npm install && npm run setup
Runtime doctor npm run doctor
Start backend only python app.py
Start backend only through npm npm run backend
Start Expo web through npm npm run web
Start backend + Expo (tmux) ./start_lazyedit.sh
Stop tmux run ./stop_lazyedit.sh
Open tmux session tmux attach -t lazyedit
Service status sudo systemctl status lazyedit.service
Service logs sudo journalctl -u lazyedit.service
DB smoke test python db_smoke_test.py
Pytest smoke test pytest tests/test_db_smoke.py

🛠️ Usage

Development: backend only

source ~/miniconda3/etc/profile.d/conda.sh
conda activate lazyedit
python app.py

Alternate entry used in current deployment scripts:

python app.py -m lazyedit

Backend default URL: http://localhost:8787 (from config.py, override with PORT or LAZYEDIT_PORT).

Development: backend + Expo app (tmux)

./start_lazyedit.sh

Default start_lazyedit.sh ports:

  • Backend: 18787
  • Expo web: 18791
  • EXPO_PUBLIC_API_URL=http://localhost:18787

Attach to session:

tmux attach -t lazyedit

Stop session:

./stop_lazyedit.sh

Service management

sudo systemctl start lazyedit.service
sudo systemctl stop lazyedit.service
sudo systemctl status lazyedit.service
sudo journalctl -u lazyedit.service

⚙️ Configuration

Copy .env.example to .env and update paths/secrets:

cp .env.example .env

Configuration precedence note:

  • config.py loads .env values if present and only sets keys not already exported in the shell.
  • Runtime values can therefore come from: shell-exported env vars -> .env -> code defaults.
  • For tmux/service runs, lazyedit_config.sh controls startup/session parameters (LAZYEDIT_DIR, CONDA_ENV, APP_ARGS, ports via startup script env).

Key variables

Variable Purpose Default/Fallback
PORT, LAZYEDIT_PORT Backend port 8787
LAZYEDIT_UPLOAD_DIR Media root directory DATA/
LAZYEDIT_DATABASE_URL, DATABASE_URL PostgreSQL DSN Local DB fallback lazyedit_db
LAZYEDIT_AUTOPUBLISH_URL AutoPublish endpoint http://localhost:8081/publish
LAZYEDIT_AUTOPUBLISH_TIMEOUT AutoPublish request timeout (seconds) 60
LAZYEDIT_WHISPER_SCRIPT Whisper/VAD script path Environment-dependent
LAZYEDIT_WHISPER_PYTHON Python executable for the dedicated Whisper env Environment-dependent
LAZYEDIT_WHISPER_MODEL, LAZYEDIT_WHISPER_FALLBACK_MODEL ASR model names large-v3 / large-v2 (example)
LAZYEDIT_TORCH_INDEX_URL PyTorch wheel index used by npm setup for CUDA/CPU wheels https://download.pytorch.org/whl/cu128
LAZYEDIT_CAPTION_PYTHON Python runtime for caption pipeline Environment-dependent
LAZYEDIT_CAPTION_PRIMARY_ROOT, LAZYEDIT_CAPTION_PRIMARY_SCRIPT Primary captioning path/script Environment-dependent
LAZYEDIT_CAPTION_FALLBACK_SCRIPT, LAZYEDIT_CAPTION_FALLBACK_CWD Fallback captioning path/script/cwd Environment-dependent
GRSAI_API_* Veo/GRSAI integration settings Environment-dependent
VENICE_*, A2E_* Venice/A2E integration settings Environment-dependent
OPENAI_API_KEY Required for OpenAI-backed features None
LAZYEDIT_AI_PROVIDER, LAZYEDIT_AI_MODEL Default structured AI provider/model deepseek / deepseek-v4-flash
LAZYEDIT_TRANSLATION_PROVIDER, LAZYEDIT_TRANSLATION_MODEL Subtitle translation provider/model deepseek / deepseek-v4-flash
DEEPSEEK_API_BASE, DEEPSEEK_API_KEY DeepSeek-compatible API endpoint and key https://api.deepseek.com / None
OPENAI_MODEL OpenAI fallback model when OpenAI provider is selected gpt-4o-mini
LAZYEDIT_SUBTITLE_CORRECTION_PROVIDER Provider for AI subtitle correction deepseek
LAZYEDIT_SUBTITLE_CORRECTION_MODEL Primary subtitle correction model deepseek-v4-pro
LAZYEDIT_SUBTITLE_CORRECTION_MODELS Comma-separated subtitle correction model preference list deepseek-v4-pro,deepseek-v4-flash
LAZYEDIT_SUBTITLE_CORRECTION_FALLBACK_MODEL Final subtitle correction fallback model deepseek-v4-flash
LAZYEDIT_SUBTITLE_CORRECTION_MAX_RETRIES Retries per correction model before trying the next model 1

Machine-specific notes:

  • app.py may set CUDA behavior (CUDA_VISIBLE_DEVICES usage in codebase context).
  • Some paths in defaults are workstation-specific; use .env overrides for portable setups.
  • lazyedit_config.sh controls tmux/session startup variables for deployment scripts.
  • Studio Settings can override AI provider/model choices at runtime and stores them in the UI preferences table.

🧾 Configuration Files

File Purpose
.env.example Template for environment variables used by backend/services
.env Machine-local overrides; loaded by config.py/app.py if present
config.py Backend defaults and environment resolution
lazyedit_config.sh tmux/service runtime profile (deploy path, conda env, app args, session name)
start_lazyedit.sh Launches backend + Expo in tmux with selected ports
install_lazyedit.sh Creates lazyedit.service and validates existing scripts/config

Recommended update order for machine portability:

  1. Copy .env.example to .env.
  2. Set path- and API-related LAZYEDIT_* values in .env.
  3. Adjust lazyedit_config.sh only for tmux/service deployment behavior.

🔌 API Examples

Base URL examples assume http://localhost:8787.

API group Representative endpoints
Upload and media /upload, /upload-stream, /media/*
Video records /api/videos, /api/videos/{id}
Processing /api/videos/{id}/transcribe, /translate, /burn-subtitles, /caption, /metadata, /process
Publish /api/videos/{id}/publish, /api/autopublish/queue
Generation /api/videos/generate (+ provider routes in app.py)

Upload:

curl -F "video=@/path/to/video.mp4" \
     -F "title=my_video" \
     -F "filename=video.mp4" \
     -F "source=api" \
     http://localhost:8787/upload

End-to-end process:

curl -X POST \
  -d "file_path=/abs/path/to/DATA/my_video/video.mp4" \
  -d "use_translation_cache=true" \
  -d "use_metadata_cache=true" \
  http://localhost:8787/video-processing

List videos:

curl http://localhost:8787/api/videos

Publish package:

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"platforms":{"xiaohongshu":true,"douyin":true}}' \
  http://localhost:8787/api/videos/123/publish

More endpoints and payload details: references/API_GUIDE.md.

Related endpoint groups you will likely use:

  • Video lifecycle: /upload, /upload-stream, /api/videos, /api/videos/{id}, /media/*
  • Processing actions: /api/videos/{id}/transcribe, /api/videos/{id}/translate, /api/videos/{id}/burn-subtitles, /api/videos/{id}/metadata, /api/videos/{id}/caption, /api/videos/{id}/process
  • Generation/provider paths: /api/videos/generate plus Venice/A2E routes exposed in app.py
  • Distribution: /api/videos/{id}/publish, /api/autopublish/queue

🧪 Examples

Frontend local run (web)

cd app
npm install
EXPO_PUBLIC_API_URL="http://localhost:8787" npx expo start --web --port 8091

If backend is on 8887:

EXPO_PUBLIC_API_URL="http://localhost:8887" npx expo start --web --port 8091

Android emulator

EXPO_PUBLIC_API_URL="http://10.0.2.2:8787" npx expo start --android

iOS simulator (macOS)

EXPO_PUBLIC_API_URL="http://127.0.0.1:8787" npx expo start --ios

Optional Sora generation helper

python -m agi.demo_fantasy_woman --seconds 8 --size 1280x720 --output DATA/sora_oracle_valley.mp4

Supported seconds: 4, 8, 12. Supported sizes: 720x1280, 1280x720, 1024x1792, 1792x1024.

🧪 Development Notes

  • Use python from Conda env lazyedit (do not assume system python3).
  • Keep large media out of Git; store runtime media in DATA/ or external storage.
  • Initialize/update submodules whenever pipeline components fail to resolve.
  • Keep edits scoped; avoid unrelated large-formatting changes.
  • For frontend work, backend API URL is controlled by EXPO_PUBLIC_API_URL.
  • CORS is open on the backend for app development.

Submodule and external dependency policy:

  • Treat external dependencies as upstream-owned. In this repository workflow, avoid editing submodule internals unless intentionally working in those projects.
  • Operational guidance in this repo treats furigana (and sometimes echomind in local setups) as external dependency paths; if uncertain, preserve upstream and avoid in-place edits.

Helpful references:

  • references/QUICKSTART.md
  • references/API_GUIDE.md
  • references/APP_GUIDE.md
  • references/DEPLOYMENT_SYSTEMS.md
  • references/TMUX_SESSIONS.md
  • references/LAZYEDIT_DATABASE_SPLIT_FROM_ECHOMIND.md
  • references/LOCAL_DNS_HOST_CACHE.md

Security/config hygiene:

  • Keep API keys and secrets in environment variables; do not commit credentials.
  • Prefer .env for machine-local overrides and keep .env.example as the public template.
  • If CUDA/GPU behavior differs by host, override via environment instead of hardcoding machine-specific values.

✅ Testing

Current formal test surface is minimal and DB-oriented.

Validation layer Command or method
DB smoke python db_smoke_test.py
Pytest DB check pytest tests/test_db_smoke.py
Functional flow Web UI + API run using short sample in DATA/
python db_smoke_test.py
pytest tests/test_db_smoke.py

For functional validation, use the web UI and API flow with a short sample clip in DATA/.

Assumptions and portability notes:

  • Some default paths in code are workstation-specific fallbacks; this is expected in current repo state.
  • If a default path does not exist on your machine, set the corresponding LAZYEDIT_* variable in .env.
  • If uncertain about a machine-specific value, preserve existing settings and add explicit overrides rather than deleting defaults.

🧱 Assumptions & Known Limits

  • The backend dependency set is not pinned by a root lockfile; environment reproducibility currently depends on local setup discipline.
  • app.py is intentionally monolithic in current repo state and contains a large route surface.
  • Most pipeline validation is integration/manual (UI + API + sample media), with limited formal automated tests.
  • Runtime directories (DATA/, temp/, translation_logs/) are operational outputs and can grow significantly.
  • Submodules are required for full functionality; partial checkout often leads to missing-script errors.

🚢 Deployment & Sync Notes

Current known paths and sync flow (from repository operations docs):

  • Development workspace: /home/lachlan/ProjectsLFS/LazyEdit
  • Deployed LazyEdit backend + app: /home/lachlan/DiskMech/Projects/lazyedit
  • Deployed AutoPubMonitor: /home/lachlan/DiskMech/Projects/autopub-monitor
  • Publishing system host: /home/lachlan/Projects/auto-publish on lazyingart
Environment Path Notes
Dev workspace /home/lachlan/ProjectsLFS/LazyEdit Main source + submodules
Deployed LazyEdit /home/lachlan/DiskMech/Projects/lazyedit tmux la-lazyedit in ops docs
Deployed AutoPubMonitor /home/lachlan/DiskMech/Projects/autopub-monitor Monitor/sync/process sessions
Publishing host /home/lachlan/Projects/auto-publish (lazyingart) Pull after submodule updates

After pushing AutoPublish/ updates from this repo, pull on publishing host:

ssh lachlan@lazyingart
cd ~/Projects/auto-publish
git pull github main

🧯 Troubleshooting

Problem Check / Fix
Missing pipeline modules or scripts Run git submodule update --init --recursive
FFmpeg not found Install FFmpeg and confirm ffmpeg -version works
Port conflicts Backend defaults to 8787; start_lazyedit.sh defaults to 18787; set LAZYEDIT_PORT or PORT explicitly
Expo cannot reach backend Ensure EXPO_PUBLIC_API_URL points to active backend host/port
Database connection issues Verify PostgreSQL + DSN/env vars; optional smoke check: python db_smoke_test.py
GPU/CUDA issues Confirm driver/CUDA compatibility with installed Torch stack
Service script fails at install Ensure lazyedit_config.sh, start_lazyedit.sh, and stop_lazyedit.sh exist before running installer

🗺️ Roadmap

  • In-app subtitle/segment editing with A/B preview and per-line controls.
  • Stronger end-to-end test coverage for core API flows.
  • Documentation convergence across i18n README variants and deployment modes.
  • Additional workflow hardening for generation-provider retries and status visibility.

🤝 Contributing

Contributions are welcome.

  1. Fork and create a feature branch.
  2. Keep commits focused and scoped.
  3. Validate changes locally (python app.py, key API flow, and app integration if relevant).
  4. Open a PR with purpose, reproduction steps, and before/after notes (screenshots for UI changes).

Practical guidelines:

  • Follow Python style (PEP 8, 4 spaces, snake_case naming).
  • Avoid committing credentials or large binaries.
  • Update docs/config scripts when behavior changes.
  • Preferred commit style: short, imperative, scoped (for example: fix ffmpeg 7 compatibility).

❤️ Support

Donate PayPal Stripe
Donate PayPal Stripe

📄 License

Apache-2.0

🙏 Acknowledgements

LazyEdit builds on open-source libraries and services, including:

  • FFmpeg for media processing
  • Tornado for backend APIs
  • MoviePy for editing workflows
  • OpenAI models for AI-assisted pipeline tasks
  • CJKWrap and multilingual text tooling in subtitle workflows

About

LazyEdit is a tool to automatically edit videos with AI-assisted auto-caption, auto-transcription, auto-highlight, auto-metadata and auto-subtitles.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors