@lazyingart/lazyedit
v0.1.0
Published
LazyEdit backend, Studio app, and media-processing runtime orchestration.
Maintainers
Readme
English · العربية · Español · Français · 日本語 · 한국어 · Tiếng Việt · 中文 (简体) · 中文(繁體) · Deutsch · Русский
LazyEdit
📌 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
- Quick Facts
- At a Glance
- Architecture Snapshot
- Demos
- Features
- Documentation & i18n
- Project Structure
- Prerequisites
- Installation
- Quick Start
- Command Cheat Sheet
- Usage
- Configuration
- Configuration Files
- API Examples
- Examples
- Development Notes
- Testing
- Assumptions & Known Limits
- Deployment & Sync Notes
- Troubleshooting
- Roadmap
- Contributing
- Support
- License
- Acknowledgements
✨ 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.pyis 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.pycentralizes environment loading and default/fallback runtime paths.start_lazyedit.shandlazyedit_config.shprovide 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.
🧩 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, andfurigana. - Operational guidance treats
furiganaandechomindas 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
- Clone and initialize submodules:
git clone [email protected]:lachlanchen/LazyEdit.git
cd LazyEdit
git submodule update --init --recursive- Activate Conda environment:
source ~/miniconda3/etc/profile.d/conda.sh
conda activate lazyedit- NPM-managed setup (recommended for a fresh machine):
npm install
npm run setupnpm 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, captioningNPM runtime commands:
npm start # starts the tmux backend + Expo profile
npm run backend # backend only
npm run web # Expo web only- Optional system-level install (service mode):
chmod +x install_lazyedit.sh
sudo ./install_lazyedit.sh --start /path/to/lazyeditService install notes:
install_lazyedit.shinstallsffmpegandtmux, validates thelazyeditconda env plus Node/npm/npx, then creates or updateslazyedit.service.- Use
--startto 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, orstop_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.pyIn a second shell:
cd app
npm install
EXPO_PUBLIC_API_URL="http://localhost:8787" npx expo start --web --port 8091Optional 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.shRuntime 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.pyAlternate entry used in current deployment scripts:
python app.py -m lazyeditBackend default URL: http://localhost:8787 (from config.py, override with PORT or LAZYEDIT_PORT).
Development: backend + Expo app (tmux)
./start_lazyedit.shDefault start_lazyedit.sh ports:
- Backend:
18787 - Expo web:
18791 EXPO_PUBLIC_API_URL=http://localhost:18787
Attach to session:
tmux attach -t lazyeditStop session:
./stop_lazyedit.shService 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 .envConfiguration precedence note:
config.pyloads.envvalues 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.shcontrols 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.pymay set CUDA behavior (CUDA_VISIBLE_DEVICESusage in codebase context).- Some paths in defaults are workstation-specific; use
.envoverrides for portable setups. lazyedit_config.shcontrols 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:
- Copy
.env.exampleto.env. - Set path- and API-related
LAZYEDIT_*values in.env. - Adjust
lazyedit_config.shonly 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/uploadEnd-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-processingList videos:
curl http://localhost:8787/api/videosPublish package:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"platforms":{"xiaohongshu":true,"douyin":true}}' \
http://localhost:8787/api/videos/123/publishMore 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/generateplus Venice/A2E routes exposed inapp.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 8091If backend is on 8887:
EXPO_PUBLIC_API_URL="http://localhost:8887" npx expo start --web --port 8091Android emulator
EXPO_PUBLIC_API_URL="http://10.0.2.2:8787" npx expo start --androidiOS simulator (macOS)
EXPO_PUBLIC_API_URL="http://127.0.0.1:8787" npx expo start --iosOptional Sora generation helper
python -m agi.demo_fantasy_woman --seconds 8 --size 1280x720 --output DATA/sora_oracle_valley.mp4Supported seconds: 4, 8, 12.
Supported sizes: 720x1280, 1280x720, 1024x1792, 1792x1024.
🧪 Development Notes
- Use
pythonfrom Conda envlazyedit(do not assume systempython3). - 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 sometimesechomindin local setups) as external dependency paths; if uncertain, preserve upstream and avoid in-place edits.
Helpful references:
references/QUICKSTART.mdreferences/API_GUIDE.mdreferences/APP_GUIDE.mdreferences/DEPLOYMENT_SYSTEMS.mdreferences/TMUX_SESSIONS.mdreferences/LAZYEDIT_DATABASE_SPLIT_FROM_ECHOMIND.mdreferences/LOCAL_DNS_HOST_CACHE.md
Security/config hygiene:
- Keep API keys and secrets in environment variables; do not commit credentials.
- Prefer
.envfor machine-local overrides and keep.env.exampleas 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.pyFor 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.pyis 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-publishonlazyingart
| 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.
- Fork and create a feature branch.
- Keep commits focused and scoped.
- Validate changes locally (
python app.py, key API flow, and app integration if relevant). - 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 |
| --- | --- | --- |
| |
|
|
📄 License
🙏 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

