@contractspec/example.video-docs-terminal 2.1.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/.turbo/turbo-build.log +38 -0
- package/.turbo/turbo-prebuild.log +1 -0
- package/CHANGELOG.md +14 -0
- package/dist/browser/build-tutorial.js +60 -0
- package/dist/browser/docs/index.js +89 -0
- package/dist/browser/docs/video-docs-terminal.docblock.js +89 -0
- package/dist/browser/example.js +33 -0
- package/dist/browser/generate-narration.js +18 -0
- package/dist/browser/index.js +389 -0
- package/dist/browser/sample-tutorials.js +192 -0
- package/dist/build-tutorial.d.ts +44 -0
- package/dist/build-tutorial.js +61 -0
- package/dist/docs/index.d.ts +1 -0
- package/dist/docs/index.js +90 -0
- package/dist/docs/video-docs-terminal.docblock.d.ts +1 -0
- package/dist/docs/video-docs-terminal.docblock.js +90 -0
- package/dist/example.d.ts +2 -0
- package/dist/example.js +34 -0
- package/dist/generate-narration.d.ts +42 -0
- package/dist/generate-narration.js +19 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +390 -0
- package/dist/node/build-tutorial.js +60 -0
- package/dist/node/docs/index.js +89 -0
- package/dist/node/docs/video-docs-terminal.docblock.js +89 -0
- package/dist/node/example.js +33 -0
- package/dist/node/generate-narration.js +18 -0
- package/dist/node/index.js +389 -0
- package/dist/node/sample-tutorials.js +192 -0
- package/dist/sample-tutorials.d.ts +40 -0
- package/dist/sample-tutorials.js +193 -0
- package/package.json +159 -0
- package/src/build-tutorial.ts +120 -0
- package/src/docs/index.ts +1 -0
- package/src/docs/video-docs-terminal.docblock.ts +93 -0
- package/src/example.ts +32 -0
- package/src/generate-narration.ts +70 -0
- package/src/index.ts +7 -0
- package/src/sample-tutorials.ts +241 -0
- package/tsconfig.json +9 -0
- package/tsdown.config.js +3 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/build-tutorial.ts
|
|
2
|
+
import { VIDEO_FORMATS } from "@contractspec/lib.video-gen/design/layouts";
|
|
3
|
+
var DEFAULT_FPS = 30;
|
|
4
|
+
var DEFAULT_SCENE_DURATION_SECONDS = 12;
|
|
5
|
+
function buildTutorialVideo(tutorial, options) {
|
|
6
|
+
const fps = options?.fps ?? DEFAULT_FPS;
|
|
7
|
+
const sceneDuration = options?.sceneDurationSeconds ?? DEFAULT_SCENE_DURATION_SECONDS;
|
|
8
|
+
const durationInFrames = sceneDuration * fps;
|
|
9
|
+
return {
|
|
10
|
+
id: `tutorial-${tutorial.id}-${Date.now().toString(36)}`,
|
|
11
|
+
scenes: [
|
|
12
|
+
{
|
|
13
|
+
id: `scene-${tutorial.id}`,
|
|
14
|
+
compositionId: "TerminalDemo",
|
|
15
|
+
props: {
|
|
16
|
+
title: tutorial.title,
|
|
17
|
+
subtitle: tutorial.subtitle,
|
|
18
|
+
lines: tutorial.lines,
|
|
19
|
+
terminalTitle: tutorial.terminalTitle,
|
|
20
|
+
prompt: options?.prompt ?? "$ ",
|
|
21
|
+
summary: tutorial.summary
|
|
22
|
+
},
|
|
23
|
+
durationInFrames
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
totalDurationInFrames: durationInFrames,
|
|
27
|
+
fps,
|
|
28
|
+
format: VIDEO_FORMATS.landscape
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function buildTutorialSuite(tutorials, options) {
|
|
32
|
+
const fps = options?.fps ?? DEFAULT_FPS;
|
|
33
|
+
const sceneDuration = options?.sceneDurationSeconds ?? DEFAULT_SCENE_DURATION_SECONDS;
|
|
34
|
+
const durationInFrames = sceneDuration * fps;
|
|
35
|
+
const scenes = tutorials.map((tutorial) => ({
|
|
36
|
+
id: `scene-${tutorial.id}`,
|
|
37
|
+
compositionId: "TerminalDemo",
|
|
38
|
+
props: {
|
|
39
|
+
title: tutorial.title,
|
|
40
|
+
subtitle: tutorial.subtitle,
|
|
41
|
+
lines: tutorial.lines,
|
|
42
|
+
terminalTitle: tutorial.terminalTitle,
|
|
43
|
+
prompt: options?.prompt ?? "$ ",
|
|
44
|
+
summary: tutorial.summary
|
|
45
|
+
},
|
|
46
|
+
durationInFrames
|
|
47
|
+
}));
|
|
48
|
+
const totalDurationInFrames = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
|
|
49
|
+
return {
|
|
50
|
+
id: `tutorial-suite-${Date.now().toString(36)}`,
|
|
51
|
+
scenes,
|
|
52
|
+
totalDurationInFrames,
|
|
53
|
+
fps,
|
|
54
|
+
format: VIDEO_FORMATS.landscape
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
buildTutorialVideo,
|
|
59
|
+
buildTutorialSuite
|
|
60
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/docs/video-docs-terminal.docblock.ts
|
|
2
|
+
import { registerDocBlocks } from "@contractspec/lib.contracts-spec/docs";
|
|
3
|
+
var blocks = [
|
|
4
|
+
{
|
|
5
|
+
id: "docs.examples.video-docs-terminal",
|
|
6
|
+
title: "Video Docs Terminal (example)",
|
|
7
|
+
summary: "Generate terminal demo videos from CLI walkthroughs using the TerminalDemo composition and ScriptGenerator.",
|
|
8
|
+
kind: "reference",
|
|
9
|
+
visibility: "public",
|
|
10
|
+
route: "/docs/examples/video-docs-terminal",
|
|
11
|
+
tags: ["video", "documentation", "terminal", "cli", "example"],
|
|
12
|
+
body: `## What this example shows
|
|
13
|
+
|
|
14
|
+
- Defining CLI tutorials as structured \`CliTutorial\` objects with \`TerminalLine\` arrays.
|
|
15
|
+
- Building single-scene and multi-scene \`VideoProject\` instances using the \`TerminalDemo\` composition.
|
|
16
|
+
- Using \`ScriptGenerator\` (deterministic, no LLM) to generate narration from tutorial content briefs.
|
|
17
|
+
- Assembling a full documentation video covering init, build, validate, and deploy workflows.
|
|
18
|
+
|
|
19
|
+
## Key concepts
|
|
20
|
+
|
|
21
|
+
- **CliTutorial**: Combines \`TerminalLine[]\` (commands + output) with a \`ContentBrief\` for narration.
|
|
22
|
+
- **TerminalDemo**: The Remotion composition that renders animated terminal sessions.
|
|
23
|
+
- **ScriptGenerator**: Produces narration scripts from content briefs. Deterministic by default.
|
|
24
|
+
- **VideoProject**: The output scene graph -- one scene per tutorial, ready for rendering or preview.
|
|
25
|
+
|
|
26
|
+
## Notes
|
|
27
|
+
|
|
28
|
+
- No LLM or voice provider is needed -- the pipeline is fully deterministic.
|
|
29
|
+
- Each tutorial maps to one \`TerminalDemo\` scene in the final video project.
|
|
30
|
+
- The example produces the \`VideoProject\` data structure, not rendered MP4. Use \`LocalRenderer\` for final output.
|
|
31
|
+
`
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "docs.examples.video-docs-terminal.usage",
|
|
35
|
+
title: "Video Docs Terminal -- Usage",
|
|
36
|
+
summary: "How to generate terminal demo videos and narration from CLI tutorials.",
|
|
37
|
+
kind: "usage",
|
|
38
|
+
visibility: "public",
|
|
39
|
+
route: "/docs/examples/video-docs-terminal/usage",
|
|
40
|
+
tags: ["video", "terminal", "usage"],
|
|
41
|
+
body: `## Usage
|
|
42
|
+
|
|
43
|
+
### Build a single tutorial video
|
|
44
|
+
|
|
45
|
+
\`\`\`ts
|
|
46
|
+
import { buildTutorialVideo } from "@contractspec/example.video-docs-terminal/build-tutorial";
|
|
47
|
+
import { initTutorial } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
48
|
+
|
|
49
|
+
const project = buildTutorialVideo(initTutorial);
|
|
50
|
+
|
|
51
|
+
console.log(project.scenes.length); // 1
|
|
52
|
+
console.log(project.scenes[0].compositionId); // "TerminalDemo"
|
|
53
|
+
console.log(project.totalDurationInFrames); // 360 (12s × 30fps)
|
|
54
|
+
\`\`\`
|
|
55
|
+
|
|
56
|
+
### Build a multi-scene tutorial suite
|
|
57
|
+
|
|
58
|
+
\`\`\`ts
|
|
59
|
+
import { buildTutorialSuite } from "@contractspec/example.video-docs-terminal/build-tutorial";
|
|
60
|
+
import { allTutorials } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
61
|
+
|
|
62
|
+
const project = buildTutorialSuite(allTutorials);
|
|
63
|
+
|
|
64
|
+
console.log(project.scenes.length); // 4 (init, build, validate, deploy)
|
|
65
|
+
\`\`\`
|
|
66
|
+
|
|
67
|
+
### Generate narration
|
|
68
|
+
|
|
69
|
+
\`\`\`ts
|
|
70
|
+
import { generateTutorialNarration } from "@contractspec/example.video-docs-terminal/generate-narration";
|
|
71
|
+
import { buildTutorial } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
72
|
+
|
|
73
|
+
const narration = await generateTutorialNarration(buildTutorial);
|
|
74
|
+
|
|
75
|
+
console.log(narration.fullText); // Full narration text
|
|
76
|
+
console.log(narration.segments.length); // Per-scene segments
|
|
77
|
+
console.log(narration.estimatedDurationSeconds); // ~12s
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
## Guardrails
|
|
81
|
+
|
|
82
|
+
- Keep terminal lines concise -- long output slows the typing animation.
|
|
83
|
+
- Target 10-15 lines per tutorial for optimal pacing at 12 seconds per scene.
|
|
84
|
+
- The \`summary\` field is displayed as a call-out after the terminal completes -- keep it to one sentence.
|
|
85
|
+
- Use \`"technical"\` narration style for documentation videos and \`"professional"\` for marketing.
|
|
86
|
+
`
|
|
87
|
+
}
|
|
88
|
+
];
|
|
89
|
+
registerDocBlocks(blocks);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/docs/video-docs-terminal.docblock.ts
|
|
2
|
+
import { registerDocBlocks } from "@contractspec/lib.contracts-spec/docs";
|
|
3
|
+
var blocks = [
|
|
4
|
+
{
|
|
5
|
+
id: "docs.examples.video-docs-terminal",
|
|
6
|
+
title: "Video Docs Terminal (example)",
|
|
7
|
+
summary: "Generate terminal demo videos from CLI walkthroughs using the TerminalDemo composition and ScriptGenerator.",
|
|
8
|
+
kind: "reference",
|
|
9
|
+
visibility: "public",
|
|
10
|
+
route: "/docs/examples/video-docs-terminal",
|
|
11
|
+
tags: ["video", "documentation", "terminal", "cli", "example"],
|
|
12
|
+
body: `## What this example shows
|
|
13
|
+
|
|
14
|
+
- Defining CLI tutorials as structured \`CliTutorial\` objects with \`TerminalLine\` arrays.
|
|
15
|
+
- Building single-scene and multi-scene \`VideoProject\` instances using the \`TerminalDemo\` composition.
|
|
16
|
+
- Using \`ScriptGenerator\` (deterministic, no LLM) to generate narration from tutorial content briefs.
|
|
17
|
+
- Assembling a full documentation video covering init, build, validate, and deploy workflows.
|
|
18
|
+
|
|
19
|
+
## Key concepts
|
|
20
|
+
|
|
21
|
+
- **CliTutorial**: Combines \`TerminalLine[]\` (commands + output) with a \`ContentBrief\` for narration.
|
|
22
|
+
- **TerminalDemo**: The Remotion composition that renders animated terminal sessions.
|
|
23
|
+
- **ScriptGenerator**: Produces narration scripts from content briefs. Deterministic by default.
|
|
24
|
+
- **VideoProject**: The output scene graph -- one scene per tutorial, ready for rendering or preview.
|
|
25
|
+
|
|
26
|
+
## Notes
|
|
27
|
+
|
|
28
|
+
- No LLM or voice provider is needed -- the pipeline is fully deterministic.
|
|
29
|
+
- Each tutorial maps to one \`TerminalDemo\` scene in the final video project.
|
|
30
|
+
- The example produces the \`VideoProject\` data structure, not rendered MP4. Use \`LocalRenderer\` for final output.
|
|
31
|
+
`
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "docs.examples.video-docs-terminal.usage",
|
|
35
|
+
title: "Video Docs Terminal -- Usage",
|
|
36
|
+
summary: "How to generate terminal demo videos and narration from CLI tutorials.",
|
|
37
|
+
kind: "usage",
|
|
38
|
+
visibility: "public",
|
|
39
|
+
route: "/docs/examples/video-docs-terminal/usage",
|
|
40
|
+
tags: ["video", "terminal", "usage"],
|
|
41
|
+
body: `## Usage
|
|
42
|
+
|
|
43
|
+
### Build a single tutorial video
|
|
44
|
+
|
|
45
|
+
\`\`\`ts
|
|
46
|
+
import { buildTutorialVideo } from "@contractspec/example.video-docs-terminal/build-tutorial";
|
|
47
|
+
import { initTutorial } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
48
|
+
|
|
49
|
+
const project = buildTutorialVideo(initTutorial);
|
|
50
|
+
|
|
51
|
+
console.log(project.scenes.length); // 1
|
|
52
|
+
console.log(project.scenes[0].compositionId); // "TerminalDemo"
|
|
53
|
+
console.log(project.totalDurationInFrames); // 360 (12s × 30fps)
|
|
54
|
+
\`\`\`
|
|
55
|
+
|
|
56
|
+
### Build a multi-scene tutorial suite
|
|
57
|
+
|
|
58
|
+
\`\`\`ts
|
|
59
|
+
import { buildTutorialSuite } from "@contractspec/example.video-docs-terminal/build-tutorial";
|
|
60
|
+
import { allTutorials } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
61
|
+
|
|
62
|
+
const project = buildTutorialSuite(allTutorials);
|
|
63
|
+
|
|
64
|
+
console.log(project.scenes.length); // 4 (init, build, validate, deploy)
|
|
65
|
+
\`\`\`
|
|
66
|
+
|
|
67
|
+
### Generate narration
|
|
68
|
+
|
|
69
|
+
\`\`\`ts
|
|
70
|
+
import { generateTutorialNarration } from "@contractspec/example.video-docs-terminal/generate-narration";
|
|
71
|
+
import { buildTutorial } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
72
|
+
|
|
73
|
+
const narration = await generateTutorialNarration(buildTutorial);
|
|
74
|
+
|
|
75
|
+
console.log(narration.fullText); // Full narration text
|
|
76
|
+
console.log(narration.segments.length); // Per-scene segments
|
|
77
|
+
console.log(narration.estimatedDurationSeconds); // ~12s
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
## Guardrails
|
|
81
|
+
|
|
82
|
+
- Keep terminal lines concise -- long output slows the typing animation.
|
|
83
|
+
- Target 10-15 lines per tutorial for optimal pacing at 12 seconds per scene.
|
|
84
|
+
- The \`summary\` field is displayed as a call-out after the terminal completes -- keep it to one sentence.
|
|
85
|
+
- Use \`"technical"\` narration style for documentation videos and \`"professional"\` for marketing.
|
|
86
|
+
`
|
|
87
|
+
}
|
|
88
|
+
];
|
|
89
|
+
registerDocBlocks(blocks);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// src/example.ts
|
|
2
|
+
import { defineExample } from "@contractspec/lib.contracts-spec";
|
|
3
|
+
var example = defineExample({
|
|
4
|
+
meta: {
|
|
5
|
+
key: "video-docs-terminal",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
title: "Video Docs Terminal",
|
|
8
|
+
description: "Generate terminal demo videos from CLI walkthroughs using the TerminalDemo composition and ScriptGenerator.",
|
|
9
|
+
kind: "script",
|
|
10
|
+
visibility: "public",
|
|
11
|
+
stability: "experimental",
|
|
12
|
+
owners: ["@platform.core"],
|
|
13
|
+
tags: ["video", "documentation", "terminal", "cli", "tutorial"]
|
|
14
|
+
},
|
|
15
|
+
docs: {
|
|
16
|
+
rootDocId: "docs.examples.video-docs-terminal",
|
|
17
|
+
usageDocId: "docs.examples.video-docs-terminal.usage"
|
|
18
|
+
},
|
|
19
|
+
entrypoints: {
|
|
20
|
+
packageName: "@contractspec/example.video-docs-terminal",
|
|
21
|
+
docs: "./docs"
|
|
22
|
+
},
|
|
23
|
+
surfaces: {
|
|
24
|
+
templates: true,
|
|
25
|
+
sandbox: { enabled: true, modes: ["markdown"] },
|
|
26
|
+
studio: { enabled: true, installable: true },
|
|
27
|
+
mcp: { enabled: true }
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
var example_default = example;
|
|
31
|
+
export {
|
|
32
|
+
example_default as default
|
|
33
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/generate-narration.ts
|
|
2
|
+
import { ScriptGenerator } from "@contractspec/lib.video-gen/generators/script-generator";
|
|
3
|
+
async function generateTutorialNarration(tutorial, options) {
|
|
4
|
+
const generator = new ScriptGenerator;
|
|
5
|
+
const style = options?.style ?? "technical";
|
|
6
|
+
return generator.generate(tutorial.brief, { enabled: true, style });
|
|
7
|
+
}
|
|
8
|
+
async function generateSuiteNarration(tutorials, options) {
|
|
9
|
+
const results = await Promise.all(tutorials.map(async (tutorial) => {
|
|
10
|
+
const script = await generateTutorialNarration(tutorial, options);
|
|
11
|
+
return [tutorial.id, script];
|
|
12
|
+
}));
|
|
13
|
+
return new Map(results);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
generateTutorialNarration,
|
|
17
|
+
generateSuiteNarration
|
|
18
|
+
};
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
// src/build-tutorial.ts
|
|
2
|
+
import { VIDEO_FORMATS } from "@contractspec/lib.video-gen/design/layouts";
|
|
3
|
+
var DEFAULT_FPS = 30;
|
|
4
|
+
var DEFAULT_SCENE_DURATION_SECONDS = 12;
|
|
5
|
+
function buildTutorialVideo(tutorial, options) {
|
|
6
|
+
const fps = options?.fps ?? DEFAULT_FPS;
|
|
7
|
+
const sceneDuration = options?.sceneDurationSeconds ?? DEFAULT_SCENE_DURATION_SECONDS;
|
|
8
|
+
const durationInFrames = sceneDuration * fps;
|
|
9
|
+
return {
|
|
10
|
+
id: `tutorial-${tutorial.id}-${Date.now().toString(36)}`,
|
|
11
|
+
scenes: [
|
|
12
|
+
{
|
|
13
|
+
id: `scene-${tutorial.id}`,
|
|
14
|
+
compositionId: "TerminalDemo",
|
|
15
|
+
props: {
|
|
16
|
+
title: tutorial.title,
|
|
17
|
+
subtitle: tutorial.subtitle,
|
|
18
|
+
lines: tutorial.lines,
|
|
19
|
+
terminalTitle: tutorial.terminalTitle,
|
|
20
|
+
prompt: options?.prompt ?? "$ ",
|
|
21
|
+
summary: tutorial.summary
|
|
22
|
+
},
|
|
23
|
+
durationInFrames
|
|
24
|
+
}
|
|
25
|
+
],
|
|
26
|
+
totalDurationInFrames: durationInFrames,
|
|
27
|
+
fps,
|
|
28
|
+
format: VIDEO_FORMATS.landscape
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function buildTutorialSuite(tutorials, options) {
|
|
32
|
+
const fps = options?.fps ?? DEFAULT_FPS;
|
|
33
|
+
const sceneDuration = options?.sceneDurationSeconds ?? DEFAULT_SCENE_DURATION_SECONDS;
|
|
34
|
+
const durationInFrames = sceneDuration * fps;
|
|
35
|
+
const scenes = tutorials.map((tutorial) => ({
|
|
36
|
+
id: `scene-${tutorial.id}`,
|
|
37
|
+
compositionId: "TerminalDemo",
|
|
38
|
+
props: {
|
|
39
|
+
title: tutorial.title,
|
|
40
|
+
subtitle: tutorial.subtitle,
|
|
41
|
+
lines: tutorial.lines,
|
|
42
|
+
terminalTitle: tutorial.terminalTitle,
|
|
43
|
+
prompt: options?.prompt ?? "$ ",
|
|
44
|
+
summary: tutorial.summary
|
|
45
|
+
},
|
|
46
|
+
durationInFrames
|
|
47
|
+
}));
|
|
48
|
+
const totalDurationInFrames = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
|
|
49
|
+
return {
|
|
50
|
+
id: `tutorial-suite-${Date.now().toString(36)}`,
|
|
51
|
+
scenes,
|
|
52
|
+
totalDurationInFrames,
|
|
53
|
+
fps,
|
|
54
|
+
format: VIDEO_FORMATS.landscape
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/docs/video-docs-terminal.docblock.ts
|
|
59
|
+
import { registerDocBlocks } from "@contractspec/lib.contracts-spec/docs";
|
|
60
|
+
var blocks = [
|
|
61
|
+
{
|
|
62
|
+
id: "docs.examples.video-docs-terminal",
|
|
63
|
+
title: "Video Docs Terminal (example)",
|
|
64
|
+
summary: "Generate terminal demo videos from CLI walkthroughs using the TerminalDemo composition and ScriptGenerator.",
|
|
65
|
+
kind: "reference",
|
|
66
|
+
visibility: "public",
|
|
67
|
+
route: "/docs/examples/video-docs-terminal",
|
|
68
|
+
tags: ["video", "documentation", "terminal", "cli", "example"],
|
|
69
|
+
body: `## What this example shows
|
|
70
|
+
|
|
71
|
+
- Defining CLI tutorials as structured \`CliTutorial\` objects with \`TerminalLine\` arrays.
|
|
72
|
+
- Building single-scene and multi-scene \`VideoProject\` instances using the \`TerminalDemo\` composition.
|
|
73
|
+
- Using \`ScriptGenerator\` (deterministic, no LLM) to generate narration from tutorial content briefs.
|
|
74
|
+
- Assembling a full documentation video covering init, build, validate, and deploy workflows.
|
|
75
|
+
|
|
76
|
+
## Key concepts
|
|
77
|
+
|
|
78
|
+
- **CliTutorial**: Combines \`TerminalLine[]\` (commands + output) with a \`ContentBrief\` for narration.
|
|
79
|
+
- **TerminalDemo**: The Remotion composition that renders animated terminal sessions.
|
|
80
|
+
- **ScriptGenerator**: Produces narration scripts from content briefs. Deterministic by default.
|
|
81
|
+
- **VideoProject**: The output scene graph -- one scene per tutorial, ready for rendering or preview.
|
|
82
|
+
|
|
83
|
+
## Notes
|
|
84
|
+
|
|
85
|
+
- No LLM or voice provider is needed -- the pipeline is fully deterministic.
|
|
86
|
+
- Each tutorial maps to one \`TerminalDemo\` scene in the final video project.
|
|
87
|
+
- The example produces the \`VideoProject\` data structure, not rendered MP4. Use \`LocalRenderer\` for final output.
|
|
88
|
+
`
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "docs.examples.video-docs-terminal.usage",
|
|
92
|
+
title: "Video Docs Terminal -- Usage",
|
|
93
|
+
summary: "How to generate terminal demo videos and narration from CLI tutorials.",
|
|
94
|
+
kind: "usage",
|
|
95
|
+
visibility: "public",
|
|
96
|
+
route: "/docs/examples/video-docs-terminal/usage",
|
|
97
|
+
tags: ["video", "terminal", "usage"],
|
|
98
|
+
body: `## Usage
|
|
99
|
+
|
|
100
|
+
### Build a single tutorial video
|
|
101
|
+
|
|
102
|
+
\`\`\`ts
|
|
103
|
+
import { buildTutorialVideo } from "@contractspec/example.video-docs-terminal/build-tutorial";
|
|
104
|
+
import { initTutorial } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
105
|
+
|
|
106
|
+
const project = buildTutorialVideo(initTutorial);
|
|
107
|
+
|
|
108
|
+
console.log(project.scenes.length); // 1
|
|
109
|
+
console.log(project.scenes[0].compositionId); // "TerminalDemo"
|
|
110
|
+
console.log(project.totalDurationInFrames); // 360 (12s × 30fps)
|
|
111
|
+
\`\`\`
|
|
112
|
+
|
|
113
|
+
### Build a multi-scene tutorial suite
|
|
114
|
+
|
|
115
|
+
\`\`\`ts
|
|
116
|
+
import { buildTutorialSuite } from "@contractspec/example.video-docs-terminal/build-tutorial";
|
|
117
|
+
import { allTutorials } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
118
|
+
|
|
119
|
+
const project = buildTutorialSuite(allTutorials);
|
|
120
|
+
|
|
121
|
+
console.log(project.scenes.length); // 4 (init, build, validate, deploy)
|
|
122
|
+
\`\`\`
|
|
123
|
+
|
|
124
|
+
### Generate narration
|
|
125
|
+
|
|
126
|
+
\`\`\`ts
|
|
127
|
+
import { generateTutorialNarration } from "@contractspec/example.video-docs-terminal/generate-narration";
|
|
128
|
+
import { buildTutorial } from "@contractspec/example.video-docs-terminal/sample-tutorials";
|
|
129
|
+
|
|
130
|
+
const narration = await generateTutorialNarration(buildTutorial);
|
|
131
|
+
|
|
132
|
+
console.log(narration.fullText); // Full narration text
|
|
133
|
+
console.log(narration.segments.length); // Per-scene segments
|
|
134
|
+
console.log(narration.estimatedDurationSeconds); // ~12s
|
|
135
|
+
\`\`\`
|
|
136
|
+
|
|
137
|
+
## Guardrails
|
|
138
|
+
|
|
139
|
+
- Keep terminal lines concise -- long output slows the typing animation.
|
|
140
|
+
- Target 10-15 lines per tutorial for optimal pacing at 12 seconds per scene.
|
|
141
|
+
- The \`summary\` field is displayed as a call-out after the terminal completes -- keep it to one sentence.
|
|
142
|
+
- Use \`"technical"\` narration style for documentation videos and \`"professional"\` for marketing.
|
|
143
|
+
`
|
|
144
|
+
}
|
|
145
|
+
];
|
|
146
|
+
registerDocBlocks(blocks);
|
|
147
|
+
// src/example.ts
|
|
148
|
+
import { defineExample } from "@contractspec/lib.contracts-spec";
|
|
149
|
+
var example = defineExample({
|
|
150
|
+
meta: {
|
|
151
|
+
key: "video-docs-terminal",
|
|
152
|
+
version: "1.0.0",
|
|
153
|
+
title: "Video Docs Terminal",
|
|
154
|
+
description: "Generate terminal demo videos from CLI walkthroughs using the TerminalDemo composition and ScriptGenerator.",
|
|
155
|
+
kind: "script",
|
|
156
|
+
visibility: "public",
|
|
157
|
+
stability: "experimental",
|
|
158
|
+
owners: ["@platform.core"],
|
|
159
|
+
tags: ["video", "documentation", "terminal", "cli", "tutorial"]
|
|
160
|
+
},
|
|
161
|
+
docs: {
|
|
162
|
+
rootDocId: "docs.examples.video-docs-terminal",
|
|
163
|
+
usageDocId: "docs.examples.video-docs-terminal.usage"
|
|
164
|
+
},
|
|
165
|
+
entrypoints: {
|
|
166
|
+
packageName: "@contractspec/example.video-docs-terminal",
|
|
167
|
+
docs: "./docs"
|
|
168
|
+
},
|
|
169
|
+
surfaces: {
|
|
170
|
+
templates: true,
|
|
171
|
+
sandbox: { enabled: true, modes: ["markdown"] },
|
|
172
|
+
studio: { enabled: true, installable: true },
|
|
173
|
+
mcp: { enabled: true }
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
var example_default = example;
|
|
177
|
+
|
|
178
|
+
// src/generate-narration.ts
|
|
179
|
+
import { ScriptGenerator } from "@contractspec/lib.video-gen/generators/script-generator";
|
|
180
|
+
async function generateTutorialNarration(tutorial, options) {
|
|
181
|
+
const generator = new ScriptGenerator;
|
|
182
|
+
const style = options?.style ?? "technical";
|
|
183
|
+
return generator.generate(tutorial.brief, { enabled: true, style });
|
|
184
|
+
}
|
|
185
|
+
async function generateSuiteNarration(tutorials, options) {
|
|
186
|
+
const results = await Promise.all(tutorials.map(async (tutorial) => {
|
|
187
|
+
const script = await generateTutorialNarration(tutorial, options);
|
|
188
|
+
return [tutorial.id, script];
|
|
189
|
+
}));
|
|
190
|
+
return new Map(results);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// src/sample-tutorials.ts
|
|
194
|
+
var initTutorial = {
|
|
195
|
+
id: "init",
|
|
196
|
+
title: "Initialize a Project",
|
|
197
|
+
subtitle: "Set up a new ContractSpec workspace in seconds",
|
|
198
|
+
terminalTitle: "~/projects",
|
|
199
|
+
lines: [
|
|
200
|
+
{ text: "contractspec init my-api", type: "command" },
|
|
201
|
+
{ text: "Creating project my-api...", type: "output", delay: 15 },
|
|
202
|
+
{ text: " ├── contracts/", type: "output", delay: 5 },
|
|
203
|
+
{ text: " ├── generated/", type: "output", delay: 5 },
|
|
204
|
+
{ text: " ├── contractspec.config.ts", type: "output", delay: 5 },
|
|
205
|
+
{ text: " └── package.json", type: "output", delay: 5 },
|
|
206
|
+
{ text: "✓ Project initialized", type: "success", delay: 10 },
|
|
207
|
+
{ text: "cd my-api", type: "command", delay: 15 },
|
|
208
|
+
{ text: "contractspec status", type: "command", delay: 15 },
|
|
209
|
+
{
|
|
210
|
+
text: "0 contracts · 0 generated files · ready",
|
|
211
|
+
type: "output",
|
|
212
|
+
delay: 10
|
|
213
|
+
}
|
|
214
|
+
],
|
|
215
|
+
summary: "Your project is ready. Define contracts next.",
|
|
216
|
+
brief: {
|
|
217
|
+
title: "Initialize a ContractSpec Project",
|
|
218
|
+
summary: "The init command scaffolds a new workspace with contracts, generated output, and configuration.",
|
|
219
|
+
problems: [
|
|
220
|
+
"Setting up API projects manually is tedious and error-prone",
|
|
221
|
+
"Teams need a consistent project structure from day one"
|
|
222
|
+
],
|
|
223
|
+
solutions: [
|
|
224
|
+
"One command creates the entire project scaffold",
|
|
225
|
+
"Standard structure ensures consistency across teams"
|
|
226
|
+
],
|
|
227
|
+
audience: {
|
|
228
|
+
role: "Developer",
|
|
229
|
+
painPoints: ["Manual project setup", "Inconsistent project structure"]
|
|
230
|
+
},
|
|
231
|
+
callToAction: "Run contractspec init to get started."
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
var buildTutorial = {
|
|
235
|
+
id: "build",
|
|
236
|
+
title: "Build from Contracts",
|
|
237
|
+
subtitle: "Generate all surfaces from a single spec",
|
|
238
|
+
terminalTitle: "~/projects/my-api",
|
|
239
|
+
lines: [
|
|
240
|
+
{ text: "# Define a contract first", type: "comment" },
|
|
241
|
+
{ text: "contractspec build", type: "command", delay: 15 },
|
|
242
|
+
{ text: "Building 3 contracts...", type: "output", delay: 15 },
|
|
243
|
+
{ text: " → CreateUser REST + GraphQL + DB", type: "output", delay: 8 },
|
|
244
|
+
{ text: " → ListUsers REST + GraphQL", type: "output", delay: 8 },
|
|
245
|
+
{ text: " → DeleteUser REST + GraphQL + DB", type: "output", delay: 8 },
|
|
246
|
+
{ text: "✓ 18 files generated in 0.4s", type: "success", delay: 12 },
|
|
247
|
+
{ text: "contractspec status", type: "command", delay: 15 },
|
|
248
|
+
{
|
|
249
|
+
text: "3 contracts · 18 generated files · all up to date",
|
|
250
|
+
type: "output",
|
|
251
|
+
delay: 10
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
summary: "3 contracts → 18 files. One spec, every surface.",
|
|
255
|
+
brief: {
|
|
256
|
+
title: "Build from Contracts",
|
|
257
|
+
summary: "The build command reads your contract definitions and generates REST, GraphQL, DB schemas, and more.",
|
|
258
|
+
problems: [
|
|
259
|
+
"Manually writing the same logic across REST, GraphQL, and DB",
|
|
260
|
+
"Generated code drifts out of sync with the spec"
|
|
261
|
+
],
|
|
262
|
+
solutions: [
|
|
263
|
+
"Deterministic build: same spec always produces the same output",
|
|
264
|
+
"All surfaces generated in a single pass"
|
|
265
|
+
],
|
|
266
|
+
metrics: [
|
|
267
|
+
"18 files from 3 contracts in 0.4 seconds",
|
|
268
|
+
"Zero manual synchronization"
|
|
269
|
+
],
|
|
270
|
+
audience: {
|
|
271
|
+
role: "Developer",
|
|
272
|
+
painPoints: ["Cross-surface code duplication", "Schema drift"]
|
|
273
|
+
},
|
|
274
|
+
callToAction: "Run contractspec build after defining your contracts."
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
var validateTutorial = {
|
|
278
|
+
id: "validate",
|
|
279
|
+
title: "Validate Contracts",
|
|
280
|
+
subtitle: "Catch errors before they reach production",
|
|
281
|
+
terminalTitle: "~/projects/my-api",
|
|
282
|
+
lines: [
|
|
283
|
+
{ text: "contractspec validate", type: "command" },
|
|
284
|
+
{ text: "Validating 3 contracts...", type: "output", delay: 15 },
|
|
285
|
+
{ text: " ✓ CreateUser schema valid", type: "success", delay: 8 },
|
|
286
|
+
{ text: " ✓ ListUsers schema valid", type: "success", delay: 8 },
|
|
287
|
+
{
|
|
288
|
+
text: ' ✗ DeleteUser missing required field "reason"',
|
|
289
|
+
type: "error",
|
|
290
|
+
delay: 8
|
|
291
|
+
},
|
|
292
|
+
{ text: "", type: "output", delay: 5 },
|
|
293
|
+
{ text: "2 passed · 1 failed", type: "output", delay: 10 },
|
|
294
|
+
{ text: "# Fix the contract and re-validate", type: "comment", delay: 15 },
|
|
295
|
+
{ text: "contractspec validate", type: "command", delay: 15 },
|
|
296
|
+
{ text: " ✓ CreateUser schema valid", type: "success", delay: 8 },
|
|
297
|
+
{ text: " ✓ ListUsers schema valid", type: "success", delay: 8 },
|
|
298
|
+
{ text: " ✓ DeleteUser schema valid", type: "success", delay: 8 },
|
|
299
|
+
{ text: "✓ All 3 contracts valid", type: "success", delay: 10 }
|
|
300
|
+
],
|
|
301
|
+
summary: "Validate early, validate often.",
|
|
302
|
+
brief: {
|
|
303
|
+
title: "Validate Contracts",
|
|
304
|
+
summary: "The validate command checks all contracts against their schemas before generating code.",
|
|
305
|
+
problems: [
|
|
306
|
+
"Invalid schemas slip through to production",
|
|
307
|
+
"Catching errors late in the pipeline costs time"
|
|
308
|
+
],
|
|
309
|
+
solutions: [
|
|
310
|
+
"Pre-build validation catches schema errors instantly",
|
|
311
|
+
"Clear error messages pinpoint exactly what needs fixing"
|
|
312
|
+
],
|
|
313
|
+
audience: {
|
|
314
|
+
role: "Developer",
|
|
315
|
+
painPoints: ["Invalid schemas in production", "Late error detection"]
|
|
316
|
+
},
|
|
317
|
+
callToAction: "Run contractspec validate as part of your CI pipeline."
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
var deployTutorial = {
|
|
321
|
+
id: "deploy",
|
|
322
|
+
title: "Deploy Artifacts",
|
|
323
|
+
subtitle: "Ship generated code to production",
|
|
324
|
+
terminalTitle: "~/projects/my-api",
|
|
325
|
+
lines: [
|
|
326
|
+
{ text: "contractspec build --production", type: "command" },
|
|
327
|
+
{
|
|
328
|
+
text: "✓ 18 files generated (production mode)",
|
|
329
|
+
type: "success",
|
|
330
|
+
delay: 15
|
|
331
|
+
},
|
|
332
|
+
{ text: "contractspec publish --dry-run", type: "command", delay: 15 },
|
|
333
|
+
{
|
|
334
|
+
text: "Publishing @my-api/contracts v1.2.0...",
|
|
335
|
+
type: "output",
|
|
336
|
+
delay: 12
|
|
337
|
+
},
|
|
338
|
+
{ text: " → npm pack (dry run)", type: "output", delay: 8 },
|
|
339
|
+
{ text: " → 3 contracts, 18 generated files", type: "output", delay: 8 },
|
|
340
|
+
{ text: " → Package size: 24.3 KB", type: "output", delay: 8 },
|
|
341
|
+
{
|
|
342
|
+
text: "✓ Dry run complete -- ready to publish",
|
|
343
|
+
type: "success",
|
|
344
|
+
delay: 10
|
|
345
|
+
},
|
|
346
|
+
{ text: "contractspec publish", type: "command", delay: 15 },
|
|
347
|
+
{ text: "✓ Published @my-api/contracts@1.2.0", type: "success", delay: 15 }
|
|
348
|
+
],
|
|
349
|
+
summary: "From spec to production in one pipeline.",
|
|
350
|
+
brief: {
|
|
351
|
+
title: "Deploy Artifacts",
|
|
352
|
+
summary: "Build in production mode and publish your generated contracts as an npm package.",
|
|
353
|
+
problems: [
|
|
354
|
+
"Deploying hand-written API code is risky and manual",
|
|
355
|
+
"Teams need confidence that generated code matches the spec"
|
|
356
|
+
],
|
|
357
|
+
solutions: [
|
|
358
|
+
"Production builds are deterministic and reproducible",
|
|
359
|
+
"Dry-run publishing catches packaging issues before release"
|
|
360
|
+
],
|
|
361
|
+
metrics: [
|
|
362
|
+
"24.3 KB package with 3 contracts and 18 files",
|
|
363
|
+
"Entire pipeline runs in seconds"
|
|
364
|
+
],
|
|
365
|
+
audience: {
|
|
366
|
+
role: "DevOps Engineer",
|
|
367
|
+
painPoints: ["Manual deployment processes", "Spec-to-production drift"]
|
|
368
|
+
},
|
|
369
|
+
callToAction: "Add contractspec publish to your CI/CD pipeline."
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
var allTutorials = [
|
|
373
|
+
initTutorial,
|
|
374
|
+
buildTutorial,
|
|
375
|
+
validateTutorial,
|
|
376
|
+
deployTutorial
|
|
377
|
+
];
|
|
378
|
+
export {
|
|
379
|
+
validateTutorial,
|
|
380
|
+
initTutorial,
|
|
381
|
+
generateTutorialNarration,
|
|
382
|
+
generateSuiteNarration,
|
|
383
|
+
example_default as example,
|
|
384
|
+
deployTutorial,
|
|
385
|
+
buildTutorialVideo,
|
|
386
|
+
buildTutorialSuite,
|
|
387
|
+
buildTutorial,
|
|
388
|
+
allTutorials
|
|
389
|
+
};
|