@thunderkiller/video-clipper 1.5.5 → 1.6.0
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.
- package/README.md +69 -349
- package/dist/config/env.d.ts +4 -0
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/index.d.ts +0 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pipeline/dumper.d.ts.map +1 -0
- package/dist/{utils → pipeline}/dumper.js +1 -1
- package/dist/pipeline/dumper.js.map +1 -0
- package/dist/pipeline/runner.d.ts.map +1 -1
- package/dist/pipeline/runner.js +80 -73
- package/dist/pipeline/runner.js.map +1 -1
- package/dist/pipeline/stages/audioProcessor.d.ts +0 -1
- package/dist/pipeline/stages/audioProcessor.d.ts.map +1 -1
- package/dist/pipeline/stages/audioProcessor.js +1 -1
- package/dist/pipeline/stages/audioProcessor.js.map +1 -1
- package/dist/pipeline/stages/clipExporter.d.ts +0 -1
- package/dist/pipeline/stages/clipExporter.d.ts.map +1 -1
- package/dist/pipeline/stages/clipExporter.js.map +1 -1
- package/dist/pipeline/stages/segmentAnalyzer.d.ts +1 -2
- package/dist/pipeline/stages/segmentAnalyzer.d.ts.map +1 -1
- package/dist/pipeline/stages/segmentAnalyzer.js +2 -2
- package/dist/pipeline/stages/segmentAnalyzer.js.map +1 -1
- package/dist/pipeline/stages/segmentSelector.d.ts +0 -1
- package/dist/pipeline/stages/segmentSelector.d.ts.map +1 -1
- package/dist/pipeline/stages/segmentSelector.js +1 -2
- package/dist/pipeline/stages/segmentSelector.js.map +1 -1
- package/dist/pipeline/stages/videoResolver.d.ts +0 -1
- package/dist/pipeline/stages/videoResolver.d.ts.map +1 -1
- package/dist/pipeline/stages/videoResolver.js.map +1 -1
- package/dist/services/audioAnalyzers/index.d.ts +0 -4
- package/dist/services/audioAnalyzers/index.d.ts.map +1 -1
- package/dist/services/audioAnalyzers/index.js +0 -3
- package/dist/services/audioAnalyzers/index.js.map +1 -1
- package/dist/services/audioAnalyzers/whisper.d.ts +0 -1
- package/dist/services/audioAnalyzers/whisper.d.ts.map +1 -1
- package/dist/services/audioAnalyzers/whisper.js +1 -21
- package/dist/services/audioAnalyzers/whisper.js.map +1 -1
- package/dist/services/audioAnalyzers/yamnet.js +1 -1
- package/dist/services/audioAnalyzers/yamnet.js.map +1 -1
- package/dist/services/audioDownloader/index.d.ts.map +1 -1
- package/dist/services/audioDownloader/index.js +3 -14
- package/dist/services/audioDownloader/index.js.map +1 -1
- package/dist/services/audioDownloader/sliceAudio.d.ts.map +1 -0
- package/dist/{utils → services/audioDownloader}/sliceAudio.js +1 -1
- package/dist/services/audioDownloader/sliceAudio.js.map +1 -0
- package/dist/services/clipGenerator/index.js +0 -16
- package/dist/services/clipGenerator/index.js.map +1 -1
- package/dist/services/clipRefiner/index.d.ts +2 -1
- package/dist/services/clipRefiner/index.d.ts.map +1 -1
- package/dist/services/clipRefiner/index.js +3 -5
- package/dist/services/clipRefiner/index.js.map +1 -1
- package/dist/services/llmAnalyzer/LLMAnalyzer.d.ts +2 -2
- package/dist/services/llmAnalyzer/LLMAnalyzer.d.ts.map +1 -1
- package/dist/services/llmAnalyzer/LLMAnalyzer.js +2 -2
- package/dist/services/llmAnalyzer/LLMAnalyzer.js.map +1 -1
- package/dist/services/llmAnalyzer/index.d.ts +3 -2
- package/dist/services/llmAnalyzer/index.d.ts.map +1 -1
- package/dist/services/llmAnalyzer/index.js +5 -7
- package/dist/services/llmAnalyzer/index.js.map +1 -1
- package/dist/services/segmentRanker/index.d.ts +2 -1
- package/dist/services/segmentRanker/index.d.ts.map +1 -1
- package/dist/services/segmentRanker/index.js +36 -0
- package/dist/services/segmentRanker/index.js.map +1 -1
- package/dist/services/transcriptAnalyzers/index.d.ts +0 -4
- package/dist/services/transcriptAnalyzers/index.d.ts.map +1 -1
- package/dist/services/transcriptAnalyzers/index.js +0 -3
- package/dist/services/transcriptAnalyzers/index.js.map +1 -1
- package/dist/services/transcriptAnalyzers/whisper.js +1 -1
- package/dist/services/transcriptAnalyzers/whisper.js.map +1 -1
- package/dist/services/transcriptAnalyzers/ytdlp.d.ts +11 -0
- package/dist/services/transcriptAnalyzers/ytdlp.d.ts.map +1 -1
- package/dist/services/transcriptAnalyzers/ytdlp.js +120 -1
- package/dist/services/transcriptAnalyzers/ytdlp.js.map +1 -1
- package/dist/services/transcriptDetector/index.d.ts +2 -2
- package/dist/services/transcriptDetector/index.d.ts.map +1 -1
- package/dist/services/transcriptDetector/index.js.map +1 -1
- package/dist/services/videoDownloader/index.d.ts.map +1 -1
- package/dist/services/videoDownloader/index.js +4 -19
- package/dist/services/videoDownloader/index.js.map +1 -1
- package/dist/types/analyzer.d.ts +2 -1
- package/dist/types/analyzer.d.ts.map +1 -1
- package/dist/types/config.d.ts +7 -3
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +12 -0
- package/dist/types/config.js.map +1 -1
- package/dist/types/downloader.d.ts.map +1 -1
- package/dist/types/pipeline.d.ts +3 -1
- package/dist/types/pipeline.d.ts.map +1 -1
- package/dist/utils/cache.d.ts +14 -18
- package/dist/utils/cache.d.ts.map +1 -1
- package/dist/utils/cache.js +32 -112
- package/dist/utils/cache.js.map +1 -1
- package/dist/utils/cacheBackend.d.ts +40 -0
- package/dist/utils/cacheBackend.d.ts.map +1 -0
- package/dist/utils/cacheBackend.js +28 -0
- package/dist/utils/cacheBackend.js.map +1 -0
- package/dist/utils/cacheFactory.d.ts +14 -0
- package/dist/utils/cacheFactory.d.ts.map +1 -0
- package/dist/utils/cacheFactory.js +31 -0
- package/dist/utils/cacheFactory.js.map +1 -0
- package/dist/utils/chunker.d.ts +0 -1
- package/dist/utils/chunker.d.ts.map +1 -1
- package/dist/utils/chunker.js.map +1 -1
- package/dist/utils/fileCacheBackend.d.ts +33 -0
- package/dist/utils/fileCacheBackend.d.ts.map +1 -0
- package/dist/utils/fileCacheBackend.js +123 -0
- package/dist/utils/fileCacheBackend.js.map +1 -0
- package/dist/utils/format.d.ts +6 -0
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +20 -0
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/logger.d.ts +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +10 -0
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/mongoCacheBackend.d.ts +51 -0
- package/dist/utils/mongoCacheBackend.d.ts.map +1 -0
- package/dist/utils/mongoCacheBackend.js +176 -0
- package/dist/utils/mongoCacheBackend.js.map +1 -0
- package/dist/utils/pythonBin.d.ts +2 -0
- package/dist/utils/pythonBin.d.ts.map +1 -0
- package/dist/utils/pythonBin.js +24 -0
- package/dist/utils/pythonBin.js.map +1 -0
- package/package.json +2 -1
- package/dist/services/signalMerger/index.d.ts +0 -5
- package/dist/services/signalMerger/index.d.ts.map +0 -1
- package/dist/services/signalMerger/index.js +0 -37
- package/dist/services/signalMerger/index.js.map +0 -1
- package/dist/services/transcriptFetcher/index.d.ts +0 -26
- package/dist/services/transcriptFetcher/index.d.ts.map +0 -1
- package/dist/services/transcriptFetcher/index.js +0 -121
- package/dist/services/transcriptFetcher/index.js.map +0 -1
- package/dist/utils/dumper.d.ts.map +0 -1
- package/dist/utils/dumper.js.map +0 -1
- package/dist/utils/redactConfig.d.ts +0 -7
- package/dist/utils/redactConfig.d.ts.map +0 -1
- package/dist/utils/redactConfig.js +0 -21
- package/dist/utils/redactConfig.js.map +0 -1
- package/dist/utils/sliceAudio.d.ts.map +0 -1
- package/dist/utils/sliceAudio.js.map +0 -1
- /package/dist/{utils → pipeline}/dumper.d.ts +0 -0
- /package/dist/{utils → services/audioDownloader}/sliceAudio.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# video-clipper
|
|
1
|
+
# @thunderkiller/video-clipper
|
|
2
2
|
|
|
3
|
-
A TypeScript CLI
|
|
3
|
+
A TypeScript CLI (and library) that analyzes a YouTube video with an LLM, finds the most interesting moments, and optionally downloads the video and cuts clips automatically.
|
|
4
4
|
|
|
5
|
-
## How
|
|
5
|
+
## How It Works
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
YouTube URL
|
|
@@ -11,10 +11,10 @@ YouTube URL
|
|
|
11
11
|
Parse URL → fetch transcript → group into chunks
|
|
12
12
|
│
|
|
13
13
|
▼
|
|
14
|
-
Parallel LLM analysis (Vercel AI SDK
|
|
14
|
+
Parallel LLM analysis (Vercel AI SDK — OpenAI, Anthropic, Google, and more)
|
|
15
15
|
│
|
|
16
16
|
▼
|
|
17
|
-
|
|
17
|
+
Merge with audio event detection → rank & deduplicate segments
|
|
18
18
|
│
|
|
19
19
|
▼
|
|
20
20
|
Refine clip boundaries (second LLM pass)
|
|
@@ -23,132 +23,80 @@ Refine clip boundaries (second LLM pass)
|
|
|
23
23
|
(Optional) Download video + cut clips with ffmpeg
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
## Tech Stack
|
|
27
|
-
|
|
28
|
-
| Layer | Choice |
|
|
29
|
-
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
30
|
-
| Language | TypeScript (Node.js 18+) |
|
|
31
|
-
| Transcript | `youtube-transcript` |
|
|
32
|
-
| LLM | Vercel AI SDK (`ai` + `@ai-sdk/openai`, `@ai-sdk/anthropic`, `@ai-sdk/google`, `@ai-sdk/xai`, `@ai-sdk/mistral`, `@ai-sdk/groq`, `@ai-sdk/openrouter`) |
|
|
33
|
-
| Structured output | `generateObject` + `zod` |
|
|
34
|
-
| Video download | `yt-dlp` via `execa` |
|
|
35
|
-
| Clip cutting | `fluent-ffmpeg` |
|
|
36
|
-
| Config validation | `zod` |
|
|
37
|
-
| Concurrency | `p-limit` |
|
|
38
|
-
|
|
39
26
|
## Requirements
|
|
40
27
|
|
|
41
28
|
- Node.js 18+
|
|
42
|
-
- `yt-dlp`
|
|
43
|
-
- `ffmpeg`
|
|
29
|
+
- [`yt-dlp`](https://github.com/yt-dlp/yt-dlp) — for video download
|
|
30
|
+
- [`ffmpeg`](https://ffmpeg.org) — for clip cutting
|
|
44
31
|
|
|
45
32
|
```bash
|
|
46
33
|
# macOS
|
|
47
34
|
brew install yt-dlp ffmpeg
|
|
48
35
|
```
|
|
49
36
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
Clips are generated by re-encoding with `libx264` (video) and `aac` (audio) to ensure perfect audio/video synchronization. This is slower than stream copy mode but prevents the common issue where video and audio become desynchronized in the output clips.
|
|
53
|
-
|
|
54
|
-
**Performance vs Quality Trade-off:**
|
|
55
|
-
|
|
56
|
-
Use the `FFMPEG_PRESET` environment variable to adjust encoding speed:
|
|
57
|
-
|
|
58
|
-
| Preset | Speed | Quality | Use Case |
|
|
59
|
-
| ---------------- | --------- | ------- | ---------------------- |
|
|
60
|
-
| `ultrafast` | Very fast | Lowest | Quick testing |
|
|
61
|
-
| `fast` (default) | Fast | Good | Balanced performance |
|
|
62
|
-
| `medium` | Medium | Better | Higher quality clips |
|
|
63
|
-
| `slow` | Slow | High | Final production clips |
|
|
64
|
-
|
|
65
|
-
Example:
|
|
37
|
+
## Installation
|
|
66
38
|
|
|
67
39
|
```bash
|
|
68
|
-
#
|
|
69
|
-
|
|
40
|
+
# Global CLI
|
|
41
|
+
npm install -g @thunderkiller/video-clipper
|
|
42
|
+
|
|
43
|
+
# One-off with npx (no install)
|
|
44
|
+
npx @thunderkiller/video-clipper <url>
|
|
70
45
|
|
|
71
|
-
#
|
|
72
|
-
|
|
46
|
+
# As a library
|
|
47
|
+
npm install @thunderkiller/video-clipper
|
|
73
48
|
```
|
|
74
49
|
|
|
75
|
-
##
|
|
50
|
+
## Quick Start
|
|
76
51
|
|
|
77
|
-
|
|
78
|
-
npm install
|
|
79
|
-
cp .env.example .env
|
|
80
|
-
```
|
|
52
|
+
**1. Configure your LLM provider**
|
|
81
53
|
|
|
82
|
-
|
|
54
|
+
Create a `.env` file in your working directory:
|
|
83
55
|
|
|
84
56
|
```env
|
|
85
|
-
# Choose your provider (openai, anthropic, google, xai, mistral, groq, zai, openrouter)
|
|
86
57
|
LLM_PROVIDER=openai
|
|
87
|
-
OPENAI_API_KEY=
|
|
88
|
-
|
|
89
|
-
# Or use a free model via OpenRouter:
|
|
90
|
-
# LLM_PROVIDER=openrouter
|
|
91
|
-
# OPENROUTER_API_KEY=sk-or-...
|
|
92
|
-
# LLM_MODEL=meta-llama/llama-3.3-70b-instruct:free
|
|
58
|
+
OPENAI_API_KEY=sk-...
|
|
93
59
|
```
|
|
94
60
|
|
|
95
|
-
|
|
61
|
+
Or use a free model via OpenRouter:
|
|
96
62
|
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
63
|
+
```env
|
|
64
|
+
LLM_PROVIDER=openrouter
|
|
65
|
+
OPENROUTER_API_KEY=sk-or-...
|
|
66
|
+
LLM_MODEL=meta-llama/llama-3.3-70b-instruct:free
|
|
67
|
+
```
|
|
100
68
|
|
|
101
|
-
|
|
102
|
-
npm run start -- <youtube-url> --download
|
|
69
|
+
**2. Run**
|
|
103
70
|
|
|
104
|
-
|
|
105
|
-
|
|
71
|
+
```bash
|
|
72
|
+
# Analyze only — prints ranked segments as JSON
|
|
73
|
+
video-clipper https://youtube.com/watch?v=VIDEO_ID
|
|
106
74
|
|
|
107
|
-
#
|
|
108
|
-
|
|
75
|
+
# Analyze and cut clips (downloads video, runs ffmpeg)
|
|
76
|
+
video-clipper https://youtube.com/watch?v=VIDEO_ID --clip
|
|
109
77
|
|
|
110
|
-
#
|
|
111
|
-
|
|
78
|
+
# Download only the top 3 segments (faster than full video)
|
|
79
|
+
video-clipper https://youtube.com/watch?v=VIDEO_ID --download-sections 3
|
|
112
80
|
```
|
|
113
81
|
|
|
114
|
-
##
|
|
115
|
-
|
|
116
|
-
All parameters are set via `.env`:
|
|
82
|
+
## CLI Flags
|
|
117
83
|
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
|
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
|
129
|
-
| `
|
|
130
|
-
|
|
|
131
|
-
|
|
|
132
|
-
| `
|
|
133
|
-
|
|
|
134
|
-
| `LLM_SYSTEM_PROMPT` | (default prompt) | Custom system prompt for LLM analysis |
|
|
135
|
-
| **Analysis parameters** |
|
|
136
|
-
| `SCORE_THRESHOLD` | `7` | Minimum score (1–10) to keep a segment |
|
|
137
|
-
| `TOP_N_SEGMENTS` | `10` | Max number of segments to return |
|
|
138
|
-
| `CHUNK_LENGTH_SEC` | `120` | LLM analysis window size in seconds |
|
|
139
|
-
| `CHUNK_OVERLAP_SEC` | `20` | Overlap between consecutive chunks |
|
|
140
|
-
| `MICRO_BLOCK_SEC` | `15` | Transcript grouping window in seconds |
|
|
141
|
-
| `MAX_CHUNKS` | — | Limit number of chunks sent to LLM (optional) |
|
|
142
|
-
| **Video download** |
|
|
143
|
-
| `DOWNLOAD_SECTIONS_MODE` | `all` | yt-dlp mode: all (full video) or N (top N segments only, e.g. 1, 2, 3...) |
|
|
144
|
-
| `FFMPEG_PRESET` | `fast` | ffmpeg encoding preset: ultrafast, superfast, veryfast, fast (default), medium, slow, slower |
|
|
145
|
-
| `TIMESTAMP_OFFSET_SECONDS` | `0` | Adjust all clip timestamps (positive = later, negative = earlier) to fix transcript-video misalignment |
|
|
146
|
-
| **Paths** |
|
|
147
|
-
| `DOWNLOAD_DIR` | `downloads/` | Where to store downloaded videos |
|
|
148
|
-
| `OUTPUT_DIR` | `outputs/` | Where to store generated clips and dumps |
|
|
149
|
-
| `CACHE_DIR` | `outputs/cache` | Where to store transcript and LLM result cache |
|
|
150
|
-
| **Output options** |
|
|
151
|
-
| `DUMP_OUTPUTS` | `true` | Write transcript/analysis JSON dumps |
|
|
84
|
+
| Flag | Description |
|
|
85
|
+
| -------------------------- | ------------------------------------------------------------------------ |
|
|
86
|
+
| `--clip` | Download video and generate mp4 clips for each segment |
|
|
87
|
+
| `--download-sections <n>` | Download only top N segments via yt-dlp `--download-sections` (e.g. `3`) |
|
|
88
|
+
| `--local-video <path>` | Cut clips from a local video file — skips yt-dlp download entirely |
|
|
89
|
+
| `--video-path <path>` | Custom output directory for downloaded videos and clips |
|
|
90
|
+
| `--threshold <n>` | Minimum score (1–10) to keep a segment (default: `7`) |
|
|
91
|
+
| `--top-n <n>` | Maximum number of segments to return (default: `10`) |
|
|
92
|
+
| `--max-duration <s>` | Abort if video is longer than N seconds |
|
|
93
|
+
| `--max-chunks <n>` | Limit number of transcript chunks sent to LLM |
|
|
94
|
+
| `--max-parallel <n>` | Max parallel LLM calls |
|
|
95
|
+
| `--no-audio` | Disable audio event detection (transcript-only mode) |
|
|
96
|
+
| `--game-profile <profile>` | Audio event profile: `valorant`, `fps`, `boss_fight`, `general` |
|
|
97
|
+
| `--output-json <path>` | Write output JSON to file instead of stdout |
|
|
98
|
+
| `--no-cache` | Bypass all caches and force a fresh run |
|
|
99
|
+
| `--help, -h` | Show help message |
|
|
152
100
|
|
|
153
101
|
## Output
|
|
154
102
|
|
|
@@ -163,267 +111,39 @@ All parameters are set via `.env`:
|
|
|
163
111
|
"start": 120,
|
|
164
112
|
"end": 150,
|
|
165
113
|
"score": 9,
|
|
166
|
-
"reason": "strong controversial opinion"
|
|
114
|
+
"reason": "strong controversial opinion",
|
|
115
|
+
"source": "transcript"
|
|
167
116
|
},
|
|
168
117
|
{
|
|
169
118
|
"rank": 2,
|
|
170
119
|
"start": 420,
|
|
171
120
|
"end": 455,
|
|
172
121
|
"score": 8,
|
|
173
|
-
"reason": "funny storytelling moment"
|
|
122
|
+
"reason": "funny storytelling moment",
|
|
123
|
+
"source": "both"
|
|
174
124
|
}
|
|
175
125
|
]
|
|
176
126
|
}
|
|
177
127
|
```
|
|
178
128
|
|
|
179
|
-
##
|
|
180
|
-
|
|
181
|
-
The CLI caches both transcript fetches and LLM chunk results to speed up subsequent runs:
|
|
182
|
-
|
|
183
|
-
- **Transcript cache**: Stored per video ID in `CACHE_DIR`
|
|
184
|
-
- **LLM chunk cache**: Stores successful chunk analyses to avoid re-analyzing the same content
|
|
185
|
-
|
|
186
|
-
Cache is automatically used on re-runs. Use `--no-cache` to bypass.
|
|
187
|
-
|
|
188
|
-
## Working with Pre-Downloaded Videos
|
|
189
|
-
|
|
190
|
-
If you already have a video downloaded (from yt-dlp, browser download, or other tool), you can skip the download step and work directly with that file.
|
|
191
|
-
|
|
192
|
-
**Workflow:**
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
# Step 1: Run analysis once to get segment timestamps
|
|
196
|
-
npm run start -- <url> --output-json analysis.json
|
|
197
|
-
|
|
198
|
-
# Step 2: (Optional) Edit timestamps in analysis.json if needed
|
|
199
|
-
# Edit the "start" and "end" values for each segment
|
|
200
|
-
|
|
201
|
-
# Step 3: Place your video in downloads/ directory
|
|
202
|
-
cp /path/to/your/video.mp4 downloads/<videoId>.mp4
|
|
203
|
-
|
|
204
|
-
# Step 4: Run again - will skip download and use your video
|
|
205
|
-
npm run start -- <url> --clip
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
**Use cases:**
|
|
209
|
-
|
|
210
|
-
- **Testing different settings** - Run different clip configurations without re-downloading
|
|
211
|
-
- **Manual timestamp adjustment** - Fine-tune segment boundaries based on visual inspection
|
|
212
|
-
- **Alternative video sources** - Work with videos downloaded from other tools or browsers
|
|
213
|
-
- **Large video files** - If you have a high-quality version, use that instead
|
|
214
|
-
|
|
215
|
-
**Notes:**
|
|
216
|
-
|
|
217
|
-
- The video file must be named exactly `{videoId}.mp4` in the `DOWNLOAD_DIR`
|
|
218
|
-
- You can apply `TIMESTAMP_OFFSET_SECONDS` globally instead of editing each timestamp
|
|
219
|
-
- Transcript cache is used, so re-running is fast (no API calls)
|
|
220
|
-
|
|
221
|
-
### Combining with Timestamp Offset
|
|
222
|
-
|
|
223
|
-
For pre-downloaded videos with known sync issues:
|
|
224
|
-
|
|
225
|
-
```bash
|
|
226
|
-
# Skip download, apply 3-second offset to all clips
|
|
227
|
-
TIMESTAMP_OFFSET_SECONDS=-3 npm run start -- <url> --clip
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
The CLI will find the existing video in `downloads/`, skip the download step, and apply the offset to all clip generation.
|
|
231
|
-
|
|
232
|
-
## Usage
|
|
233
|
-
|
|
234
|
-
### Basic analysis (no download)
|
|
235
|
-
|
|
236
|
-
```bash
|
|
237
|
-
npm run start -- https://youtube.com/watch?v=abc123
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Download full video and generate clips
|
|
241
|
-
|
|
242
|
-
```bash
|
|
243
|
-
npm run start -- https://youtube.com/watch?v=abc123 --clip
|
|
244
|
-
```
|
|
129
|
+
## Programmatic API
|
|
245
130
|
|
|
246
|
-
|
|
131
|
+
```typescript
|
|
132
|
+
import { runPipeline, parseArgs, config } from '@thunderkiller/video-clipper';
|
|
247
133
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
npm run start -- https://youtube.com/watch?v=abc123 --download-sections 3
|
|
251
|
-
|
|
252
|
-
# Download top 5 segments
|
|
253
|
-
npm run start -- https://youtube.com/watch?v=abc123 --download-sections 5
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### Custom output directory
|
|
257
|
-
|
|
258
|
-
```bash
|
|
259
|
-
# Store clips in custom directory
|
|
260
|
-
npm run start -- https://youtube.com/watch?v=abc123 --clip --video-path ./my-clips
|
|
261
|
-
|
|
262
|
-
# Download segments to custom path
|
|
263
|
-
npm run start -- https://youtube.com/watch?v=abc123 --download-sections 3 --video-path ./downloads
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
### Custom thresholds
|
|
267
|
-
|
|
268
|
-
```bash
|
|
269
|
-
npm run start -- https://youtube.com/watch?v=abc123 --threshold 8 --top-n 5
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### Testing with limited chunks
|
|
273
|
-
|
|
274
|
-
```bash
|
|
275
|
-
npm run start -- https://youtube.com/watch?v=abc123 --max-chunks 3
|
|
134
|
+
const args = parseArgs(process.argv);
|
|
135
|
+
await runPipeline(args);
|
|
276
136
|
```
|
|
277
137
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
```bash
|
|
281
|
-
# Fix 3-second audio delay (shift earlier)
|
|
282
|
-
TIMESTAMP_OFFSET_SECONDS=-3 npm run start -- <url> --clip
|
|
283
|
-
|
|
284
|
-
# Fix 2-second early start (shift later)
|
|
285
|
-
TIMESTAMP_OFFSET_SECONDS=2 npm run start -- <url> --clip
|
|
286
|
-
|
|
287
|
-
# High quality, slower processing, with offset
|
|
288
|
-
FFMPEG_PRESET=slow TIMESTAMP_OFFSET_SECONDS=-3 npm run start -- <url> --clip
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
## Troubleshooting Audio Sync Issues
|
|
292
|
-
|
|
293
|
-
### Problem: Audio is delayed or starts early
|
|
294
|
-
|
|
295
|
-
**Symptoms:**
|
|
296
|
-
|
|
297
|
-
- Video starts at correct moment but audio plays 2-5 seconds later/earlier
|
|
298
|
-
- Lip movements don't match speech in the clip
|
|
299
|
-
- Content in clip doesn't match the transcript segment
|
|
300
|
-
|
|
301
|
-
**Root Causes:**
|
|
302
|
-
|
|
303
|
-
1. **Transcript misalignment** - Transcript timestamps don't perfectly match the video
|
|
304
|
-
- **Auto-generated captions**: Often have 1-3 second delays
|
|
305
|
-
- **Manual captions**: Usually more accurate but can have timing issues
|
|
306
|
-
- **Multiple caption tracks**: Transcripts from different video versions
|
|
307
|
-
|
|
308
|
-
2. **Millisecond precision loss** - Old implementation lost decimal seconds
|
|
309
|
-
- Now fixed: `--download-sections` uses HH:MM:SS.mmm format
|
|
310
|
-
|
|
311
|
-
3. **Version differences** - The transcript might be from a slightly different version of the video
|
|
312
|
-
|
|
313
|
-
### Solution: Use `TIMESTAMP_OFFSET_SECONDS`
|
|
314
|
-
|
|
315
|
-
**What it does:**
|
|
316
|
-
Applies a global offset to all clip timestamps. Positive = shift later, negative = shift earlier.
|
|
317
|
-
|
|
318
|
-
**How to use:**
|
|
319
|
-
|
|
320
|
-
```bash
|
|
321
|
-
# Add to .env
|
|
322
|
-
TIMESTAMP_OFFSET_SECONDS=-3
|
|
323
|
-
|
|
324
|
-
# Or inline
|
|
325
|
-
TIMESTAMP_OFFSET_SECONDS=-3 npm run start -- <url> --clip
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
### Finding the Correct Offset
|
|
329
|
-
|
|
330
|
-
**Step 1: Test with logging**
|
|
331
|
-
|
|
332
|
-
Run a single segment and observe the logs:
|
|
333
|
-
|
|
334
|
-
```bash
|
|
335
|
-
TIMESTAMP_OFFSET_SECONDS=0 npm run start -- <url> --download-sections 1
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
Look for these log lines:
|
|
339
|
-
|
|
340
|
-
```
|
|
341
|
-
[info] Downloading segment 1: 00:02:00.500-00:02:30.000 (strong opinion...)
|
|
342
|
-
[info] Requested: 120.50s - 150.00s
|
|
343
|
-
[info] Adjusted: 117.50s - 147.00s (offset: -3s)
|
|
344
|
-
[info] Cutting clip: start=117.50s, end=147.00s, duration=29.50s
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
**Step 2: Play and verify**
|
|
348
|
-
|
|
349
|
-
- Open the generated clip
|
|
350
|
-
- Check if the moment matches the transcript description
|
|
351
|
-
- Note if it's too early or too late
|
|
352
|
-
|
|
353
|
-
**Step 3: Adjust offset**
|
|
354
|
-
|
|
355
|
-
If clip **starts 3 seconds late**:
|
|
356
|
-
|
|
357
|
-
```bash
|
|
358
|
-
TIMESTAMP_OFFSET_SECONDS=-3 # Negative = shift earlier
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
If clip **starts 2 seconds early**:
|
|
362
|
-
|
|
363
|
-
```bash
|
|
364
|
-
TIMESTAMP_OFFSET_SECONDS=2 # Positive = shift later
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
**Step 4: Verify with multiple clips**
|
|
368
|
-
|
|
369
|
-
```bash
|
|
370
|
-
TIMESTAMP_OFFSET_SECONDS=-3 npm run start -- <url> --download-sections 3
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
Check if the offset works consistently across different segments.
|
|
374
|
-
|
|
375
|
-
### Binary Search for Optimal Offset
|
|
376
|
-
|
|
377
|
-
If you're unsure of the exact offset:
|
|
378
|
-
|
|
379
|
-
```bash
|
|
380
|
-
# Try 0, -3, -6, -9 to see which is closest
|
|
381
|
-
for offset in 0 -3 -6 -9; do
|
|
382
|
-
TIMESTAMP_OFFSET_SECONDS=$offset npm run start -- <url> --download-sections 1
|
|
383
|
-
echo "Tested offset: $offset"
|
|
384
|
-
# Play and check accuracy
|
|
385
|
-
done
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
Then narrow down: `-3` seems good, try `-2` and `-4`, etc.
|
|
389
|
-
|
|
390
|
-
### Common Scenarios
|
|
391
|
-
|
|
392
|
-
| Scenario | Likely Offset | Explanation |
|
|
393
|
-
| ----------------------- | ------------- | --------------------------------------------------- |
|
|
394
|
-
| Auto-generated captions | `-1` to `-3` | ASR timing often lags behind actual speech |
|
|
395
|
-
| Manual captions | `0` to `-1` | Usually more accurate, small sync issues |
|
|
396
|
-
| Multiple caption tracks | `-2` to `-5` | Different versions may have systematic offset |
|
|
397
|
-
| Regional variations | Varies | Different regions may have different caption timing |
|
|
398
|
-
|
|
399
|
-
### Verifying the Fix
|
|
400
|
-
|
|
401
|
-
After applying `TIMESTAMP_OFFSET_SECONDS`, verify:
|
|
402
|
-
|
|
403
|
-
1. **Watch the clip**: Audio and video should be synchronized
|
|
404
|
-
2. **Check multiple clips**: Offset should work consistently
|
|
405
|
-
3. **Compare with original**: Clip should match the described content
|
|
406
|
-
|
|
407
|
-
If offset varies between segments, the issue might be video-specific rather than a global transcript offset.
|
|
408
|
-
|
|
409
|
-
### CLI Flags
|
|
410
|
-
|
|
411
|
-
| Flag | Description |
|
|
412
|
-
| ---------------------------- | ----------------------------------------------------------------------------- |
|
|
413
|
-
| `--clip` | Download video and generate mp4 clips for each segment |
|
|
414
|
-
| `--download-sections <mode>` | yt-dlp mode: `all` (full video) or `N` (top N segments only, e.g. 1, 2, 3...) |
|
|
415
|
-
| `--video-path <path>` | Custom output directory for downloaded videos and clips |
|
|
416
|
-
| `--threshold <n>` | Minimum score (1–10) to keep a segment |
|
|
417
|
-
| `--top-n <n>` | Maximum number of segments to return |
|
|
418
|
-
| `--max-duration <s>` | Abort if video is longer than N seconds |
|
|
419
|
-
| `--max-chunks <n>` | Limit number of transcript chunks sent to LLM |
|
|
420
|
-
| `--max-parallel <n>` | Max number of LLM calls to run in parallel |
|
|
421
|
-
| `--output-json <path>` | Write output JSON to file instead of stdout |
|
|
422
|
-
| `--no-cache` | Bypass all caches and force a fresh run |
|
|
423
|
-
| `--help, -h` | Show help message |
|
|
424
|
-
|
|
425
|
-
## Docs
|
|
138
|
+
All public types and Zod schemas are exported from the package root. See [src/lib.ts](src/lib.ts) for the full surface.
|
|
426
139
|
|
|
427
|
-
|
|
140
|
+
## Documentation
|
|
428
141
|
|
|
429
|
-
|
|
142
|
+
| Doc | Description |
|
|
143
|
+
| ------------------------------------------------ | --------------------------------------------------------------------- |
|
|
144
|
+
| [docs/configuration.md](docs/configuration.md) | Full environment variable reference, provider setup, FFmpeg presets |
|
|
145
|
+
| [docs/advanced-usage.md](docs/advanced-usage.md) | Advanced CLI examples, caching, pre-downloaded videos |
|
|
146
|
+
| [docs/audio-sync.md](docs/audio-sync.md) | Audio/video sync troubleshooting and `TIMESTAMP_OFFSET_SECONDS` guide |
|
|
147
|
+
| [docs/yt-downloader.md](docs/yt-downloader.md) | yt-dlp download modes explained |
|
|
148
|
+
| [docs/free-models.md](docs/free-models.md) | Free models that work well with this tool |
|
|
149
|
+
| [docs/plan.md](docs/plan.md) | Full architecture and pipeline design |
|
package/dist/config/env.d.ts
CHANGED
|
@@ -28,6 +28,9 @@ export declare const config: {
|
|
|
28
28
|
AUDIO_LLM_BOOST_WINDOW: number;
|
|
29
29
|
AUDIO_LLM_SCORE_BOOST: number;
|
|
30
30
|
GAME_PROFILE: "valorant" | "fps" | "boss_fight" | "general";
|
|
31
|
+
CACHE_BACKEND: "file" | "mongodb";
|
|
32
|
+
MONGODB_DATABASE: string;
|
|
33
|
+
CACHE_TTL_SECONDS: number;
|
|
31
34
|
OPENAI_API_KEY?: string | undefined;
|
|
32
35
|
ANTHROPIC_API_KEY?: string | undefined;
|
|
33
36
|
GOOGLE_GENERATIVE_AI_API_KEY?: string | undefined;
|
|
@@ -45,5 +48,6 @@ export declare const config: {
|
|
|
45
48
|
FFPROBE_PATH?: string | undefined;
|
|
46
49
|
YT_DLP_COOKIES_FROM_BROWSER?: "chrome" | "firefox" | "safari" | "brave" | "edge" | "opera" | "chromium" | undefined;
|
|
47
50
|
YT_DLP_COOKIES_FILE?: string | undefined;
|
|
51
|
+
MONGODB_URI?: string | undefined;
|
|
48
52
|
};
|
|
49
53
|
//# sourceMappingURL=env.d.ts.map
|
package/dist/config/env.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAiBvB,eAAO,MAAM,MAAM
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAiBvB,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAe,CAAC"}
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { log } from './utils/logger.js';
|
|
3
|
-
import { formatConfig } from './utils/
|
|
3
|
+
import { formatConfig } from './utils/format.js';
|
|
4
4
|
import { config } from './config/index.js';
|
|
5
5
|
import { parseArgs, printUsage } from './cli.js';
|
|
6
6
|
import { runPipeline } from './pipeline/runner.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAErC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,UAAU,EAAE,CAAC;IACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACd,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACtC,UAAU,EAAE,CAAC;IACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAClC,GAAG,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAChD,UAAU,EAAE,CAAC;IACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;IAC7C,GAAG,CAAC,IAAI,CACN,8FAA8F,CAC/F,CAAC;AACJ,CAAC;AAED,GAAG,CAAC,IAAI,CACN,kCAAkC,MAAM,CAAC,SAAS,GAAG;IACnD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,oBAAoB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/D,CAAC,IAAI,CAAC,gBAAgB,KAAK,SAAS,IAAI,IAAI,CAAC,gBAAgB,KAAK,KAAK;QACrE,CAAC,CAAC,0BAA0B,IAAI,CAAC,gBAAgB,GAAG;QACpD,CAAC,CAAC,EAAE,CAAC;IACP,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAC/D,CAAC;AACF,GAAG,CAAC,IAAI,CAAC,WAAW,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE5C,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC9B,GAAG,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dumper.d.ts","sourceRoot":"","sources":["../../src/pipeline/dumper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExE;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAY5F;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAYzF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { config } from '../config/index.js';
|
|
4
|
-
import { log } from '
|
|
4
|
+
import { log } from '../utils/logger.js';
|
|
5
5
|
/**
|
|
6
6
|
* Writes the raw normalized transcript lines to
|
|
7
7
|
* `{OUTPUT_DIR}/transcript/{videoId}.json`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dumper.js","sourceRoot":"","sources":["../../src/pipeline/dumper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAGzC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe,EAAE,KAAuB;IAC3E,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QACvD,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;QACnD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACtE,GAAG,CAAC,IAAI,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CACN,iCAAiC,OAAO,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAChG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe,EAAE,MAAsB;IACxE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACrD,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;QACnD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACvE,GAAG,CAAC,IAAI,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CACN,+BAA+B,OAAO,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC9F,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/pipeline/runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/pipeline/runner.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,mBAAmB,CAAC;AAejE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAwG9D"}
|