demofly 0.2.8 → 0.2.9
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 +154 -0
- package/dist/commands/analyze.d.ts +3 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +163 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/demos/open.d.ts.map +1 -1
- package/dist/commands/demos/open.js +2 -1
- package/dist/commands/demos/open.js.map +1 -1
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +575 -49
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/push.d.ts.map +1 -1
- package/dist/commands/push.js +20 -1
- package/dist/commands/push.js.map +1 -1
- package/dist/commands/render.d.ts.map +1 -1
- package/dist/commands/render.js +5 -2
- package/dist/commands/render.js.map +1 -1
- package/dist/commands/tts.d.ts.map +1 -1
- package/dist/commands/tts.js +127 -12
- package/dist/commands/tts.js.map +1 -1
- package/dist/commands/voices/select.d.ts.map +1 -1
- package/dist/commands/voices/select.js +66 -11
- package/dist/commands/voices/select.js.map +1 -1
- package/dist/lib/audio-probe.d.ts +23 -0
- package/dist/lib/audio-probe.d.ts.map +1 -0
- package/dist/lib/audio-probe.js +59 -0
- package/dist/lib/audio-probe.js.map +1 -0
- package/dist/lib/demo-config.d.ts +7 -0
- package/dist/lib/demo-config.d.ts.map +1 -1
- package/dist/lib/demo-config.js +9 -0
- package/dist/lib/demo-config.js.map +1 -1
- package/dist/lib/edit-proposals.d.ts +48 -1
- package/dist/lib/edit-proposals.d.ts.map +1 -1
- package/dist/lib/edit-proposals.js +49 -0
- package/dist/lib/edit-proposals.js.map +1 -1
- package/dist/lib/push-project.d.ts +37 -0
- package/dist/lib/push-project.d.ts.map +1 -0
- package/dist/lib/push-project.js +194 -0
- package/dist/lib/push-project.js.map +1 -0
- package/dist/lib/retiming.js +47 -0
- package/dist/lib/retiming.js.map +1 -1
- package/dist/lib/scene-assembler.d.ts +29 -0
- package/dist/lib/scene-assembler.d.ts.map +1 -0
- package/dist/lib/scene-assembler.js +202 -0
- package/dist/lib/scene-assembler.js.map +1 -0
- package/dist/lib/voice-resolver.d.ts +4 -0
- package/dist/lib/voice-resolver.d.ts.map +1 -1
- package/dist/lib/voice-resolver.js +5 -2
- package/dist/lib/voice-resolver.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import {} from "commander";
|
|
2
2
|
import { createInterface } from "node:readline";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
3
5
|
import { getToken } from "../../lib/credentials.js";
|
|
4
6
|
import { createApiClient, getAppUrl } from "../../lib/api-client.js";
|
|
5
7
|
import { setDefaultVoice, getDefaultVoice } from "../../lib/voice-config.js";
|
|
6
|
-
import {
|
|
8
|
+
import { getDemoVoicePreference, setDemoVoicePreference } from "../../lib/demo-config.js";
|
|
9
|
+
import { KOKORO_VOICES, resolveVoice, buildAvailableVoices } from "../../lib/voice-resolver.js";
|
|
7
10
|
function prompt(question) {
|
|
8
11
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
9
12
|
return new Promise((resolve) => {
|
|
@@ -15,11 +18,22 @@ function prompt(question) {
|
|
|
15
18
|
}
|
|
16
19
|
export function registerSelectCommand(voices) {
|
|
17
20
|
voices
|
|
18
|
-
.command("select")
|
|
19
|
-
.description("Choose default voice interactively")
|
|
20
|
-
.
|
|
21
|
+
.command("select [demo]")
|
|
22
|
+
.description("Choose default voice interactively (or set voice for a specific demo)")
|
|
23
|
+
.option("--voice <id>", "Set voice directly without interactive picker")
|
|
24
|
+
.action(async (demo, opts) => {
|
|
25
|
+
// Validate demo directory if provided
|
|
26
|
+
let demoDir = null;
|
|
27
|
+
if (demo) {
|
|
28
|
+
demoDir = resolve(process.cwd(), "demofly", demo);
|
|
29
|
+
const configPath = resolve(demoDir, "demofly.json");
|
|
30
|
+
if (!existsSync(demoDir) || !existsSync(configPath)) {
|
|
31
|
+
console.error(`Demo '${demo}' not found. Check the demo name and try again.`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
21
35
|
const token = await getToken();
|
|
22
|
-
|
|
36
|
+
// Build voice choices
|
|
23
37
|
const choices = KOKORO_VOICES.map((v) => ({
|
|
24
38
|
name: v.name,
|
|
25
39
|
provider: "kokoro",
|
|
@@ -27,6 +41,7 @@ export function registerSelectCommand(voices) {
|
|
|
27
41
|
label: `${v.name} (kokoro)`,
|
|
28
42
|
}));
|
|
29
43
|
let isPro = false;
|
|
44
|
+
let apiVoices = null;
|
|
30
45
|
if (token) {
|
|
31
46
|
const api = createApiClient(token);
|
|
32
47
|
const [subRes, voicesRes] = await Promise.all([
|
|
@@ -34,6 +49,7 @@ export function registerSelectCommand(voices) {
|
|
|
34
49
|
api.get("/voices").catch(() => null),
|
|
35
50
|
]);
|
|
36
51
|
isPro = subRes?.plan === "pro";
|
|
52
|
+
apiVoices = voicesRes;
|
|
37
53
|
if (voicesRes) {
|
|
38
54
|
for (const v of voicesRes) {
|
|
39
55
|
if (v.provider === "kokoro" || v.provider === "orpheus")
|
|
@@ -51,12 +67,45 @@ export function registerSelectCommand(voices) {
|
|
|
51
67
|
console.log("Could not reach Demofly API. Showing local voices only.\n");
|
|
52
68
|
}
|
|
53
69
|
}
|
|
70
|
+
// Direct voice selection via --voice flag
|
|
71
|
+
if (opts.voice) {
|
|
72
|
+
const available = buildAvailableVoices(apiVoices?.map((v) => ({
|
|
73
|
+
voiceName: v.voiceName,
|
|
74
|
+
provider: v.provider,
|
|
75
|
+
voiceId: v.voiceId,
|
|
76
|
+
providerId: v.providerId,
|
|
77
|
+
tier: v.tier,
|
|
78
|
+
})) ?? undefined);
|
|
79
|
+
const resolved = resolveVoice(opts.voice, undefined, available);
|
|
80
|
+
if (!resolved) {
|
|
81
|
+
console.error(`Voice "${opts.voice}" not found. Run \`demofly voices list\` to see available voices.`);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
if (resolved.tier === "premium" && !isPro) {
|
|
85
|
+
console.log(`This is a premium voice. Upgrade to Pro to use it: ${getAppUrl()}/upgrade`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (demoDir) {
|
|
89
|
+
setDemoVoicePreference(demoDir, { name: resolved.name, provider: resolved.provider });
|
|
90
|
+
console.log(`Voice for ${demo} set to ${resolved.name} (${resolved.provider})`);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
setDefaultVoice(resolved.name, resolved.provider);
|
|
94
|
+
console.log(`Default voice set to: ${resolved.name} (${resolved.provider})`);
|
|
95
|
+
}
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Determine current voice for highlighting
|
|
99
|
+
const currentVoice = demoDir
|
|
100
|
+
? getDemoVoicePreference(demoDir) ?? getDefaultVoice()
|
|
101
|
+
: getDefaultVoice();
|
|
54
102
|
// Display numbered list
|
|
55
|
-
|
|
103
|
+
const target = demoDir ? `voice for ${demo}` : "default voice";
|
|
104
|
+
console.log(`Select ${target}:\n`);
|
|
56
105
|
for (let i = 0; i < choices.length; i++) {
|
|
57
|
-
const
|
|
58
|
-
choices[i].provider ===
|
|
59
|
-
const marker =
|
|
106
|
+
const isCurrent = choices[i].name === currentVoice.name &&
|
|
107
|
+
choices[i].provider === currentVoice.provider;
|
|
108
|
+
const marker = isCurrent ? " (current)" : "";
|
|
60
109
|
console.log(` ${(i + 1).toString().padStart(2)}. ${choices[i].label}${marker}`);
|
|
61
110
|
}
|
|
62
111
|
console.log();
|
|
@@ -72,8 +121,14 @@ export function registerSelectCommand(voices) {
|
|
|
72
121
|
console.log(`This is a premium voice. Upgrade to Pro to use it: ${getAppUrl()}/upgrade`);
|
|
73
122
|
return;
|
|
74
123
|
}
|
|
75
|
-
|
|
76
|
-
|
|
124
|
+
if (demoDir) {
|
|
125
|
+
setDemoVoicePreference(demoDir, { name: selected.name, provider: selected.provider });
|
|
126
|
+
console.log(`Voice for ${demo} set to ${selected.name} (${selected.provider})`);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
setDefaultVoice(selected.name, selected.provider);
|
|
130
|
+
console.log(`Default voice set to: ${selected.name} (${selected.provider})`);
|
|
131
|
+
}
|
|
77
132
|
});
|
|
78
133
|
}
|
|
79
134
|
//# sourceMappingURL=select.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/commands/voices/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/commands/voices/select.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare function hasFfprobe(): boolean;
|
|
2
|
+
/**
|
|
3
|
+
* Probe audio file duration using ffprobe.
|
|
4
|
+
* Returns duration in milliseconds.
|
|
5
|
+
*/
|
|
6
|
+
export declare function probeAudioDuration(filePath: string): number;
|
|
7
|
+
export type OverflowSeverity = "ok" | "warning" | "critical";
|
|
8
|
+
export interface OverflowResult {
|
|
9
|
+
overflowMs: number;
|
|
10
|
+
severity: OverflowSeverity;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Compute overflow of audio duration relative to scene window.
|
|
14
|
+
* Positive overflowMs = audio is too long.
|
|
15
|
+
* Negative overflowMs = audio fits with room to spare.
|
|
16
|
+
*
|
|
17
|
+
* Severity thresholds:
|
|
18
|
+
* - ok: overflow <= 0
|
|
19
|
+
* - warning: overflow > 0 but <= 2000ms OR <= 30% of window (whichever is larger)
|
|
20
|
+
* - critical: overflow > 2000ms AND > 30% of window
|
|
21
|
+
*/
|
|
22
|
+
export declare function computeOverflow(audioDurationMs: number, sceneWindowMs: number): OverflowResult;
|
|
23
|
+
//# sourceMappingURL=audio-probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-probe.d.ts","sourceRoot":"","sources":["../../src/lib/audio-probe.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,IAAI,OAAO,CAOpC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAuB3D;AAED,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,SAAS,GAAG,UAAU,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,eAAe,EAAE,MAAM,EACvB,aAAa,EAAE,MAAM,GACpB,cAAc,CAehB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
export function hasFfprobe() {
|
|
4
|
+
try {
|
|
5
|
+
execSync("ffprobe -version", { stdio: "pipe" });
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Probe audio file duration using ffprobe.
|
|
14
|
+
* Returns duration in milliseconds.
|
|
15
|
+
*/
|
|
16
|
+
export function probeAudioDuration(filePath) {
|
|
17
|
+
if (!existsSync(filePath)) {
|
|
18
|
+
throw new Error(`Audio file not found: ${filePath}`);
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const output = execSync(`ffprobe -v error -show_entries format=duration -of csv=p=0 "${filePath}"`, { encoding: "utf-8", timeout: 30_000, stdio: ["pipe", "pipe", "pipe"] });
|
|
22
|
+
const seconds = parseFloat(output.trim());
|
|
23
|
+
if (Number.isNaN(seconds)) {
|
|
24
|
+
throw new Error(`ffprobe returned non-numeric duration: ${output.trim()}`);
|
|
25
|
+
}
|
|
26
|
+
return Math.round(seconds * 1000);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (error instanceof Error && error.message.startsWith("Audio file not found")) {
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
const execError = error;
|
|
33
|
+
const detail = execError.stderr || execError.message || "unknown error";
|
|
34
|
+
throw new Error(`ffprobe failed for ${filePath}: ${detail}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Compute overflow of audio duration relative to scene window.
|
|
39
|
+
* Positive overflowMs = audio is too long.
|
|
40
|
+
* Negative overflowMs = audio fits with room to spare.
|
|
41
|
+
*
|
|
42
|
+
* Severity thresholds:
|
|
43
|
+
* - ok: overflow <= 0
|
|
44
|
+
* - warning: overflow > 0 but <= 2000ms OR <= 30% of window (whichever is larger)
|
|
45
|
+
* - critical: overflow > 2000ms AND > 30% of window
|
|
46
|
+
*/
|
|
47
|
+
export function computeOverflow(audioDurationMs, sceneWindowMs) {
|
|
48
|
+
const overflowMs = audioDurationMs - sceneWindowMs;
|
|
49
|
+
if (overflowMs <= 0) {
|
|
50
|
+
return { overflowMs, severity: "ok" };
|
|
51
|
+
}
|
|
52
|
+
const exceedsAbsolute = overflowMs > 2000;
|
|
53
|
+
const exceedsPercent = overflowMs > sceneWindowMs * 0.3;
|
|
54
|
+
if (exceedsAbsolute && exceedsPercent) {
|
|
55
|
+
return { overflowMs, severity: "critical" };
|
|
56
|
+
}
|
|
57
|
+
return { overflowMs, severity: "warning" };
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=audio-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audio-probe.js","sourceRoot":"","sources":["../../src/lib/audio-probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,QAAQ,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CACrB,+DAA+D,QAAQ,GAAG,EAC1E,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CACxE,CAAC;QACF,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,0CAA0C,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;YAC/E,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,SAAS,GAAG,KAA8C,CAAC;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,OAAO,IAAI,eAAe,CAAC;QACxE,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,KAAK,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AASD;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,eAAuB,EACvB,aAAqB;IAErB,MAAM,UAAU,GAAG,eAAe,GAAG,aAAa,CAAC;IAEnD,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,eAAe,GAAG,UAAU,GAAG,IAAI,CAAC;IAC1C,MAAM,cAAc,GAAG,UAAU,GAAG,aAAa,GAAG,GAAG,CAAC;IAExD,IAAI,eAAe,IAAI,cAAc,EAAE,CAAC;QACtC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IAC9C,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAC7C,CAAC"}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
export interface VoicePreference {
|
|
2
|
+
name: string;
|
|
3
|
+
provider: string;
|
|
4
|
+
}
|
|
1
5
|
export interface DemoConfig {
|
|
2
6
|
projectSlug: string;
|
|
3
7
|
cloudDemoId?: string;
|
|
8
|
+
voicePreference?: VoicePreference;
|
|
4
9
|
}
|
|
5
10
|
export declare function readDemoConfig(projectDir: string): DemoConfig | null;
|
|
6
11
|
export declare function writeDemoConfig(projectDir: string, config: DemoConfig): void;
|
|
12
|
+
export declare function getDemoVoicePreference(projectDir: string): VoicePreference | null;
|
|
13
|
+
export declare function setDemoVoicePreference(projectDir: string, voice: VoicePreference): void;
|
|
7
14
|
export declare function ensureProjectSlug(projectDir: string): string;
|
|
8
15
|
//# sourceMappingURL=demo-config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"demo-config.d.ts","sourceRoot":"","sources":["../../src/lib/demo-config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"demo-config.d.ts","sourceRoot":"","sources":["../../src/lib/demo-config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAID,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQpE;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAG5E;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAGjF;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAIvF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAU5D"}
|
package/dist/lib/demo-config.js
CHANGED
|
@@ -16,6 +16,15 @@ export function writeDemoConfig(projectDir, config) {
|
|
|
16
16
|
const configPath = resolve(projectDir, CONFIG_FILE);
|
|
17
17
|
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
18
18
|
}
|
|
19
|
+
export function getDemoVoicePreference(projectDir) {
|
|
20
|
+
const config = readDemoConfig(projectDir);
|
|
21
|
+
return config?.voicePreference ?? null;
|
|
22
|
+
}
|
|
23
|
+
export function setDemoVoicePreference(projectDir, voice) {
|
|
24
|
+
const existing = readDemoConfig(projectDir);
|
|
25
|
+
const config = { projectSlug: basename(projectDir), ...existing, voicePreference: voice };
|
|
26
|
+
writeDemoConfig(projectDir, config);
|
|
27
|
+
}
|
|
19
28
|
export function ensureProjectSlug(projectDir) {
|
|
20
29
|
const existing = readDemoConfig(projectDir);
|
|
21
30
|
if (existing?.projectSlug) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"demo-config.js","sourceRoot":"","sources":["../../src/lib/demo-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"demo-config.js","sourceRoot":"","sources":["../../src/lib/demo-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAa9C,MAAM,WAAW,GAAG,cAAc,CAAC;AAEnC,MAAM,UAAU,cAAc,CAAC,UAAkB;IAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,UAAkB,EAAE,MAAkB;IACpE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACpD,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC1C,OAAO,MAAM,EAAE,eAAe,IAAI,IAAI,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAkB,EAAE,KAAsB;IAC/E,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAe,EAAE,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;IACtG,eAAe,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,QAAQ,EAAE,WAAW,EAAE,CAAC;QAC1B,OAAO,QAAQ,CAAC,WAAW,CAAC;IAC9B,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IACxC,MAAM,MAAM,GAAe,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE,CAAC;IACpE,eAAe,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -8,16 +8,39 @@
|
|
|
8
8
|
* data, hero moment awareness, and assembly best practices.
|
|
9
9
|
*/
|
|
10
10
|
import type { AlignmentData } from "./alignment.js";
|
|
11
|
-
export type EditType = "speed_video" | "slow_video" | "freeze_frame" | "trim_silence" | "insert_crossfade" | "pad_silence" | "no_change";
|
|
11
|
+
export type EditType = "speed_video" | "slow_video" | "freeze_frame" | "trim_silence" | "insert_crossfade" | "pad_silence" | "no_change" | "cut_segment" | "speed_segment";
|
|
12
12
|
export interface EditDecision {
|
|
13
13
|
beatId: string;
|
|
14
|
+
sceneId?: string;
|
|
14
15
|
editType: EditType;
|
|
15
16
|
segmentStartMs: number;
|
|
16
17
|
segmentEndMs: number;
|
|
17
18
|
targetDurationMs: number;
|
|
19
|
+
speedFactor?: number;
|
|
18
20
|
rationale: string;
|
|
19
21
|
confidence: number;
|
|
20
22
|
}
|
|
23
|
+
export interface DeadTimeCandidate {
|
|
24
|
+
sceneId: string;
|
|
25
|
+
startMs: number;
|
|
26
|
+
endMs: number;
|
|
27
|
+
gapMs: number;
|
|
28
|
+
hasNarration: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface DeterministicSignals {
|
|
31
|
+
deadTimeCandidates: DeadTimeCandidate[];
|
|
32
|
+
silenceSegments: {
|
|
33
|
+
sceneId: string;
|
|
34
|
+
startMs: number;
|
|
35
|
+
endMs: number;
|
|
36
|
+
}[];
|
|
37
|
+
durationDrift: {
|
|
38
|
+
sceneId: string;
|
|
39
|
+
audioDurationMs: number;
|
|
40
|
+
videoDurationMs: number;
|
|
41
|
+
driftMs: number;
|
|
42
|
+
}[];
|
|
43
|
+
}
|
|
21
44
|
export interface EditDecisionsData {
|
|
22
45
|
decisions: EditDecision[];
|
|
23
46
|
skipped: EditDecision[];
|
|
@@ -39,6 +62,30 @@ export interface EditDecisionsData {
|
|
|
39
62
|
* based on visual content).
|
|
40
63
|
*/
|
|
41
64
|
export declare function generateEditProposals(alignment: AlignmentData, heroSceneIds?: string[]): EditDecisionsData;
|
|
65
|
+
/**
|
|
66
|
+
* Detect dead time segments within scenes: gaps between timing markers
|
|
67
|
+
* that exceed a threshold with no corresponding narration coverage.
|
|
68
|
+
*/
|
|
69
|
+
export declare function detectDeadTime(timingData: import("./timing.js").TimingData, narrationBeats?: {
|
|
70
|
+
sceneId: string;
|
|
71
|
+
startMs: number;
|
|
72
|
+
endMs: number;
|
|
73
|
+
}[], thresholdMs?: number): DeadTimeCandidate[];
|
|
74
|
+
/**
|
|
75
|
+
* Build deterministic signals for the LLM edit decision engine.
|
|
76
|
+
*/
|
|
77
|
+
export declare function buildDeterministicSignals(timingData: import("./timing.js").TimingData, audioDurations?: {
|
|
78
|
+
sceneId: string;
|
|
79
|
+
durationMs: number;
|
|
80
|
+
}[], narrationBeats?: {
|
|
81
|
+
sceneId: string;
|
|
82
|
+
startMs: number;
|
|
83
|
+
endMs: number;
|
|
84
|
+
}[], silenceSegments?: {
|
|
85
|
+
sceneId: string;
|
|
86
|
+
startMs: number;
|
|
87
|
+
endMs: number;
|
|
88
|
+
}[]): DeterministicSignals;
|
|
42
89
|
/**
|
|
43
90
|
* Generate edit proposals and write to recordings/edit-decisions.json.
|
|
44
91
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit-proposals.d.ts","sourceRoot":"","sources":["../../src/lib/edit-proposals.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAGnE,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,YAAY,GACZ,cAAc,GACd,cAAc,GACd,kBAAkB,GAClB,aAAa,GACb,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"edit-proposals.d.ts","sourceRoot":"","sources":["../../src/lib/edit-proposals.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAGnE,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,YAAY,GACZ,cAAc,GACd,cAAc,GACd,kBAAkB,GAClB,aAAa,GACb,WAAW,GACX,aAAa,GACb,eAAe,CAAC;AAEpB,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;IACxC,eAAe,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvE,aAAa,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACzG;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAUD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,aAAa,EACxB,YAAY,GAAE,MAAM,EAAO,GAC1B,iBAAiB,CA2BnB;AAwGD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,OAAO,aAAa,EAAE,UAAU,EAC5C,cAAc,GAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAO,EAC1E,WAAW,SAAO,GACjB,iBAAiB,EAAE,CAiCrB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,OAAO,aAAa,EAAE,UAAU,EAC5C,cAAc,GAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAAO,EAC9D,cAAc,GAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAO,EAC1E,eAAe,GAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAO,GAC1E,oBAAoB,CAgBtB;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,YAAY,GAAE,MAAM,EAAO,GAC1B,iBAAiB,GAAG,IAAI,CAqB1B"}
|
|
@@ -140,6 +140,55 @@ function proposeEdit(beat, heroSceneIds) {
|
|
|
140
140
|
}
|
|
141
141
|
return null;
|
|
142
142
|
}
|
|
143
|
+
/**
|
|
144
|
+
* Detect dead time segments within scenes: gaps between timing markers
|
|
145
|
+
* that exceed a threshold with no corresponding narration coverage.
|
|
146
|
+
*/
|
|
147
|
+
export function detectDeadTime(timingData, narrationBeats = [], thresholdMs = 2000) {
|
|
148
|
+
const candidates = [];
|
|
149
|
+
for (const scene of timingData.scenes) {
|
|
150
|
+
const markers = scene.markers;
|
|
151
|
+
for (let i = 0; i < markers.length - 1; i++) {
|
|
152
|
+
const gapMs = markers[i + 1].ms - markers[i].ms;
|
|
153
|
+
if (gapMs <= thresholdMs)
|
|
154
|
+
continue;
|
|
155
|
+
const gapStartMs = markers[i].ms;
|
|
156
|
+
const gapEndMs = markers[i + 1].ms;
|
|
157
|
+
// Check if narration covers this window
|
|
158
|
+
const hasNarration = narrationBeats.some((beat) => beat.sceneId === scene.sceneId &&
|
|
159
|
+
beat.startMs <= gapEndMs &&
|
|
160
|
+
beat.endMs >= gapStartMs);
|
|
161
|
+
if (!hasNarration) {
|
|
162
|
+
candidates.push({
|
|
163
|
+
sceneId: scene.sceneId,
|
|
164
|
+
startMs: gapStartMs,
|
|
165
|
+
endMs: gapEndMs,
|
|
166
|
+
gapMs,
|
|
167
|
+
hasNarration: false,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return candidates;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Build deterministic signals for the LLM edit decision engine.
|
|
176
|
+
*/
|
|
177
|
+
export function buildDeterministicSignals(timingData, audioDurations = [], narrationBeats = [], silenceSegments = []) {
|
|
178
|
+
const deadTimeCandidates = detectDeadTime(timingData, narrationBeats);
|
|
179
|
+
const durationDrift = timingData.scenes.map((scene) => {
|
|
180
|
+
const audio = audioDurations.find((a) => a.sceneId === scene.sceneId);
|
|
181
|
+
const videoDurationMs = scene.endMs - scene.startMs;
|
|
182
|
+
const audioDurationMs = audio?.durationMs ?? 0;
|
|
183
|
+
return {
|
|
184
|
+
sceneId: scene.sceneId,
|
|
185
|
+
audioDurationMs,
|
|
186
|
+
videoDurationMs,
|
|
187
|
+
driftMs: videoDurationMs - audioDurationMs,
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
return { deadTimeCandidates, silenceSegments, durationDrift };
|
|
191
|
+
}
|
|
143
192
|
/**
|
|
144
193
|
* Generate edit proposals and write to recordings/edit-decisions.json.
|
|
145
194
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit-proposals.js","sourceRoot":"","sources":["../../src/lib/edit-proposals.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"edit-proposals.js","sourceRoot":"","sources":["../../src/lib/edit-proposals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push Project
|
|
3
|
+
*
|
|
4
|
+
* Shared artifact collection and upload logic for pushing a demo project
|
|
5
|
+
* to the demofly cloud. Used by both `push` command and `generate --cloud`.
|
|
6
|
+
*/
|
|
7
|
+
import type { ApiClient } from "./api-client.js";
|
|
8
|
+
export interface PushPayload {
|
|
9
|
+
artifacts: Record<string, string>;
|
|
10
|
+
audio: Record<string, string>;
|
|
11
|
+
metadata: Record<string, unknown>;
|
|
12
|
+
recordings: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
export interface PushResponse {
|
|
15
|
+
url?: string;
|
|
16
|
+
warnings?: string[];
|
|
17
|
+
errors?: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface PushResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
url?: string;
|
|
22
|
+
warnings?: string[];
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Validate that required project files exist.
|
|
27
|
+
* Returns list of missing files, or empty array if all present.
|
|
28
|
+
*/
|
|
29
|
+
export declare function validatePushArtifacts(projectDir: string): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Push a demo project's artifacts to the demofly cloud.
|
|
32
|
+
*
|
|
33
|
+
* Collects text artifacts, audio files, recordings, and metadata
|
|
34
|
+
* from the project directory and uploads them to the API.
|
|
35
|
+
*/
|
|
36
|
+
export declare function pushProject(projectDir: string, project: string, apiClient: ApiClient): Promise<PushResult>;
|
|
37
|
+
//# sourceMappingURL=push-project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-project.d.ts","sourceRoot":"","sources":["../../src/lib/push-project.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAcjD,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAyGD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAQlE;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,UAAU,CAAC,CAqGrB"}
|