@nebutra/video-pipeline 0.1.2 → 0.1.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nebutra/video-pipeline",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Storyboard-first video planning, rendering manifests, and cost previews",
5
5
  "private": false,
6
6
  "license": "MIT",
@@ -23,17 +23,21 @@
23
23
  "category": "ai",
24
24
  "summary": "Storyboard-first brand video planning, cost, preview, and composition surface"
25
25
  },
26
- "main": "./src/index.ts",
27
- "types": "./src/index.ts",
26
+ "main": "./dist/index.js",
27
+ "types": "./dist/index.d.ts",
28
28
  "exports": {
29
- ".": "./src/index.ts"
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js",
32
+ "default": "./dist/index.js"
33
+ }
30
34
  },
31
35
  "dependencies": {
32
- "@nebutra/capability-kit": "0.2.2",
33
- "@nebutra/generation-context": "0.1.2",
34
- "@nebutra/image-pipeline": "0.1.2",
35
- "@nebutra/errors": "0.1.2",
36
- "@nebutra/reel": "1.0.2"
36
+ "@nebutra/generation-context": "0.1.3",
37
+ "@nebutra/capability-kit": "0.2.4",
38
+ "@nebutra/reel": "1.0.4",
39
+ "@nebutra/image-pipeline": "0.1.3",
40
+ "@nebutra/errors": "0.1.2"
37
41
  },
38
42
  "devDependencies": {
39
43
  "@types/node": "^25.9.1",
@@ -54,6 +58,12 @@
54
58
  "publishConfig": {
55
59
  "access": "public"
56
60
  },
61
+ "files": [
62
+ "dist",
63
+ "README.md",
64
+ "LICENSE",
65
+ "CHANGELOG.md"
66
+ ],
57
67
  "scripts": {
58
68
  "build": "tsup",
59
69
  "test": "vitest run",
@@ -1,22 +0,0 @@
1
-
2
- > @nebutra/video-pipeline@0.1.2 build /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/video-pipeline
3
- > tsup
4
-
5
- CLI Building entry: src/cli.ts, src/index.ts
6
- CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.5.1
8
- CLI Using tsup config: /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/video-pipeline/tsup.config.ts
9
- CLI Target: es2022
10
- CLI Cleaning output folder
11
- ESM Build start
12
- ESM dist/chunk-YOKTCRLB.js 4.78 KB
13
- ESM dist/cli.js 1.18 KB
14
- ESM dist/index.js 152.00 B
15
- ESM dist/chunk-YOKTCRLB.js.map 9.72 KB
16
- ESM dist/index.js.map 71.00 B
17
- ESM dist/cli.js.map 2.10 KB
18
- ESM ⚡️ Build success in 14ms
19
- DTS Build start
20
- DTS ⚡️ Build success in 5890ms
21
- DTS dist/cli.d.ts 13.00 B
22
- DTS dist/index.d.ts 1.94 KB
@@ -1,14 +0,0 @@
1
-
2
- > @nebutra/video-pipeline@0.1.1 test /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/video-pipeline
3
- > vitest run
4
-
5
-
6
- RUN v4.1.4 /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/video-pipeline
7
-
8
- ✓ src/index.test.ts (2 tests) 29ms
9
-
10
- Test Files 1 passed (1)
11
- Tests 2 passed (2)
12
- Start at 09:41:00
13
- Duration 1.05s (transform 255ms, setup 0ms, import 403ms, tests 29ms, environment 0ms)
14
-
@@ -1,4 +0,0 @@
1
-
2
- > @nebutra/video-pipeline@0.1.2 typecheck /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/video-pipeline
3
- > tsc --noEmit
4
-
package/examples/cost.ts DELETED
@@ -1,10 +0,0 @@
1
- import { createDemoBrandContext } from "@nebutra/generation-context";
2
- import { VideoPipeline } from "../src/index";
3
-
4
- const pipeline = new VideoPipeline();
5
- const storyboard = await pipeline.plan(
6
- { type: "brand-film", durationS: 60, theme: "debugging launch" },
7
- createDemoBrandContext(),
8
- );
9
-
10
- process.stdout.write(`${JSON.stringify(await pipeline.cost(storyboard), null, 2)}\n`);
package/examples/plan.ts DELETED
@@ -1,9 +0,0 @@
1
- import { createDemoBrandContext } from "@nebutra/generation-context";
2
- import { VideoPipeline } from "../src/index";
3
-
4
- const storyboard = await new VideoPipeline().plan(
5
- { type: "brand-film", durationS: 24, theme: "indie developer journey" },
6
- createDemoBrandContext(),
7
- );
8
-
9
- process.stdout.write(`${JSON.stringify(storyboard.scenes, null, 2)}\n`);
@@ -1,10 +0,0 @@
1
- import { createDemoBrandContext } from "@nebutra/generation-context";
2
- import { VideoPipeline } from "../src/index";
3
-
4
- const pipeline = new VideoPipeline();
5
- const storyboard = await pipeline.plan(
6
- { type: "turntable", durationS: 8, subject: "product mockup" },
7
- createDemoBrandContext(),
8
- );
9
-
10
- process.stdout.write(`${JSON.stringify(await pipeline.preview(storyboard), null, 2)}\n`);
package/src/cli.ts DELETED
@@ -1,31 +0,0 @@
1
- import { createDemoBrandContext } from "@nebutra/generation-context";
2
- import { readVideoDebug, VideoPipeline } from "./index";
3
-
4
- const command = process.argv[2] ?? "doctor";
5
- const pipeline = new VideoPipeline();
6
- const brand = createDemoBrandContext();
7
- const storyboard = await pipeline.plan(
8
- { type: "brand-film", durationS: 16, theme: "indie developer journey" },
9
- brand,
10
- );
11
-
12
- if (command === "doctor") {
13
- process.stdout.write(
14
- `${JSON.stringify({ capability: "video-pipeline", results: await pipeline.doctor() }, null, 2)}\n`,
15
- );
16
- } else if (command === "debug") {
17
- process.stdout.write(
18
- `${JSON.stringify({ capability: "video-pipeline", entries: await readVideoDebug() }, null, 2)}\n`,
19
- );
20
- } else if (command === "cost") {
21
- process.stdout.write(
22
- `${JSON.stringify({ capability: "video-pipeline", cost: await pipeline.cost(storyboard) }, null, 2)}\n`,
23
- );
24
- } else if (command === "preview") {
25
- process.stdout.write(
26
- `${JSON.stringify({ capability: "video-pipeline", preview: await pipeline.preview(storyboard) }, null, 2)}\n`,
27
- );
28
- } else {
29
- process.stderr.write(`Unknown video-pipeline command: ${command}\n`);
30
- process.exitCode = 1;
31
- }
package/src/index.test.ts DELETED
@@ -1,34 +0,0 @@
1
- import { mkdtemp, readFile, rm } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
3
- import { join } from "node:path";
4
- import { createDemoBrandContext } from "@nebutra/generation-context";
5
- import { afterEach, describe, expect, it } from "vitest";
6
- import { VideoPipeline } from "./index";
7
-
8
- let root: string | undefined;
9
-
10
- afterEach(async () => {
11
- if (root) await rm(root, { recursive: true, force: true });
12
- root = undefined;
13
- });
14
-
15
- describe("VideoPipeline", () => {
16
- it("requires storyboard before render", async () => {
17
- root = await mkdtemp(join(tmpdir(), "video-pipeline-"));
18
- const pipeline = new VideoPipeline({ root });
19
- const brand = createDemoBrandContext();
20
- const storyboard = await pipeline.plan(
21
- { type: "brand-film", durationS: 20, theme: "launch" },
22
- brand,
23
- );
24
- expect(storyboard.scenes.length).toBeGreaterThan(1);
25
- const asset = await pipeline.render(storyboard, brand);
26
- expect(await readFile(asset.path, "utf8")).toContain(storyboard.id);
27
- });
28
-
29
- it("requires BrandContext", async () => {
30
- await expect(
31
- new VideoPipeline().plan({ type: "clip", durationS: 4, prompt: "ship" }, undefined),
32
- ).rejects.toMatchObject({ capability: "video-pipeline" });
33
- });
34
- });
package/src/index.ts DELETED
@@ -1,180 +0,0 @@
1
- import { mkdir, writeFile } from "node:fs/promises";
2
- import { dirname, join } from "node:path";
3
- import { appendCapabilityDebug, readCapabilityDebug } from "@nebutra/capability-kit/debug";
4
- import {
5
- assetId,
6
- type BrandContext,
7
- type GeneratedAsset,
8
- requireBrandContext,
9
- summarizeBrandContext,
10
- } from "@nebutra/generation-context";
11
- import {
12
- type StoryboardPlan,
13
- type StoryboardScene,
14
- storyboardTotalDuration,
15
- } from "@nebutra/reel/storyboard";
16
-
17
- export type VideoIntent =
18
- | { type: "brand-film"; durationS: number; theme: string }
19
- | { type: "turntable"; durationS: number; subject: string }
20
- | { type: "clip"; durationS: number; prompt: string };
21
-
22
- export type Storyboard = StoryboardPlan<VideoIntent>;
23
-
24
- export interface VideoAsset extends GeneratedAsset {
25
- readonly kind: "video";
26
- readonly durationS: number;
27
- readonly format: "manifest-json" | "mp4";
28
- readonly storyboardId: string;
29
- }
30
-
31
- export interface SyncedVideoOutput {
32
- readonly videoTrack: readonly VideoAsset[];
33
- readonly audioTrack?: readonly GeneratedAsset[];
34
- readonly voiceTrack?: readonly GeneratedAsset[];
35
- readonly captionTrack?: readonly { startS: number; endS: number; text: string }[];
36
- }
37
-
38
- export interface VideoHealth {
39
- readonly provider: string;
40
- readonly ok: boolean;
41
- readonly suggestion?: string;
42
- }
43
-
44
- export interface VideoPipelineOptions {
45
- readonly root?: string;
46
- }
47
-
48
- export async function readVideoDebug(root = process.cwd(), limit = 10): Promise<unknown[]> {
49
- return readCapabilityDebug("video-pipeline", { root, limit });
50
- }
51
-
52
- function sceneCount(durationS: number): number {
53
- return Math.max(1, Math.min(8, Math.ceil(durationS / 8)));
54
- }
55
-
56
- export class VideoPipeline {
57
- readonly #root: string;
58
-
59
- constructor(options: VideoPipelineOptions = {}) {
60
- this.#root = options.root ?? process.cwd();
61
- }
62
-
63
- async plan(intent: VideoIntent, brandInput: BrandContext | undefined): Promise<Storyboard> {
64
- const brand = requireBrandContext(brandInput, "video-pipeline");
65
- const count = sceneCount(intent.durationS);
66
- const baseDuration = Math.max(1, Math.floor(intent.durationS / count));
67
- const scenes = Array.from({ length: count }, (_, index): StoryboardScene => {
68
- const sceneNumber = index + 1;
69
- const durationS =
70
- index === count - 1 ? intent.durationS - baseDuration * index : baseDuration;
71
- const prompt = `${brand.name} ${intent.type} scene ${sceneNumber}: ${summarizeBrandContext(brand)}`;
72
- return {
73
- id: `scene_${sceneNumber}`,
74
- sceneIndex: sceneNumber,
75
- prompt,
76
- description: prompt,
77
- duration: durationS,
78
- durationS,
79
- status: "draft",
80
- outputEnabled: true,
81
- selectedImageIndex: -1,
82
- outputHistory: [],
83
- outputHistoryCursor: -1,
84
- referenceImages: brand.referenceImages.map((reference) => reference.path),
85
- transition: index === 0 ? "cut" : "fade",
86
- musicCue: brand.toneKeywords.join(", "),
87
- voiceCue: sceneNumber === 1 ? "introduce the product promise" : "advance the story",
88
- };
89
- });
90
- return {
91
- id: assetId("storyboard", `${intent.type}_${brand.brandId}`),
92
- tenantId: brand.tenantId,
93
- brandId: brand.brandId,
94
- intent,
95
- scenes,
96
- totalDurationS: storyboardTotalDuration(scenes),
97
- };
98
- }
99
-
100
- async render(storyboard: Storyboard, brandInput: BrandContext | undefined): Promise<VideoAsset> {
101
- const brand = requireBrandContext(brandInput, "video-pipeline");
102
- const id = assetId("video", storyboard.id);
103
- const path = join(this.#root, ".nebutra", "generated", "video-pipeline", `${id}.video.json`);
104
- await mkdir(dirname(path), { recursive: true });
105
- await writeFile(
106
- path,
107
- `${JSON.stringify({ storyboard, brand: summarizeBrandContext(brand), renderer: "manifest-local" }, null, 2)}\n`,
108
- "utf8",
109
- );
110
- const asset: VideoAsset = {
111
- id,
112
- tenantId: brand.tenantId,
113
- kind: "video",
114
- path,
115
- brandId: brand.brandId,
116
- provider: "manifest-local",
117
- model: "storyboard-manifest-v1",
118
- createdAt: new Date().toISOString(),
119
- license: { status: "commercial-ok", source: "deterministic local manifest" },
120
- durationS: storyboard.totalDurationS,
121
- format: "manifest-json",
122
- storyboardId: storyboard.id,
123
- metadata: { scenes: storyboard.scenes.length },
124
- };
125
- await appendCapabilityDebug("video-pipeline", { type: "render", asset }, { root: this.#root });
126
- return asset;
127
- }
128
-
129
- async create(intent: VideoIntent, brand: BrandContext | undefined): Promise<VideoAsset> {
130
- return this.render(await this.plan(intent, brand), brand);
131
- }
132
-
133
- async compose(output: SyncedVideoOutput): Promise<VideoAsset> {
134
- const first = output.videoTrack[0];
135
- if (!first) {
136
- throw new Error("compose requires at least one video track");
137
- }
138
- const id = assetId("composition", first.id);
139
- const path = join(this.#root, ".nebutra", "generated", "video-pipeline", `${id}.compose.json`);
140
- await mkdir(dirname(path), { recursive: true });
141
- await writeFile(path, `${JSON.stringify(output, null, 2)}\n`, "utf8");
142
- return { ...first, id, path, storyboardId: first.storyboardId };
143
- }
144
-
145
- async cost(storyboard: Storyboard): Promise<{ estimatedUsd: number; durationS: number }> {
146
- return {
147
- estimatedUsd: Number((storyboard.totalDurationS * 0.003).toFixed(4)),
148
- durationS: storyboard.totalDurationS,
149
- };
150
- }
151
-
152
- async preview(storyboard: Storyboard): Promise<{ path: string }> {
153
- const path = join(
154
- this.#root,
155
- ".nebutra",
156
- "generated",
157
- "video-pipeline",
158
- `${storyboard.id}.preview.json`,
159
- );
160
- await mkdir(dirname(path), { recursive: true });
161
- await writeFile(path, `${JSON.stringify(storyboard, null, 2)}\n`, "utf8");
162
- return { path };
163
- }
164
-
165
- async doctor(): Promise<VideoHealth[]> {
166
- return [
167
- { provider: "manifest-local", ok: true },
168
- {
169
- provider: "local-video-model",
170
- ok: Boolean(process.env.VIDEO_LOCAL_MODEL_PATH),
171
- suggestion: "Set VIDEO_LOCAL_MODEL_PATH to enable local clip rendering.",
172
- },
173
- {
174
- provider: "remote-video",
175
- ok: Boolean(process.env.VIDEO_REMOTE_API_KEY),
176
- suggestion: "Set VIDEO_REMOTE_API_KEY to enable remote video fallback.",
177
- },
178
- ];
179
- }
180
- }
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "target": "esnext",
7
- "types": ["node"],
8
- "incremental": false
9
- },
10
- "include": ["src", "examples"],
11
- "exclude": ["node_modules", "dist"]
12
- }
package/tsup.config.ts DELETED
@@ -1,17 +0,0 @@
1
- import { defineConfig } from "tsup";
2
-
3
- export default defineConfig({
4
- entry: ["src/index.ts", "src/cli.ts"],
5
- format: ["esm"],
6
- dts: true,
7
- sourcemap: true,
8
- clean: true,
9
- target: "es2022",
10
- external: [
11
- "@nebutra/capability-kit/debug",
12
- "@nebutra/errors",
13
- "@nebutra/generation-context",
14
- "@nebutra/image-pipeline",
15
- "@nebutra/reel/storyboard",
16
- ],
17
- });