venice-video-harness 2.4.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/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +598 -0
- package/dist/assembly/manifest-builder.d.ts +8 -0
- package/dist/assembly/manifest-builder.d.ts.map +1 -0
- package/dist/assembly/manifest-builder.js +196 -0
- package/dist/assembly/manifest-builder.js.map +1 -0
- package/dist/assembly/remotion-scaffold.d.ts +14 -0
- package/dist/assembly/remotion-scaffold.d.ts.map +1 -0
- package/dist/assembly/remotion-scaffold.js +292 -0
- package/dist/assembly/remotion-scaffold.js.map +1 -0
- package/dist/assembly/types.d.ts +67 -0
- package/dist/assembly/types.d.ts.map +1 -0
- package/dist/assembly/types.js +5 -0
- package/dist/assembly/types.js.map +1 -0
- package/dist/characters/describer.d.ts +32 -0
- package/dist/characters/describer.d.ts.map +1 -0
- package/dist/characters/describer.js +309 -0
- package/dist/characters/describer.js.map +1 -0
- package/dist/characters/extractor.d.ts +27 -0
- package/dist/characters/extractor.d.ts.map +1 -0
- package/dist/characters/extractor.js +274 -0
- package/dist/characters/extractor.js.map +1 -0
- package/dist/characters/reference-manager.d.ts +95 -0
- package/dist/characters/reference-manager.d.ts.map +1 -0
- package/dist/characters/reference-manager.js +346 -0
- package/dist/characters/reference-manager.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +310 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +66 -0
- package/dist/config.js.map +1 -0
- package/dist/editing/aligner.d.ts +44 -0
- package/dist/editing/aligner.d.ts.map +1 -0
- package/dist/editing/aligner.js +201 -0
- package/dist/editing/aligner.js.map +1 -0
- package/dist/editing/edl.d.ts +45 -0
- package/dist/editing/edl.d.ts.map +1 -0
- package/dist/editing/edl.js +133 -0
- package/dist/editing/edl.js.map +1 -0
- package/dist/editing/overlays.d.ts +97 -0
- package/dist/editing/overlays.d.ts.map +1 -0
- package/dist/editing/overlays.js +41 -0
- package/dist/editing/overlays.js.map +1 -0
- package/dist/editing/packer.d.ts +52 -0
- package/dist/editing/packer.d.ts.map +1 -0
- package/dist/editing/packer.js +170 -0
- package/dist/editing/packer.js.map +1 -0
- package/dist/editing/providers/whisper-cpp.d.ts +32 -0
- package/dist/editing/providers/whisper-cpp.d.ts.map +1 -0
- package/dist/editing/providers/whisper-cpp.js +239 -0
- package/dist/editing/providers/whisper-cpp.js.map +1 -0
- package/dist/editing/render.d.ts +36 -0
- package/dist/editing/render.d.ts.map +1 -0
- package/dist/editing/render.js +227 -0
- package/dist/editing/render.js.map +1 -0
- package/dist/editing/self-eval.d.ts +48 -0
- package/dist/editing/self-eval.d.ts.map +1 -0
- package/dist/editing/self-eval.js +293 -0
- package/dist/editing/self-eval.js.map +1 -0
- package/dist/editing/silence.d.ts +76 -0
- package/dist/editing/silence.d.ts.map +1 -0
- package/dist/editing/silence.js +189 -0
- package/dist/editing/silence.js.map +1 -0
- package/dist/editing/types.d.ts +178 -0
- package/dist/editing/types.d.ts.map +1 -0
- package/dist/editing/types.js +13 -0
- package/dist/editing/types.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive.d.ts +12 -0
- package/dist/interactive.d.ts.map +1 -0
- package/dist/interactive.js +78 -0
- package/dist/interactive.js.map +1 -0
- package/dist/mini-drama/assembler.d.ts +61 -0
- package/dist/mini-drama/assembler.d.ts.map +1 -0
- package/dist/mini-drama/assembler.js +466 -0
- package/dist/mini-drama/assembler.js.map +1 -0
- package/dist/mini-drama/audio-mix.d.ts +65 -0
- package/dist/mini-drama/audio-mix.d.ts.map +1 -0
- package/dist/mini-drama/audio-mix.js +118 -0
- package/dist/mini-drama/audio-mix.js.map +1 -0
- package/dist/mini-drama/cli.d.ts +3 -0
- package/dist/mini-drama/cli.d.ts.map +1 -0
- package/dist/mini-drama/cli.js +2869 -0
- package/dist/mini-drama/cli.js.map +1 -0
- package/dist/mini-drama/fcpxml-export.d.ts +2 -0
- package/dist/mini-drama/fcpxml-export.d.ts.map +1 -0
- package/dist/mini-drama/fcpxml-export.js +5 -0
- package/dist/mini-drama/fcpxml-export.js.map +1 -0
- package/dist/mini-drama/generation-planner.d.ts +24 -0
- package/dist/mini-drama/generation-planner.d.ts.map +1 -0
- package/dist/mini-drama/generation-planner.js +304 -0
- package/dist/mini-drama/generation-planner.js.map +1 -0
- package/dist/mini-drama/location-generator.d.ts +23 -0
- package/dist/mini-drama/location-generator.d.ts.map +1 -0
- package/dist/mini-drama/location-generator.js +144 -0
- package/dist/mini-drama/location-generator.js.map +1 -0
- package/dist/mini-drama/music-cues.d.ts +96 -0
- package/dist/mini-drama/music-cues.d.ts.map +1 -0
- package/dist/mini-drama/music-cues.js +332 -0
- package/dist/mini-drama/music-cues.js.map +1 -0
- package/dist/mini-drama/panel-fixer.d.ts +12 -0
- package/dist/mini-drama/panel-fixer.d.ts.map +1 -0
- package/dist/mini-drama/panel-fixer.js +319 -0
- package/dist/mini-drama/panel-fixer.js.map +1 -0
- package/dist/mini-drama/prompt-builder.d.ts +149 -0
- package/dist/mini-drama/prompt-builder.d.ts.map +1 -0
- package/dist/mini-drama/prompt-builder.js +722 -0
- package/dist/mini-drama/prompt-builder.js.map +1 -0
- package/dist/mini-drama/reference-slots.d.ts +31 -0
- package/dist/mini-drama/reference-slots.d.ts.map +1 -0
- package/dist/mini-drama/reference-slots.js +161 -0
- package/dist/mini-drama/reference-slots.js.map +1 -0
- package/dist/mini-drama/shot-paths.d.ts +77 -0
- package/dist/mini-drama/shot-paths.d.ts.map +1 -0
- package/dist/mini-drama/shot-paths.js +101 -0
- package/dist/mini-drama/shot-paths.js.map +1 -0
- package/dist/mini-drama/storyboard-reference-generator.d.ts +47 -0
- package/dist/mini-drama/storyboard-reference-generator.d.ts.map +1 -0
- package/dist/mini-drama/storyboard-reference-generator.js +293 -0
- package/dist/mini-drama/storyboard-reference-generator.js.map +1 -0
- package/dist/mini-drama/subtitle-generator.d.ts +12 -0
- package/dist/mini-drama/subtitle-generator.d.ts.map +1 -0
- package/dist/mini-drama/subtitle-generator.js +139 -0
- package/dist/mini-drama/subtitle-generator.js.map +1 -0
- package/dist/mini-drama/timeline-export/davinci-fcpxml.d.ts +3 -0
- package/dist/mini-drama/timeline-export/davinci-fcpxml.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/davinci-fcpxml.js +150 -0
- package/dist/mini-drama/timeline-export/davinci-fcpxml.js.map +1 -0
- package/dist/mini-drama/timeline-export/fcpxml.d.ts +11 -0
- package/dist/mini-drama/timeline-export/fcpxml.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/fcpxml.js +140 -0
- package/dist/mini-drama/timeline-export/fcpxml.js.map +1 -0
- package/dist/mini-drama/timeline-export/index.d.ts +13 -0
- package/dist/mini-drama/timeline-export/index.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/index.js +26 -0
- package/dist/mini-drama/timeline-export/index.js.map +1 -0
- package/dist/mini-drama/timeline-export/premiere-xmeml.d.ts +3 -0
- package/dist/mini-drama/timeline-export/premiere-xmeml.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/premiere-xmeml.js +211 -0
- package/dist/mini-drama/timeline-export/premiere-xmeml.js.map +1 -0
- package/dist/mini-drama/timeline-export/probe.d.ts +53 -0
- package/dist/mini-drama/timeline-export/probe.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/probe.js +89 -0
- package/dist/mini-drama/timeline-export/probe.js.map +1 -0
- package/dist/mini-drama/timeline-export/types.d.ts +57 -0
- package/dist/mini-drama/timeline-export/types.d.ts.map +1 -0
- package/dist/mini-drama/timeline-export/types.js +14 -0
- package/dist/mini-drama/timeline-export/types.js.map +1 -0
- package/dist/mini-drama/video-generator.d.ts +22 -0
- package/dist/mini-drama/video-generator.d.ts.map +1 -0
- package/dist/mini-drama/video-generator.js +1305 -0
- package/dist/mini-drama/video-generator.js.map +1 -0
- package/dist/mini-drama/voice-reference.d.ts +42 -0
- package/dist/mini-drama/voice-reference.d.ts.map +1 -0
- package/dist/mini-drama/voice-reference.js +170 -0
- package/dist/mini-drama/voice-reference.js.map +1 -0
- package/dist/output/html-renderer.d.ts +2 -0
- package/dist/output/html-renderer.d.ts.map +1 -0
- package/dist/output/html-renderer.js +37 -0
- package/dist/output/html-renderer.js.map +1 -0
- package/dist/parsers/fountain-parser.d.ts +34 -0
- package/dist/parsers/fountain-parser.d.ts.map +1 -0
- package/dist/parsers/fountain-parser.js +71 -0
- package/dist/parsers/fountain-parser.js.map +1 -0
- package/dist/parsers/pdf-parser.d.ts +24 -0
- package/dist/parsers/pdf-parser.d.ts.map +1 -0
- package/dist/parsers/pdf-parser.js +237 -0
- package/dist/parsers/pdf-parser.js.map +1 -0
- package/dist/parsers/scene-extractor.d.ts +41 -0
- package/dist/parsers/scene-extractor.d.ts.map +1 -0
- package/dist/parsers/scene-extractor.js +400 -0
- package/dist/parsers/scene-extractor.js.map +1 -0
- package/dist/series/manager.d.ts +64 -0
- package/dist/series/manager.d.ts.map +1 -0
- package/dist/series/manager.js +282 -0
- package/dist/series/manager.js.map +1 -0
- package/dist/series/types.d.ts +641 -0
- package/dist/series/types.d.ts.map +1 -0
- package/dist/series/types.js +304 -0
- package/dist/series/types.js.map +1 -0
- package/dist/storyboard/assembler.d.ts +134 -0
- package/dist/storyboard/assembler.d.ts.map +1 -0
- package/dist/storyboard/assembler.js +319 -0
- package/dist/storyboard/assembler.js.map +1 -0
- package/dist/storyboard/prompt-builder.d.ts +113 -0
- package/dist/storyboard/prompt-builder.d.ts.map +1 -0
- package/dist/storyboard/prompt-builder.js +578 -0
- package/dist/storyboard/prompt-builder.js.map +1 -0
- package/dist/storyboard/shot-planner.d.ts +34 -0
- package/dist/storyboard/shot-planner.d.ts.map +1 -0
- package/dist/storyboard/shot-planner.js +446 -0
- package/dist/storyboard/shot-planner.js.map +1 -0
- package/dist/user-config.d.ts +15 -0
- package/dist/user-config.d.ts.map +1 -0
- package/dist/user-config.js +103 -0
- package/dist/user-config.js.map +1 -0
- package/dist/venice/audio-preflight.d.ts +80 -0
- package/dist/venice/audio-preflight.d.ts.map +1 -0
- package/dist/venice/audio-preflight.js +142 -0
- package/dist/venice/audio-preflight.js.map +1 -0
- package/dist/venice/audio.d.ts +88 -0
- package/dist/venice/audio.d.ts.map +1 -0
- package/dist/venice/audio.js +234 -0
- package/dist/venice/audio.js.map +1 -0
- package/dist/venice/client.d.ts +86 -0
- package/dist/venice/client.d.ts.map +1 -0
- package/dist/venice/client.js +375 -0
- package/dist/venice/client.js.map +1 -0
- package/dist/venice/edit.d.ts +57 -0
- package/dist/venice/edit.d.ts.map +1 -0
- package/dist/venice/edit.js +100 -0
- package/dist/venice/edit.js.map +1 -0
- package/dist/venice/generate.d.ts +47 -0
- package/dist/venice/generate.d.ts.map +1 -0
- package/dist/venice/generate.js +150 -0
- package/dist/venice/generate.js.map +1 -0
- package/dist/venice/image-bytes.d.ts +26 -0
- package/dist/venice/image-bytes.d.ts.map +1 -0
- package/dist/venice/image-bytes.js +101 -0
- package/dist/venice/image-bytes.js.map +1 -0
- package/dist/venice/models.d.ts +143 -0
- package/dist/venice/models.d.ts.map +1 -0
- package/dist/venice/models.js +984 -0
- package/dist/venice/models.js.map +1 -0
- package/dist/venice/multi-edit.d.ts +40 -0
- package/dist/venice/multi-edit.d.ts.map +1 -0
- package/dist/venice/multi-edit.js +97 -0
- package/dist/venice/multi-edit.js.map +1 -0
- package/dist/venice/provenance.d.ts +66 -0
- package/dist/venice/provenance.d.ts.map +1 -0
- package/dist/venice/provenance.js +151 -0
- package/dist/venice/provenance.js.map +1 -0
- package/dist/venice/recipe.d.ts +69 -0
- package/dist/venice/recipe.d.ts.map +1 -0
- package/dist/venice/recipe.js +103 -0
- package/dist/venice/recipe.js.map +1 -0
- package/dist/venice/rejection.d.ts +63 -0
- package/dist/venice/rejection.d.ts.map +1 -0
- package/dist/venice/rejection.js +111 -0
- package/dist/venice/rejection.js.map +1 -0
- package/dist/venice/seedance-preflight.d.ts +38 -0
- package/dist/venice/seedance-preflight.d.ts.map +1 -0
- package/dist/venice/seedance-preflight.js +29 -0
- package/dist/venice/seedance-preflight.js.map +1 -0
- package/dist/venice/types.d.ts +212 -0
- package/dist/venice/types.d.ts.map +1 -0
- package/dist/venice/types.js +9 -0
- package/dist/venice/types.js.map +1 -0
- package/dist/venice/video.d.ts +77 -0
- package/dist/venice/video.d.ts.map +1 -0
- package/dist/venice/video.js +163 -0
- package/dist/venice/video.js.map +1 -0
- package/dist/venice/voices.d.ts +40 -0
- package/dist/venice/voices.d.ts.map +1 -0
- package/dist/venice/voices.js +194 -0
- package/dist/venice/voices.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Silence-gap and filler-word detection.
|
|
3
|
+
*
|
|
4
|
+
* Built on the same `ffmpeg silencedetect` pattern used by
|
|
5
|
+
* `.claude/skills/burn-in-subtitles/scripts/derive-captions.ts`. Reused here
|
|
6
|
+
* rather than duplicated.
|
|
7
|
+
*
|
|
8
|
+
* Filler words are identified from word-level transcripts (not audio), so
|
|
9
|
+
* this module pairs with `src/editing/packer.ts` output.
|
|
10
|
+
*/
|
|
11
|
+
import type { WordTiming } from './types.js';
|
|
12
|
+
export interface SilenceSpan {
|
|
13
|
+
startSec: number;
|
|
14
|
+
endSec: number;
|
|
15
|
+
durationSec: number;
|
|
16
|
+
}
|
|
17
|
+
export interface DetectSilencesOptions {
|
|
18
|
+
silenceDb?: number;
|
|
19
|
+
silenceMin?: number;
|
|
20
|
+
/** Optional time range; if omitted, runs on the whole file. */
|
|
21
|
+
startSec?: number;
|
|
22
|
+
endSec?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Run ffmpeg silencedetect and parse the silence spans. Defaults match the
|
|
26
|
+
* burn-in-subtitles skill's recommendations for Kokoro-style VO.
|
|
27
|
+
*/
|
|
28
|
+
export declare function detectSilences(file: string, options?: DetectSilencesOptions): SilenceSpan[];
|
|
29
|
+
/**
|
|
30
|
+
* Default filler-word lexicon. "you know" and "i mean" are handled as
|
|
31
|
+
* bigrams via the multi-word detector below.
|
|
32
|
+
*
|
|
33
|
+
* Intentionally excluded:
|
|
34
|
+
* - `...` (three dots) — Kokoro intentional breath gap (anti-pattern E2)
|
|
35
|
+
* - `so` / `well` / `okay` — too often content-bearing for general removal
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_FILLER_UNIGRAMS: Set<string>;
|
|
38
|
+
export declare const DEFAULT_FILLER_BIGRAMS: Array<[string, string]>;
|
|
39
|
+
export interface FillerMatch {
|
|
40
|
+
startSec: number;
|
|
41
|
+
endSec: number;
|
|
42
|
+
text: string;
|
|
43
|
+
/** Preferred trim — includes a small padding window so we cut cleanly. */
|
|
44
|
+
trimStartSec: number;
|
|
45
|
+
trimEndSec: number;
|
|
46
|
+
kind: 'filler-unigram' | 'filler-bigram';
|
|
47
|
+
}
|
|
48
|
+
export interface DetectFillersOptions {
|
|
49
|
+
unigrams?: Set<string>;
|
|
50
|
+
bigrams?: Array<[string, string]>;
|
|
51
|
+
/** Padding around each filler for cleaner trims (seconds). */
|
|
52
|
+
paddingSec?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Minimum gap between a filler and the next content word for the filler
|
|
55
|
+
* to be a safe trim candidate. Prevents clipping adjacent content.
|
|
56
|
+
*/
|
|
57
|
+
minGapSec?: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Scan a word stream for filler words and bigrams, returning trim
|
|
61
|
+
* candidates with padded boundaries. The caller decides which to apply —
|
|
62
|
+
* never auto-trim without user confirmation (anti-pattern E2).
|
|
63
|
+
*/
|
|
64
|
+
export declare function detectFillers(words: WordTiming[], options?: DetectFillersOptions): FillerMatch[];
|
|
65
|
+
export interface CutCandidate {
|
|
66
|
+
atSec: number;
|
|
67
|
+
kind: 'silence' | 'sentence-end' | 'phrase-end';
|
|
68
|
+
scoreSec: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Suggest cut points within a take: silence midpoints, sentence endings,
|
|
72
|
+
* and phrase endings. Score = estimated time to the next content word
|
|
73
|
+
* (larger scores are safer cuts).
|
|
74
|
+
*/
|
|
75
|
+
export declare function suggestCutCandidates(silences: SilenceSpan[], words: WordTiming[]): CutCandidate[];
|
|
76
|
+
//# sourceMappingURL=silence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"silence.d.ts","sourceRoot":"","sources":["../../src/editing/silence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,qBAA0B,GAClC,WAAW,EAAE,CAoDf;AAMD;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,aAWlC,CAAC;AAEH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAK1D,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,GAAG,eAAe,CAAC;CAC1C;AAMD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,GAAE,oBAAyB,GACjC,WAAW,EAAE,CAqDf;AAMD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,GAAG,cAAc,GAAG,YAAY,CAAC;IAChD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,WAAW,EAAE,EACvB,KAAK,EAAE,UAAU,EAAE,GAClB,YAAY,EAAE,CAmChB"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Silence-gap and filler-word detection.
|
|
3
|
+
*
|
|
4
|
+
* Built on the same `ffmpeg silencedetect` pattern used by
|
|
5
|
+
* `.claude/skills/burn-in-subtitles/scripts/derive-captions.ts`. Reused here
|
|
6
|
+
* rather than duplicated.
|
|
7
|
+
*
|
|
8
|
+
* Filler words are identified from word-level transcripts (not audio), so
|
|
9
|
+
* this module pairs with `src/editing/packer.ts` output.
|
|
10
|
+
*/
|
|
11
|
+
import { execSync } from 'node:child_process';
|
|
12
|
+
/**
|
|
13
|
+
* Run ffmpeg silencedetect and parse the silence spans. Defaults match the
|
|
14
|
+
* burn-in-subtitles skill's recommendations for Kokoro-style VO.
|
|
15
|
+
*/
|
|
16
|
+
export function detectSilences(file, options = {}) {
|
|
17
|
+
const silenceDb = options.silenceDb ?? -30;
|
|
18
|
+
const silenceMin = options.silenceMin ?? 0.18;
|
|
19
|
+
const rangeArgs = [];
|
|
20
|
+
if (options.startSec !== undefined) {
|
|
21
|
+
rangeArgs.push('-ss', String(options.startSec));
|
|
22
|
+
}
|
|
23
|
+
const durationFlag = [];
|
|
24
|
+
if (options.startSec !== undefined && options.endSec !== undefined) {
|
|
25
|
+
durationFlag.push('-t', String(options.endSec - options.startSec));
|
|
26
|
+
}
|
|
27
|
+
const cmd = [
|
|
28
|
+
'ffmpeg',
|
|
29
|
+
'-hide_banner',
|
|
30
|
+
'-nostats',
|
|
31
|
+
...rangeArgs,
|
|
32
|
+
'-i',
|
|
33
|
+
`"${file}"`,
|
|
34
|
+
...durationFlag,
|
|
35
|
+
'-af',
|
|
36
|
+
`"silencedetect=noise=${silenceDb}dB:d=${silenceMin}"`,
|
|
37
|
+
'-f',
|
|
38
|
+
'null',
|
|
39
|
+
'-',
|
|
40
|
+
'2>&1',
|
|
41
|
+
].join(' ');
|
|
42
|
+
const offset = options.startSec ?? 0;
|
|
43
|
+
const out = execSync(cmd, { encoding: 'utf-8' });
|
|
44
|
+
const spans = [];
|
|
45
|
+
let pending = null;
|
|
46
|
+
for (const line of out.split('\n')) {
|
|
47
|
+
const s = line.match(/silence_start: ([\d.]+)/);
|
|
48
|
+
if (s) {
|
|
49
|
+
pending = parseFloat(s[1]) + offset;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const e = line.match(/silence_end: ([\d.]+) \| silence_duration: ([\d.]+)/);
|
|
53
|
+
if (e && pending !== null) {
|
|
54
|
+
const endSec = parseFloat(e[1]) + offset;
|
|
55
|
+
spans.push({
|
|
56
|
+
startSec: pending,
|
|
57
|
+
endSec,
|
|
58
|
+
durationSec: parseFloat(e[2]),
|
|
59
|
+
});
|
|
60
|
+
pending = null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return spans;
|
|
64
|
+
}
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Filler-word detection
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
/**
|
|
69
|
+
* Default filler-word lexicon. "you know" and "i mean" are handled as
|
|
70
|
+
* bigrams via the multi-word detector below.
|
|
71
|
+
*
|
|
72
|
+
* Intentionally excluded:
|
|
73
|
+
* - `...` (three dots) — Kokoro intentional breath gap (anti-pattern E2)
|
|
74
|
+
* - `so` / `well` / `okay` — too often content-bearing for general removal
|
|
75
|
+
*/
|
|
76
|
+
export const DEFAULT_FILLER_UNIGRAMS = new Set([
|
|
77
|
+
'um',
|
|
78
|
+
'umm',
|
|
79
|
+
'uh',
|
|
80
|
+
'uhh',
|
|
81
|
+
'er',
|
|
82
|
+
'erm',
|
|
83
|
+
'ah',
|
|
84
|
+
'hmm',
|
|
85
|
+
'mm',
|
|
86
|
+
'mhm',
|
|
87
|
+
]);
|
|
88
|
+
export const DEFAULT_FILLER_BIGRAMS = [
|
|
89
|
+
['you', 'know'],
|
|
90
|
+
['i', 'mean'],
|
|
91
|
+
['sort', 'of'],
|
|
92
|
+
['kind', 'of'],
|
|
93
|
+
];
|
|
94
|
+
function normalize(word) {
|
|
95
|
+
return word.toLowerCase().replace(/[^a-z']/g, '');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Scan a word stream for filler words and bigrams, returning trim
|
|
99
|
+
* candidates with padded boundaries. The caller decides which to apply —
|
|
100
|
+
* never auto-trim without user confirmation (anti-pattern E2).
|
|
101
|
+
*/
|
|
102
|
+
export function detectFillers(words, options = {}) {
|
|
103
|
+
const unigrams = options.unigrams ?? DEFAULT_FILLER_UNIGRAMS;
|
|
104
|
+
const bigrams = options.bigrams ?? DEFAULT_FILLER_BIGRAMS;
|
|
105
|
+
const padding = options.paddingSec ?? 0.04;
|
|
106
|
+
const minGap = options.minGapSec ?? 0.05;
|
|
107
|
+
const matches = [];
|
|
108
|
+
for (let i = 0; i < words.length; i++) {
|
|
109
|
+
const w = words[i];
|
|
110
|
+
const token = normalize(w.word);
|
|
111
|
+
// Bigram match
|
|
112
|
+
if (i + 1 < words.length) {
|
|
113
|
+
const next = words[i + 1];
|
|
114
|
+
const bg = [token, normalize(next.word)];
|
|
115
|
+
const isBigram = bigrams.some(([a, b]) => a === bg[0] && b === bg[1]);
|
|
116
|
+
if (isBigram) {
|
|
117
|
+
const gapAfter = i + 2 < words.length ? words[i + 2].startSec - next.endSec : Infinity;
|
|
118
|
+
if (gapAfter >= minGap) {
|
|
119
|
+
matches.push({
|
|
120
|
+
startSec: w.startSec,
|
|
121
|
+
endSec: next.endSec,
|
|
122
|
+
text: `${w.word} ${next.word}`,
|
|
123
|
+
trimStartSec: Math.max(0, w.startSec - padding),
|
|
124
|
+
trimEndSec: next.endSec + padding,
|
|
125
|
+
kind: 'filler-bigram',
|
|
126
|
+
});
|
|
127
|
+
i++; // consume both words
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (unigrams.has(token)) {
|
|
133
|
+
const gapBefore = i > 0 ? w.startSec - words[i - 1].endSec : Infinity;
|
|
134
|
+
const gapAfter = i + 1 < words.length ? words[i + 1].startSec - w.endSec : Infinity;
|
|
135
|
+
if (gapBefore >= minGap && gapAfter >= minGap) {
|
|
136
|
+
matches.push({
|
|
137
|
+
startSec: w.startSec,
|
|
138
|
+
endSec: w.endSec,
|
|
139
|
+
text: w.word,
|
|
140
|
+
trimStartSec: Math.max(0, w.startSec - padding),
|
|
141
|
+
trimEndSec: w.endSec + padding,
|
|
142
|
+
kind: 'filler-unigram',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return matches;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Suggest cut points within a take: silence midpoints, sentence endings,
|
|
151
|
+
* and phrase endings. Score = estimated time to the next content word
|
|
152
|
+
* (larger scores are safer cuts).
|
|
153
|
+
*/
|
|
154
|
+
export function suggestCutCandidates(silences, words) {
|
|
155
|
+
const candidates = [];
|
|
156
|
+
for (const sil of silences) {
|
|
157
|
+
if (sil.durationSec < 0.2)
|
|
158
|
+
continue;
|
|
159
|
+
candidates.push({
|
|
160
|
+
atSec: sil.startSec + sil.durationSec / 2,
|
|
161
|
+
kind: 'silence',
|
|
162
|
+
scoreSec: sil.durationSec,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
for (let i = 0; i < words.length - 1; i++) {
|
|
166
|
+
const w = words[i];
|
|
167
|
+
const next = words[i + 1];
|
|
168
|
+
const gap = next.startSec - w.endSec;
|
|
169
|
+
const endsHard = /[.!?]$/.test(w.word);
|
|
170
|
+
const endsSoft = /[,;:]$/.test(w.word);
|
|
171
|
+
if (endsHard && gap >= 0.15) {
|
|
172
|
+
candidates.push({
|
|
173
|
+
atSec: w.endSec + gap / 2,
|
|
174
|
+
kind: 'sentence-end',
|
|
175
|
+
scoreSec: gap,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
else if (endsSoft && gap >= 0.25) {
|
|
179
|
+
candidates.push({
|
|
180
|
+
atSec: w.endSec + gap / 2,
|
|
181
|
+
kind: 'phrase-end',
|
|
182
|
+
scoreSec: gap,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
candidates.sort((a, b) => a.atSec - b.atSec);
|
|
187
|
+
return candidates;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=silence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"silence.js","sourceRoot":"","sources":["../../src/editing/silence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editing pipeline types.
|
|
3
|
+
*
|
|
4
|
+
* The editing pipeline is parallel to the generation pipeline. It consumes
|
|
5
|
+
* existing video/audio files (either Venice-generated shots or raw footage),
|
|
6
|
+
* transcribes them, produces an LLM-readable pack, then drives an EDL-based
|
|
7
|
+
* cut with a self-evaluating QA loop.
|
|
8
|
+
*
|
|
9
|
+
* Design principle from browser-use/video-use: text is the primary surface;
|
|
10
|
+
* pixels are consulted on demand via the timeline_view composite.
|
|
11
|
+
*/
|
|
12
|
+
export interface WordTiming {
|
|
13
|
+
/** The word as transcribed (may include punctuation attached by whisper). */
|
|
14
|
+
word: string;
|
|
15
|
+
/** Seconds from the start of the source file. */
|
|
16
|
+
startSec: number;
|
|
17
|
+
endSec: number;
|
|
18
|
+
/** Optional confidence 0..1 from the transcriber. */
|
|
19
|
+
confidence?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface AudioEvent {
|
|
22
|
+
/**
|
|
23
|
+
* Event label e.g. `(laughter)`, `(applause)`, `(sigh)`, `(music)`.
|
|
24
|
+
* Whisper.cpp does not emit these natively; aligner can inject them from
|
|
25
|
+
* script cues (`shot.sfx`) for generated content.
|
|
26
|
+
*/
|
|
27
|
+
label: string;
|
|
28
|
+
startSec: number;
|
|
29
|
+
endSec: number;
|
|
30
|
+
}
|
|
31
|
+
export interface TakePhrase {
|
|
32
|
+
/**
|
|
33
|
+
* Speaker label. For generated content this is the character name from
|
|
34
|
+
* `shot.characters[0]`. For real footage it defaults to `S0` (single-
|
|
35
|
+
* speaker). Pyannote integration in a future phase will populate this.
|
|
36
|
+
*/
|
|
37
|
+
speaker: string;
|
|
38
|
+
startSec: number;
|
|
39
|
+
endSec: number;
|
|
40
|
+
text: string;
|
|
41
|
+
words: WordTiming[];
|
|
42
|
+
}
|
|
43
|
+
export interface Take {
|
|
44
|
+
/**
|
|
45
|
+
* Short opaque id used in `takes_packed.md` headings. Pattern `CNNNN`
|
|
46
|
+
* (e.g. `C0103`) to match video-use. Generated from the source file name
|
|
47
|
+
* hash + ordinal.
|
|
48
|
+
*/
|
|
49
|
+
id: string;
|
|
50
|
+
/** Absolute path to the source media file. */
|
|
51
|
+
file: string;
|
|
52
|
+
/** Total duration in seconds (from ffprobe). */
|
|
53
|
+
durationSec: number;
|
|
54
|
+
phrases: TakePhrase[];
|
|
55
|
+
audioEvents: AudioEvent[];
|
|
56
|
+
/** ISO timestamp when this take was transcribed. */
|
|
57
|
+
transcribedAt: string;
|
|
58
|
+
/** Transcriber that produced this take (e.g. `whisper-cpp:base.en`). */
|
|
59
|
+
transcriber: string;
|
|
60
|
+
/** Mode: pure ASR vs forced-aligned ground-truth script. */
|
|
61
|
+
mode: 'asr' | 'aligned';
|
|
62
|
+
}
|
|
63
|
+
export interface TakesPack {
|
|
64
|
+
takes: Take[];
|
|
65
|
+
/** ISO timestamp when the pack was assembled. */
|
|
66
|
+
generatedAt: string;
|
|
67
|
+
/** Short description of the source folder. */
|
|
68
|
+
sourceLabel: string;
|
|
69
|
+
}
|
|
70
|
+
export interface TranscribeOptions {
|
|
71
|
+
/** Language code or 'auto' for detection. */
|
|
72
|
+
language?: string;
|
|
73
|
+
/** Whisper model size: tiny, base, small, medium, large. */
|
|
74
|
+
modelSize?: 'tiny' | 'base' | 'small' | 'medium' | 'large' | 'tiny.en' | 'base.en' | 'small.en' | 'medium.en';
|
|
75
|
+
/** Word-level timestamp threshold (whisper.cpp `--word-thold`). */
|
|
76
|
+
wordThreshold?: number;
|
|
77
|
+
/** Max cpu threads for whisper.cpp. */
|
|
78
|
+
threads?: number;
|
|
79
|
+
}
|
|
80
|
+
export interface TranscribeResult {
|
|
81
|
+
/** Per-word timings for the entire source. */
|
|
82
|
+
words: WordTiming[];
|
|
83
|
+
/** Full text (joined words, preserving whisper's punctuation). */
|
|
84
|
+
text: string;
|
|
85
|
+
/** Language detected. */
|
|
86
|
+
language: string;
|
|
87
|
+
/** Duration of the source in seconds (from ffprobe, not the transcriber). */
|
|
88
|
+
durationSec: number;
|
|
89
|
+
/** Human-readable transcriber label, e.g. `whisper-cpp:base.en`. */
|
|
90
|
+
transcriberLabel: string;
|
|
91
|
+
}
|
|
92
|
+
export interface TranscriberProvider {
|
|
93
|
+
/** Unique id for this provider, used in Take.transcriber. */
|
|
94
|
+
readonly id: string;
|
|
95
|
+
/**
|
|
96
|
+
* Transcribe a single audio or video file. Callers are responsible for
|
|
97
|
+
* audio extraction; providers should accept any file ffmpeg can decode.
|
|
98
|
+
*/
|
|
99
|
+
transcribe(file: string, options?: TranscribeOptions): Promise<TranscribeResult>;
|
|
100
|
+
/**
|
|
101
|
+
* Check that the provider's dependencies are available (binary on PATH,
|
|
102
|
+
* API key present, etc.). Throws with a helpful install message if not.
|
|
103
|
+
*/
|
|
104
|
+
assertAvailable(): Promise<void>;
|
|
105
|
+
}
|
|
106
|
+
export type EdlTransition = 'cut' | 'crossfade' | 'fade-to-black';
|
|
107
|
+
export interface EdlClip {
|
|
108
|
+
/** Source take id (matches Take.id). */
|
|
109
|
+
sourceId: string;
|
|
110
|
+
/** Seconds into the source where this clip starts. */
|
|
111
|
+
startSec: number;
|
|
112
|
+
endSec: number;
|
|
113
|
+
/** Trim extra frames off the head/tail (applied on top of start/end). */
|
|
114
|
+
trimStartMs?: number;
|
|
115
|
+
trimEndMs?: number;
|
|
116
|
+
/** Transition entering this clip (from previous clip). Default 'cut'. */
|
|
117
|
+
transitionIn?: EdlTransition;
|
|
118
|
+
/** Transition leaving this clip (to next clip). Default 'cut'. */
|
|
119
|
+
transitionOut?: EdlTransition;
|
|
120
|
+
/** Transition duration when crossfade/fade-to-black. Default 250ms. */
|
|
121
|
+
transitionMs?: number;
|
|
122
|
+
/**
|
|
123
|
+
* Optional human-readable note from the LLM explaining why this clip was
|
|
124
|
+
* included. Preserved through re-renders for audit.
|
|
125
|
+
*/
|
|
126
|
+
rationale?: string;
|
|
127
|
+
}
|
|
128
|
+
export interface EdlColorGrade {
|
|
129
|
+
/** Named grade preset, e.g. `warm-cinematic`, `neutral-punch`. */
|
|
130
|
+
preset?: string;
|
|
131
|
+
/** Raw ffmpeg filter chain (e.g. `eq=contrast=1.05:saturation=1.1`). */
|
|
132
|
+
filter?: string;
|
|
133
|
+
}
|
|
134
|
+
export interface Edl {
|
|
135
|
+
clips: EdlClip[];
|
|
136
|
+
/** Global audio fade at every cut boundary (video-use's "no pops" rule). */
|
|
137
|
+
audioFadeMs: number;
|
|
138
|
+
/** Optional global color grade applied to every clip. */
|
|
139
|
+
colorGrade?: EdlColorGrade;
|
|
140
|
+
/** Target container / codec settings. */
|
|
141
|
+
output: {
|
|
142
|
+
width?: number;
|
|
143
|
+
height?: number;
|
|
144
|
+
fps?: number;
|
|
145
|
+
videoCodec: string;
|
|
146
|
+
audioCodec: string;
|
|
147
|
+
crf: number;
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export interface CutQaFinding {
|
|
151
|
+
kind: 'visual-jump' | 'aspect-regression' | 'subtitle-overlap' | 'vo-truncation' | 'lighting-discontinuity' | 'audio-pop';
|
|
152
|
+
/** Trailer-time seconds where the issue was observed. */
|
|
153
|
+
atSec: number;
|
|
154
|
+
/** Which EDL clip index(es) triggered the finding. */
|
|
155
|
+
clipIndex?: number;
|
|
156
|
+
severity: 'warn' | 'fail';
|
|
157
|
+
message: string;
|
|
158
|
+
/** Path to a timeline_view composite illustrating the issue. */
|
|
159
|
+
evidencePath?: string;
|
|
160
|
+
}
|
|
161
|
+
export interface CutQaReport {
|
|
162
|
+
iteration: number;
|
|
163
|
+
generatedAt: string;
|
|
164
|
+
findings: CutQaFinding[];
|
|
165
|
+
passed: boolean;
|
|
166
|
+
}
|
|
167
|
+
export interface EditSession {
|
|
168
|
+
project: string;
|
|
169
|
+
sourcesDir: string;
|
|
170
|
+
editDir: string;
|
|
171
|
+
takesPackPath: string;
|
|
172
|
+
sources: string[];
|
|
173
|
+
edl: Edl;
|
|
174
|
+
iterations: CutQaReport[];
|
|
175
|
+
createdAt: string;
|
|
176
|
+
updatedAt: string;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/editing/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editing pipeline types.
|
|
3
|
+
*
|
|
4
|
+
* The editing pipeline is parallel to the generation pipeline. It consumes
|
|
5
|
+
* existing video/audio files (either Venice-generated shots or raw footage),
|
|
6
|
+
* transcribes them, produces an LLM-readable pack, then drives an EDL-based
|
|
7
|
+
* cut with a self-evaluating QA loop.
|
|
8
|
+
*
|
|
9
|
+
* Design principle from browser-use/video-use: text is the primary surface;
|
|
10
|
+
* pixels are consulted on demand via the timeline_view composite.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/editing/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { VeniceClient, VeniceRequestError } from './venice/client.js';
|
|
2
|
+
export { generateVideo, quoteVideo } from './venice/video.js';
|
|
3
|
+
export { listVideoModels, getVideoModel } from './venice/models.js';
|
|
4
|
+
export { createSeries, loadSeries, saveSeries, listSeries } from './series/manager.js';
|
|
5
|
+
export type { SeriesState, EpisodeScript, ShotScript } from './series/types.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACvF,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { VeniceClient, VeniceRequestError } from './venice/client.js';
|
|
2
|
+
export { generateVideo, quoteVideo } from './venice/video.js';
|
|
3
|
+
export { listVideoModels, getVideoModel } from './venice/models.js';
|
|
4
|
+
export { createSeries, loadSeries, saveSeries, listSeries } from './series/manager.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface PromptOptions {
|
|
2
|
+
defaultValue?: string;
|
|
3
|
+
required?: boolean;
|
|
4
|
+
hidden?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function promptText(label: string, options?: PromptOptions): Promise<string>;
|
|
7
|
+
export declare function promptChoice<T extends string>(label: string, choices: ReadonlyArray<{
|
|
8
|
+
label: string;
|
|
9
|
+
value: T;
|
|
10
|
+
description?: string;
|
|
11
|
+
}>, defaultIndex?: number): Promise<T>;
|
|
12
|
+
//# sourceMappingURL=interactive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA2CD,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkB5F;AAED,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EACjD,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACzE,YAAY,SAAI,GACf,OAAO,CAAC,CAAC,CAAC,CAYZ"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline/promises';
|
|
2
|
+
import { stdin, stdout } from 'node:process';
|
|
3
|
+
async function hiddenQuestion(label) {
|
|
4
|
+
if (!stdin.isTTY || !stdout.isTTY || typeof stdin.setRawMode !== 'function') {
|
|
5
|
+
throw new Error('Hidden input requires an interactive terminal. Use --api-key or VENICE_API_KEY in non-interactive environments.');
|
|
6
|
+
}
|
|
7
|
+
stdout.write(label);
|
|
8
|
+
stdin.setRawMode(true);
|
|
9
|
+
stdin.resume();
|
|
10
|
+
stdin.setEncoding('utf-8');
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
let value = '';
|
|
13
|
+
const cleanup = () => {
|
|
14
|
+
stdin.off('data', onData);
|
|
15
|
+
stdin.setRawMode(false);
|
|
16
|
+
stdin.pause();
|
|
17
|
+
stdout.write('\n');
|
|
18
|
+
};
|
|
19
|
+
const onData = (chunk) => {
|
|
20
|
+
for (const char of chunk) {
|
|
21
|
+
if (char === '\u0003') {
|
|
22
|
+
cleanup();
|
|
23
|
+
reject(new Error('Prompt cancelled.'));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (char === '\r' || char === '\n') {
|
|
27
|
+
cleanup();
|
|
28
|
+
resolve(value);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (char === '\u007f' || char === '\b') {
|
|
32
|
+
value = value.slice(0, -1);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (char >= ' ')
|
|
36
|
+
value += char;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
stdin.on('data', onData);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export async function promptText(label, options = {}) {
|
|
43
|
+
const suffix = options.defaultValue ? ` [${options.defaultValue}]` : '';
|
|
44
|
+
while (true) {
|
|
45
|
+
let value;
|
|
46
|
+
if (options.hidden) {
|
|
47
|
+
value = await hiddenQuestion(`${label}${suffix}: `);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
51
|
+
try {
|
|
52
|
+
value = await rl.question(`${label}${suffix}: `);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
rl.close();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const selected = value.trim() || options.defaultValue || '';
|
|
59
|
+
if (selected || !options.required)
|
|
60
|
+
return selected;
|
|
61
|
+
console.error(`${label} is required.`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function promptChoice(label, choices, defaultIndex = 0) {
|
|
65
|
+
console.log(`\n${label}`);
|
|
66
|
+
choices.forEach((choice, index) => {
|
|
67
|
+
const description = choice.description ? ` — ${choice.description}` : '';
|
|
68
|
+
console.log(` ${index + 1}. ${choice.label}${description}`);
|
|
69
|
+
});
|
|
70
|
+
while (true) {
|
|
71
|
+
const answer = await promptText('Choose', { defaultValue: String(defaultIndex + 1), required: true });
|
|
72
|
+
const selected = Number.parseInt(answer, 10) - 1;
|
|
73
|
+
if (selected >= 0 && selected < choices.length)
|
|
74
|
+
return choices[selected].value;
|
|
75
|
+
console.error(`Enter a number from 1 to ${choices.length}.`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=interactive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive.js","sourceRoot":"","sources":["../src/interactive.ts"],"names":[],"mappings":"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"}
|