lasagnastack 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lasagnastack-0.1.0/PKG-INFO +205 -0
- lasagnastack-0.1.0/README.md +184 -0
- lasagnastack-0.1.0/pyproject.toml +106 -0
- lasagnastack-0.1.0/setup.cfg +4 -0
- lasagnastack-0.1.0/src/lasagnastack/__init__.py +0 -0
- lasagnastack-0.1.0/src/lasagnastack/__main__.py +3 -0
- lasagnastack-0.1.0/src/lasagnastack/base.py +205 -0
- lasagnastack-0.1.0/src/lasagnastack/cache.py +30 -0
- lasagnastack-0.1.0/src/lasagnastack/cli.py +73 -0
- lasagnastack-0.1.0/src/lasagnastack/io.py +85 -0
- lasagnastack-0.1.0/src/lasagnastack/llm/__init__.py +0 -0
- lasagnastack-0.1.0/src/lasagnastack/llm/base.py +29 -0
- lasagnastack-0.1.0/src/lasagnastack/llm/gemini.py +394 -0
- lasagnastack-0.1.0/src/lasagnastack/logging_config.py +20 -0
- lasagnastack-0.1.0/src/lasagnastack/models/__init__.py +0 -0
- lasagnastack-0.1.0/src/lasagnastack/models/critique.py +14 -0
- lasagnastack-0.1.0/src/lasagnastack/models/cut_list.py +123 -0
- lasagnastack-0.1.0/src/lasagnastack/models/enhance.py +62 -0
- lasagnastack-0.1.0/src/lasagnastack/models/inventory.py +85 -0
- lasagnastack-0.1.0/src/lasagnastack/models/post_caption.py +8 -0
- lasagnastack-0.1.0/src/lasagnastack/pipeline.py +172 -0
- lasagnastack-0.1.0/src/lasagnastack/stages/__init__.py +0 -0
- lasagnastack-0.1.0/src/lasagnastack/stages/analyse.py +144 -0
- lasagnastack-0.1.0/src/lasagnastack/stages/critique.py +149 -0
- lasagnastack-0.1.0/src/lasagnastack/stages/direct.py +94 -0
- lasagnastack-0.1.0/src/lasagnastack/stages/enhance.py +120 -0
- lasagnastack-0.1.0/src/lasagnastack/stages/ingest.py +183 -0
- lasagnastack-0.1.0/src/lasagnastack/stages/post_caption.py +136 -0
- lasagnastack-0.1.0/src/lasagnastack/stages/render.py +172 -0
- lasagnastack-0.1.0/src/lasagnastack/video_editors/__init__.py +3 -0
- lasagnastack-0.1.0/src/lasagnastack/video_editors/base.py +53 -0
- lasagnastack-0.1.0/src/lasagnastack/video_editors/pycapcut.py +579 -0
- lasagnastack-0.1.0/src/lasagnastack.egg-info/PKG-INFO +205 -0
- lasagnastack-0.1.0/src/lasagnastack.egg-info/SOURCES.txt +40 -0
- lasagnastack-0.1.0/src/lasagnastack.egg-info/dependency_links.txt +1 -0
- lasagnastack-0.1.0/src/lasagnastack.egg-info/requires.txt +13 -0
- lasagnastack-0.1.0/src/lasagnastack.egg-info/top_level.txt +1 -0
- lasagnastack-0.1.0/tests/test_analyse.py +109 -0
- lasagnastack-0.1.0/tests/test_critique.py +278 -0
- lasagnastack-0.1.0/tests/test_direct.py +55 -0
- lasagnastack-0.1.0/tests/test_ingest.py +233 -0
- lasagnastack-0.1.0/tests/test_render.py +320 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lasagnastack
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: An AI pipeline that turns raw video clips into an editable CapCut project for short-form reel editing.
|
|
5
|
+
Author-email: Julian Wong <julianwong2000@gmail.com>
|
|
6
|
+
Requires-Python: <3.13,>=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: av>=14.0.0
|
|
9
|
+
Requires-Dist: ffmpeg-python>=0.2.0
|
|
10
|
+
Requires-Dist: google-genai>=1.0.0
|
|
11
|
+
Requires-Dist: mlflow>=2.19.0
|
|
12
|
+
Requires-Dist: opencv-python-headless>=4.0.0
|
|
13
|
+
Requires-Dist: pycapcut>=0.0.3
|
|
14
|
+
Requires-Dist: pydantic>=2.0.0
|
|
15
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
16
|
+
Requires-Dist: python-semantic-release>=10.5.3
|
|
17
|
+
Requires-Dist: scenedetect>=0.6.4
|
|
18
|
+
Requires-Dist: setuptools>=80.9.0
|
|
19
|
+
Requires-Dist: structlog>=25.0.0
|
|
20
|
+
Requires-Dist: tenacity>=9.0.0
|
|
21
|
+
|
|
22
|
+
# LasagnaStack
|
|
23
|
+
|
|
24
|
+
<img src="docs/lasagna.png" alt="LasagnaStack" width="180" />
|
|
25
|
+
|
|
26
|
+
An AI pipeline that turns raw video clips into an editable CapCut project for short-form reel editing.
|
|
27
|
+
|
|
28
|
+
It is as simple as:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python -m lasagnastack make ./my_clips/ --out ./my_capcut_draft/
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
where...
|
|
35
|
+
|
|
36
|
+
`./my_clips/`: a folder of raw video clips in MP4/MOV format + one `.txt` creator brief.
|
|
37
|
+
`./my_capcut_draft/`: a CapCut draft folder, ready to open in CapCut Desktop.
|
|
38
|
+
|
|
39
|
+
The pipeline runs in six sequential stages: **ingest** (uses ffmpeg) → **analyse** (uses LLM) → **direct** (uses LLM) → **critique loop** (uses LLM) → **enhance** (uses LLM) → **render** (uses pyCapCut).
|
|
40
|
+
|
|
41
|
+
Each stage is a subclass of the `Stage` abstract base class (`base.py`). Adding, removing, or reordering stages requires only editing the `stages` list in `ReelPipeline`. See [`ARCHITECTURE.md`](ARCHITECTURE.md) for the full architecture guide.
|
|
42
|
+
|
|
43
|
+
## Get started with development
|
|
44
|
+
|
|
45
|
+
1. Clone the repository.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git clone https://github.com/jyjulianwong/LasagnaStack.git
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
2. Verify that you have a compatible Python version installed on your machine.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python --version
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
3. Install [uv](https://github.com/astral-sh/uv) (used as the package manager for this project).
|
|
58
|
+
|
|
59
|
+
4. Install the development dependencies.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
cd LasagnaStack/
|
|
63
|
+
uv sync --all-groups
|
|
64
|
+
uv run pre-commit install
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Set up environment
|
|
68
|
+
|
|
69
|
+
Copy `.env.sample` to `.env` and fill in your values:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cp .env.sample .env
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`.env` is gitignored. Values set in the shell environment take precedence over `.env`.
|
|
76
|
+
|
|
77
|
+
## Authentication
|
|
78
|
+
|
|
79
|
+
Get a Gemini API key at [aistudio.google.com/apikey](https://aistudio.google.com/apikey) and add it to your `.env`:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
LSNSTK_LLM_GEMINI_API_KEY=your-key-here
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Run the pipeline
|
|
86
|
+
|
|
87
|
+
Prepare an input folder containing your MP4/MOV clips and exactly one `.txt` brief file, then run:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
uv run python -m lasagnastack make ./my_clips/ --out ./drafts/reel_2025_05_05
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The pipeline pauses for confirmation between each stage. To skip all prompts:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
uv run python -m lasagnastack make ./my_clips/ --out ./drafts/reel_2025_05_05 --yes
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Full CLI reference:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
usage: lasagnastack make [-h] --out OUTPUT_DIR [--skill SKILL_FILE] [--yes]
|
|
103
|
+
[--critique-max-retries N] [--ingest-max-workers N]
|
|
104
|
+
[--analyse-max-workers N] INPUT_DIR
|
|
105
|
+
|
|
106
|
+
positional arguments:
|
|
107
|
+
INPUT_DIR Folder containing clips and brief .txt
|
|
108
|
+
|
|
109
|
+
options:
|
|
110
|
+
--out OUTPUT_DIR Destination for the CapCut draft and working files
|
|
111
|
+
--skill SKILL_FILE Path to Markdown skill file injected into the direct,
|
|
112
|
+
critique, and enhance prompt templates (optional)
|
|
113
|
+
--yes, -y Auto-confirm all stage prompts
|
|
114
|
+
--critique-max-retries N Maximum # of critique loop retries (default: 2)
|
|
115
|
+
--ingest-max-workers N Maximum # of parallel worker processes for `ingest` stage (default: 2)
|
|
116
|
+
--analyse-max-workers N Maximum # of concurrent LLM calls for `analyse` stage (default: 4)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Open the draft in CapCut Desktop (macOS)
|
|
120
|
+
|
|
121
|
+
If CapCut Desktop is installed, the pipeline automatically:
|
|
122
|
+
|
|
123
|
+
1. Detects `~/Movies/CapCut/User Data/`
|
|
124
|
+
2. Copies **all** `.mp4`/`.mov` files from your input folder into the CapCut draft folder — including clips not used on the timeline — so they are immediately available in CapCut's import panel
|
|
125
|
+
3. Rewrites the timeline clip paths in `draft_info.json` to point to the copied files
|
|
126
|
+
4. Registers the draft in `root_meta_info.json` so it appears on the CapCut home screen straight away
|
|
127
|
+
|
|
128
|
+
Open CapCut Desktop after the pipeline finishes — the draft will appear on the home screen under your local projects with all media already linked. Drafts are named **LasagnaStack - Reel Name** and use that same string as the folder name so they are easy to identify among existing projects.
|
|
129
|
+
|
|
130
|
+
If CapCut is not installed, the draft is written to `<output_dir>/draft/LasagnaStack - {reel_name}/` and you can copy it manually.
|
|
131
|
+
|
|
132
|
+
> This has been tested with CapCut Desktop 8.5.0 on macOS Sequoia 15.6.1. There may be issues with older versions or other operating systems.
|
|
133
|
+
|
|
134
|
+
## Track LLM costs with MLflow
|
|
135
|
+
|
|
136
|
+
Every pipeline run is automatically traced with [MLflow](https://mlflow.org). Each Gemini API call is recorded as a span (prompt, response, token counts, latency, and estimated USD cost). Session-level totals are written to the run when the pipeline finishes.
|
|
137
|
+
|
|
138
|
+
**1. Start the MLflow server** (in a separate terminal, before running the pipeline):
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
mlflow server --host 127.0.0.1 --port 5001
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
> **macOS note:** port 5000 is reserved by AirPlay Receiver. Use 5001 or higher.
|
|
145
|
+
|
|
146
|
+
**2. Add the tracking variables to `.env`:**
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
MLFLOW_TRACKING_URI=http://localhost:5001
|
|
150
|
+
MLFLOW_EXPERIMENT_NAME=lasagnastack
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**3. Run the pipeline as normal.** Open `http://localhost:5000` in your browser to watch live.
|
|
154
|
+
|
|
155
|
+
In **Experiments -> lasagnastack -> Traces**, spans appear in real time as stages progress. Each trace has three levels: the top-level pipeline span (`ReelPipeline.run`), a per-stage span (e.g. `AnalyseStage.run`), and individual LLM call spans (`GeminiClient._call_api`) nested inside.
|
|
156
|
+
|
|
157
|
+
Runs are named `lasagnastack-{brief_stem}-{4-char-id}` and tagged with the model, reel name, and `critique_max_retries`.
|
|
158
|
+
|
|
159
|
+
> **No server?** Set `MLFLOW_TRACKING_URI=mlruns` to write results to a local folder instead, then view them with `mlflow ui`.
|
|
160
|
+
|
|
161
|
+
## Configuration
|
|
162
|
+
|
|
163
|
+
| Parameter | How to set | Default |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| LLM model | `LSNSTK_LLM_MODEL` env. var. | `gemini/gemini-2.5-flash` |
|
|
166
|
+
| Gemini API key | `LSNSTK_LLM_GEMINI_API_KEY` env. var. (required) | — |
|
|
167
|
+
| Path to skill file | `--skill` CLI flag | — |
|
|
168
|
+
| `critique` stage maximum # of retries | `--critique-max-retries` CLI flag | `2` |
|
|
169
|
+
| `ingest` stage maximum # of worker processes | `--ingest-max-workers` CLI flag | `2` |
|
|
170
|
+
| `analyse` stage maximum # of concurrent LLM calls | `--analyse-max-workers` CLI flag | `4` |
|
|
171
|
+
|
|
172
|
+
## Architecture
|
|
173
|
+
|
|
174
|
+
See [`ARCHITECTURE.md`](ARCHITECTURE.md) for four annotated diagrams covering the pipeline data flow, the Stage 4 critique loop, the Stage 6 render + CapCut export, and the extensibility model.
|
|
175
|
+
|
|
176
|
+
## Get started with Jupyter notebooks
|
|
177
|
+
|
|
178
|
+
1. Once the above setup is complete, set up a Python kernel.
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
source .venv/bin/activate
|
|
182
|
+
python -m ipykernel install --user --name=lasagnastack
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
2. Refer to the following common commands.
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
jupyter kernelspec list
|
|
189
|
+
jupyter kernelspec uninstall lasagnastack
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
3. Start the Jupyter server.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
jupyter lab
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## This repo is cool because...
|
|
199
|
+
|
|
200
|
+
- The pipeline is modularlised into stages, with each stage being responsible for transforming the global state of the pipeline run (similar to LangGraph). It is easy to add, remove, or reorder stages.
|
|
201
|
+
- The pipeline supports "skills" -- each user can write their own skill `.md` file to customise the pipeline to their own accounts' styles and branding, or use pre-written skills from marketplaces to cater for different types of reel content.
|
|
202
|
+
- Chain-of-thought reasoning is enabled via Gemini.
|
|
203
|
+
- Human-in-the-loop is deeply integrated in the design, with each stage prompting the user for confirmation before proceeding to the next stage.
|
|
204
|
+
- Prompt caching is enabled to avoid unnecessary LLM calls to reduce latency and cost.
|
|
205
|
+
- The tool is deeply integrated with its host machine. It auto-detects CapCut Desktop, copies all source media (timeline clips and unused footage) so the project opens in CapCut with no missing-media errors, no manual steps, all your raw clips already in the import panel, and the timeline editor populated and ready to go.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# LasagnaStack
|
|
2
|
+
|
|
3
|
+
<img src="docs/lasagna.png" alt="LasagnaStack" width="180" />
|
|
4
|
+
|
|
5
|
+
An AI pipeline that turns raw video clips into an editable CapCut project for short-form reel editing.
|
|
6
|
+
|
|
7
|
+
It is as simple as:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
python -m lasagnastack make ./my_clips/ --out ./my_capcut_draft/
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
where...
|
|
14
|
+
|
|
15
|
+
`./my_clips/`: a folder of raw video clips in MP4/MOV format + one `.txt` creator brief.
|
|
16
|
+
`./my_capcut_draft/`: a CapCut draft folder, ready to open in CapCut Desktop.
|
|
17
|
+
|
|
18
|
+
The pipeline runs in six sequential stages: **ingest** (uses ffmpeg) → **analyse** (uses LLM) → **direct** (uses LLM) → **critique loop** (uses LLM) → **enhance** (uses LLM) → **render** (uses pyCapCut).
|
|
19
|
+
|
|
20
|
+
Each stage is a subclass of the `Stage` abstract base class (`base.py`). Adding, removing, or reordering stages requires only editing the `stages` list in `ReelPipeline`. See [`ARCHITECTURE.md`](ARCHITECTURE.md) for the full architecture guide.
|
|
21
|
+
|
|
22
|
+
## Get started with development
|
|
23
|
+
|
|
24
|
+
1. Clone the repository.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git clone https://github.com/jyjulianwong/LasagnaStack.git
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
2. Verify that you have a compatible Python version installed on your machine.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
python --version
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. Install [uv](https://github.com/astral-sh/uv) (used as the package manager for this project).
|
|
37
|
+
|
|
38
|
+
4. Install the development dependencies.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
cd LasagnaStack/
|
|
42
|
+
uv sync --all-groups
|
|
43
|
+
uv run pre-commit install
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Set up environment
|
|
47
|
+
|
|
48
|
+
Copy `.env.sample` to `.env` and fill in your values:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
cp .env.sample .env
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`.env` is gitignored. Values set in the shell environment take precedence over `.env`.
|
|
55
|
+
|
|
56
|
+
## Authentication
|
|
57
|
+
|
|
58
|
+
Get a Gemini API key at [aistudio.google.com/apikey](https://aistudio.google.com/apikey) and add it to your `.env`:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
LSNSTK_LLM_GEMINI_API_KEY=your-key-here
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Run the pipeline
|
|
65
|
+
|
|
66
|
+
Prepare an input folder containing your MP4/MOV clips and exactly one `.txt` brief file, then run:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
uv run python -m lasagnastack make ./my_clips/ --out ./drafts/reel_2025_05_05
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The pipeline pauses for confirmation between each stage. To skip all prompts:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uv run python -m lasagnastack make ./my_clips/ --out ./drafts/reel_2025_05_05 --yes
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Full CLI reference:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
usage: lasagnastack make [-h] --out OUTPUT_DIR [--skill SKILL_FILE] [--yes]
|
|
82
|
+
[--critique-max-retries N] [--ingest-max-workers N]
|
|
83
|
+
[--analyse-max-workers N] INPUT_DIR
|
|
84
|
+
|
|
85
|
+
positional arguments:
|
|
86
|
+
INPUT_DIR Folder containing clips and brief .txt
|
|
87
|
+
|
|
88
|
+
options:
|
|
89
|
+
--out OUTPUT_DIR Destination for the CapCut draft and working files
|
|
90
|
+
--skill SKILL_FILE Path to Markdown skill file injected into the direct,
|
|
91
|
+
critique, and enhance prompt templates (optional)
|
|
92
|
+
--yes, -y Auto-confirm all stage prompts
|
|
93
|
+
--critique-max-retries N Maximum # of critique loop retries (default: 2)
|
|
94
|
+
--ingest-max-workers N Maximum # of parallel worker processes for `ingest` stage (default: 2)
|
|
95
|
+
--analyse-max-workers N Maximum # of concurrent LLM calls for `analyse` stage (default: 4)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Open the draft in CapCut Desktop (macOS)
|
|
99
|
+
|
|
100
|
+
If CapCut Desktop is installed, the pipeline automatically:
|
|
101
|
+
|
|
102
|
+
1. Detects `~/Movies/CapCut/User Data/`
|
|
103
|
+
2. Copies **all** `.mp4`/`.mov` files from your input folder into the CapCut draft folder — including clips not used on the timeline — so they are immediately available in CapCut's import panel
|
|
104
|
+
3. Rewrites the timeline clip paths in `draft_info.json` to point to the copied files
|
|
105
|
+
4. Registers the draft in `root_meta_info.json` so it appears on the CapCut home screen straight away
|
|
106
|
+
|
|
107
|
+
Open CapCut Desktop after the pipeline finishes — the draft will appear on the home screen under your local projects with all media already linked. Drafts are named **LasagnaStack - Reel Name** and use that same string as the folder name so they are easy to identify among existing projects.
|
|
108
|
+
|
|
109
|
+
If CapCut is not installed, the draft is written to `<output_dir>/draft/LasagnaStack - {reel_name}/` and you can copy it manually.
|
|
110
|
+
|
|
111
|
+
> This has been tested with CapCut Desktop 8.5.0 on macOS Sequoia 15.6.1. There may be issues with older versions or other operating systems.
|
|
112
|
+
|
|
113
|
+
## Track LLM costs with MLflow
|
|
114
|
+
|
|
115
|
+
Every pipeline run is automatically traced with [MLflow](https://mlflow.org). Each Gemini API call is recorded as a span (prompt, response, token counts, latency, and estimated USD cost). Session-level totals are written to the run when the pipeline finishes.
|
|
116
|
+
|
|
117
|
+
**1. Start the MLflow server** (in a separate terminal, before running the pipeline):
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
mlflow server --host 127.0.0.1 --port 5001
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
> **macOS note:** port 5000 is reserved by AirPlay Receiver. Use 5001 or higher.
|
|
124
|
+
|
|
125
|
+
**2. Add the tracking variables to `.env`:**
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
MLFLOW_TRACKING_URI=http://localhost:5001
|
|
129
|
+
MLFLOW_EXPERIMENT_NAME=lasagnastack
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**3. Run the pipeline as normal.** Open `http://localhost:5000` in your browser to watch live.
|
|
133
|
+
|
|
134
|
+
In **Experiments -> lasagnastack -> Traces**, spans appear in real time as stages progress. Each trace has three levels: the top-level pipeline span (`ReelPipeline.run`), a per-stage span (e.g. `AnalyseStage.run`), and individual LLM call spans (`GeminiClient._call_api`) nested inside.
|
|
135
|
+
|
|
136
|
+
Runs are named `lasagnastack-{brief_stem}-{4-char-id}` and tagged with the model, reel name, and `critique_max_retries`.
|
|
137
|
+
|
|
138
|
+
> **No server?** Set `MLFLOW_TRACKING_URI=mlruns` to write results to a local folder instead, then view them with `mlflow ui`.
|
|
139
|
+
|
|
140
|
+
## Configuration
|
|
141
|
+
|
|
142
|
+
| Parameter | How to set | Default |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| LLM model | `LSNSTK_LLM_MODEL` env. var. | `gemini/gemini-2.5-flash` |
|
|
145
|
+
| Gemini API key | `LSNSTK_LLM_GEMINI_API_KEY` env. var. (required) | — |
|
|
146
|
+
| Path to skill file | `--skill` CLI flag | — |
|
|
147
|
+
| `critique` stage maximum # of retries | `--critique-max-retries` CLI flag | `2` |
|
|
148
|
+
| `ingest` stage maximum # of worker processes | `--ingest-max-workers` CLI flag | `2` |
|
|
149
|
+
| `analyse` stage maximum # of concurrent LLM calls | `--analyse-max-workers` CLI flag | `4` |
|
|
150
|
+
|
|
151
|
+
## Architecture
|
|
152
|
+
|
|
153
|
+
See [`ARCHITECTURE.md`](ARCHITECTURE.md) for four annotated diagrams covering the pipeline data flow, the Stage 4 critique loop, the Stage 6 render + CapCut export, and the extensibility model.
|
|
154
|
+
|
|
155
|
+
## Get started with Jupyter notebooks
|
|
156
|
+
|
|
157
|
+
1. Once the above setup is complete, set up a Python kernel.
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
source .venv/bin/activate
|
|
161
|
+
python -m ipykernel install --user --name=lasagnastack
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
2. Refer to the following common commands.
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
jupyter kernelspec list
|
|
168
|
+
jupyter kernelspec uninstall lasagnastack
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
3. Start the Jupyter server.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
jupyter lab
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## This repo is cool because...
|
|
178
|
+
|
|
179
|
+
- The pipeline is modularlised into stages, with each stage being responsible for transforming the global state of the pipeline run (similar to LangGraph). It is easy to add, remove, or reorder stages.
|
|
180
|
+
- The pipeline supports "skills" -- each user can write their own skill `.md` file to customise the pipeline to their own accounts' styles and branding, or use pre-written skills from marketplaces to cater for different types of reel content.
|
|
181
|
+
- Chain-of-thought reasoning is enabled via Gemini.
|
|
182
|
+
- Human-in-the-loop is deeply integrated in the design, with each stage prompting the user for confirmation before proceeding to the next stage.
|
|
183
|
+
- Prompt caching is enabled to avoid unnecessary LLM calls to reduce latency and cost.
|
|
184
|
+
- The tool is deeply integrated with its host machine. It auto-detects CapCut Desktop, copies all source media (timeline clips and unused footage) so the project opens in CapCut with no missing-media errors, no manual steps, all your raw clips already in the import panel, and the timeline editor populated and ready to go.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "lasagnastack"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "An AI pipeline that turns raw video clips into an editable CapCut project for short-form reel editing."
|
|
9
|
+
authors = [
|
|
10
|
+
{ name = "Julian Wong", email = "julianwong2000@gmail.com" }
|
|
11
|
+
]
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.12,<3.13"
|
|
14
|
+
dependencies = [
|
|
15
|
+
"av>=14.0.0",
|
|
16
|
+
"ffmpeg-python>=0.2.0",
|
|
17
|
+
"google-genai>=1.0.0",
|
|
18
|
+
"mlflow>=2.19.0",
|
|
19
|
+
"opencv-python-headless>=4.0.0",
|
|
20
|
+
"pycapcut>=0.0.3",
|
|
21
|
+
"pydantic>=2.0.0",
|
|
22
|
+
"python-dotenv>=1.0.0",
|
|
23
|
+
"python-semantic-release>=10.5.3",
|
|
24
|
+
"scenedetect>=0.6.4",
|
|
25
|
+
"setuptools>=80.9.0",
|
|
26
|
+
"structlog>=25.0.0",
|
|
27
|
+
"tenacity>=9.0.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[dependency-groups]
|
|
31
|
+
dev = [
|
|
32
|
+
"pre-commit>=4.2.0",
|
|
33
|
+
"pyrefly>=0.26.0",
|
|
34
|
+
"pytest>=7.2.0",
|
|
35
|
+
"ruff>=0.11.1",
|
|
36
|
+
"uv-sort==0.6.0",
|
|
37
|
+
]
|
|
38
|
+
docs = [
|
|
39
|
+
"pdoc>=15.0.4",
|
|
40
|
+
]
|
|
41
|
+
notebook = [
|
|
42
|
+
"ipykernel>=6.30.0",
|
|
43
|
+
"ipython>=9.4.0",
|
|
44
|
+
"jupyterlab>=4.4.5",
|
|
45
|
+
"matplotlib>=3.10.3",
|
|
46
|
+
"nbconvert>=7.16.6",
|
|
47
|
+
"notebook>=7.4.4",
|
|
48
|
+
"plotly>=6.2.0",
|
|
49
|
+
"seaborn>=0.13.2",
|
|
50
|
+
"voila>=0.5.8",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[tool.setuptools.packages.find]
|
|
54
|
+
where = ["src"]
|
|
55
|
+
|
|
56
|
+
[tool.ruff]
|
|
57
|
+
line-length = 88
|
|
58
|
+
indent-width = 4
|
|
59
|
+
exclude = [
|
|
60
|
+
"build",
|
|
61
|
+
"dist",
|
|
62
|
+
"__pycache__",
|
|
63
|
+
"*.ipynb"
|
|
64
|
+
]
|
|
65
|
+
fix = true
|
|
66
|
+
|
|
67
|
+
[tool.ruff.lint.pycodestyle]
|
|
68
|
+
ignore-overlong-task-comments = true
|
|
69
|
+
|
|
70
|
+
[tool.ruff.lint]
|
|
71
|
+
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
|
72
|
+
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
|
|
73
|
+
# McCabe complexity (`C901`) by default.
|
|
74
|
+
select = ["E4", "E7", "E9", "F", "I"]
|
|
75
|
+
ignore = []
|
|
76
|
+
|
|
77
|
+
# Allow fix for all enabled rules (when `--fix`) is provided.
|
|
78
|
+
fixable = ["ALL"]
|
|
79
|
+
unfixable = []
|
|
80
|
+
|
|
81
|
+
task-tags = ["HACK", "TODO"]
|
|
82
|
+
|
|
83
|
+
[tool.pydocstyle]
|
|
84
|
+
convention = "google"
|
|
85
|
+
add-ignore = "D104,D418"
|
|
86
|
+
|
|
87
|
+
[tool.pyrefly]
|
|
88
|
+
# Set the directory Pyrefly will search for files to type check
|
|
89
|
+
project-includes = ["src/lasagnastack/*"]
|
|
90
|
+
project-excludes = ["**/*venv/**/*"]
|
|
91
|
+
|
|
92
|
+
# Manually set the `sys.platform` Pyrefly will assume when type checking
|
|
93
|
+
python-platform = "darwin"
|
|
94
|
+
|
|
95
|
+
# Return an import error when `<library>-stubs` can be imported, but no non-stubs version of that library can be found
|
|
96
|
+
ignore-missing-source = false
|
|
97
|
+
|
|
98
|
+
# A table mapping error codes to an `is-enabled` boolean
|
|
99
|
+
[tool.pyrefly.errors]
|
|
100
|
+
# Disable `bad-assignment` errors
|
|
101
|
+
bad-assignment = false
|
|
102
|
+
# Disable `bad-return` errors
|
|
103
|
+
bad-return = false
|
|
104
|
+
|
|
105
|
+
[tool.semantic_release]
|
|
106
|
+
version_toml = ["pyproject.toml:project.version"]
|
|
File without changes
|