@kvman/kvvideo 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +10 -2
- package/dist/api.d.ts +79 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +2 -0
- package/dist/api.js.map +1 -0
- package/dist/browser/channels.d.ts +6 -0
- package/dist/browser/channels.d.ts.map +1 -0
- package/dist/browser/channels.js +5 -0
- package/dist/browser/channels.js.map +1 -0
- package/dist/browser/launch.d.ts +4 -0
- package/dist/browser/launch.d.ts.map +1 -0
- package/dist/browser/launch.js +8 -0
- package/dist/browser/launch.js.map +1 -0
- package/dist/browser/start-browser.d.ts +5 -0
- package/dist/browser/start-browser.d.ts.map +1 -0
- package/dist/browser/start-browser.js +17 -0
- package/dist/browser/start-browser.js.map +1 -0
- package/dist/compose/ass-file.d.ts +12 -0
- package/dist/compose/ass-file.d.ts.map +1 -0
- package/dist/compose/ass-file.js +36 -0
- package/dist/compose/ass-file.js.map +1 -0
- package/dist/compose/caption-font.d.ts +6 -0
- package/dist/compose/caption-font.d.ts.map +1 -0
- package/dist/compose/caption-font.js +23 -0
- package/dist/compose/caption-font.js.map +1 -0
- package/dist/compose/compose-input.d.ts +48 -0
- package/dist/compose/compose-input.d.ts.map +1 -0
- package/dist/compose/compose-input.js +37 -0
- package/dist/compose/compose-input.js.map +1 -0
- package/dist/compose/player-copies.d.ts +6 -0
- package/dist/compose/player-copies.d.ts.map +1 -0
- package/dist/compose/player-copies.js +31 -0
- package/dist/compose/player-copies.js.map +1 -0
- package/dist/compose/register-compose.d.ts +3 -0
- package/dist/compose/register-compose.d.ts.map +1 -0
- package/dist/compose/register-compose.js +65 -0
- package/dist/compose/register-compose.js.map +1 -0
- package/dist/compose/render.d.ts +16 -0
- package/dist/compose/render.d.ts.map +1 -0
- package/dist/compose/render.js +35 -0
- package/dist/compose/render.js.map +1 -0
- package/dist/compose/scene-args.d.ts +12 -0
- package/dist/compose/scene-args.d.ts.map +1 -0
- package/dist/compose/scene-args.js +42 -0
- package/dist/compose/scene-args.js.map +1 -0
- package/dist/compose/scene-plan.d.ts +28 -0
- package/dist/compose/scene-plan.d.ts.map +1 -0
- package/dist/compose/scene-plan.js +32 -0
- package/dist/compose/scene-plan.js.map +1 -0
- package/dist/connector.d.ts +79 -0
- package/dist/connector.d.ts.map +1 -0
- package/dist/connector.js +44 -0
- package/dist/connector.js.map +1 -0
- package/dist/files/answer-path.d.ts +3 -0
- package/dist/files/answer-path.d.ts.map +1 -0
- package/dist/files/answer-path.js +6 -0
- package/dist/files/answer-path.js.map +1 -0
- package/dist/files/place-output.d.ts +8 -0
- package/dist/files/place-output.d.ts.map +1 -0
- package/dist/files/place-output.js +24 -0
- package/dist/files/place-output.js.map +1 -0
- package/dist/files/workspace-paths.d.ts +7 -0
- package/dist/files/workspace-paths.d.ts.map +1 -0
- package/dist/files/workspace-paths.js +48 -0
- package/dist/files/workspace-paths.js.map +1 -0
- package/dist/fonts/bundled-fonts.d.ts +10 -0
- package/dist/fonts/bundled-fonts.d.ts.map +1 -0
- package/dist/fonts/bundled-fonts.js +10 -0
- package/dist/fonts/bundled-fonts.js.map +1 -0
- package/dist/fonts/font-family.d.ts +2 -0
- package/dist/fonts/font-family.d.ts.map +1 -0
- package/dist/fonts/font-family.js +43 -0
- package/dist/fonts/font-family.js.map +1 -0
- package/dist/fonts/register-fonts.d.ts +3 -0
- package/dist/fonts/register-fonts.d.ts.map +1 -0
- package/dist/fonts/register-fonts.js +12 -0
- package/dist/fonts/register-fonts.js.map +1 -0
- package/dist/guide.d.ts +3 -0
- package/dist/guide.d.ts.map +1 -0
- package/dist/guide.js +6 -0
- package/dist/guide.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/narration/captions.d.ts +10 -0
- package/dist/narration/captions.d.ts.map +1 -0
- package/dist/narration/captions.js +42 -0
- package/dist/narration/captions.js.map +1 -0
- package/dist/narration/piper.d.ts +8 -0
- package/dist/narration/piper.d.ts.map +1 -0
- package/dist/narration/piper.js +19 -0
- package/dist/narration/piper.js.map +1 -0
- package/dist/narration/register-narration.d.ts +17 -0
- package/dist/narration/register-narration.d.ts.map +1 -0
- package/dist/narration/register-narration.js +75 -0
- package/dist/narration/register-narration.js.map +1 -0
- package/dist/narration/speech-services.d.ts +19 -0
- package/dist/narration/speech-services.d.ts.map +1 -0
- package/dist/narration/speech-services.js +50 -0
- package/dist/narration/speech-services.js.map +1 -0
- package/dist/problems.d.ts +12 -0
- package/dist/problems.d.ts.map +1 -0
- package/dist/problems.js +19 -0
- package/dist/problems.js.map +1 -0
- package/dist/programs/kill-tree.d.ts +16 -0
- package/dist/programs/kill-tree.d.ts.map +1 -0
- package/dist/programs/kill-tree.js +28 -0
- package/dist/programs/kill-tree.js.map +1 -0
- package/dist/programs/media-duration.d.ts +10 -0
- package/dist/programs/media-duration.d.ts.map +1 -0
- package/dist/programs/media-duration.js +10 -0
- package/dist/programs/media-duration.js.map +1 -0
- package/dist/programs/piped-program.d.ts +7 -0
- package/dist/programs/piped-program.d.ts.map +1 -0
- package/dist/programs/piped-program.js +45 -0
- package/dist/programs/piped-program.js.map +1 -0
- package/dist/programs/programs.d.ts +6 -0
- package/dist/programs/programs.d.ts.map +1 -0
- package/dist/programs/programs.js +6 -0
- package/dist/programs/programs.js.map +1 -0
- package/dist/programs/run-program.d.ts +22 -0
- package/dist/programs/run-program.d.ts.map +1 -0
- package/dist/programs/run-program.js +46 -0
- package/dist/programs/run-program.js.map +1 -0
- package/dist/record/address.d.ts +5 -0
- package/dist/record/address.d.ts.map +1 -0
- package/dist/record/address.js +28 -0
- package/dist/record/address.js.map +1 -0
- package/dist/record/cursor-script.d.ts +2 -0
- package/dist/record/cursor-script.d.ts.map +1 -0
- package/dist/record/cursor-script.js +21 -0
- package/dist/record/cursor-script.js.map +1 -0
- package/dist/record/encoder-args.d.ts +3 -0
- package/dist/record/encoder-args.d.ts.map +1 -0
- package/dist/record/encoder-args.js +13 -0
- package/dist/record/encoder-args.js.map +1 -0
- package/dist/record/frame-writer.d.ts +8 -0
- package/dist/record/frame-writer.d.ts.map +1 -0
- package/dist/record/frame-writer.js +30 -0
- package/dist/record/frame-writer.js.map +1 -0
- package/dist/record/own-port.d.ts +2 -0
- package/dist/record/own-port.d.ts.map +1 -0
- package/dist/record/own-port.js +23 -0
- package/dist/record/own-port.js.map +1 -0
- package/dist/record/pointer.d.ts +9 -0
- package/dist/record/pointer.d.ts.map +1 -0
- package/dist/record/pointer.js +23 -0
- package/dist/record/pointer.js.map +1 -0
- package/dist/record/recorder.d.ts +24 -0
- package/dist/record/recorder.d.ts.map +1 -0
- package/dist/record/recorder.js +69 -0
- package/dist/record/recorder.js.map +1 -0
- package/dist/record/register-record.d.ts +3 -0
- package/dist/record/register-record.d.ts.map +1 -0
- package/dist/record/register-record.js +49 -0
- package/dist/record/register-record.js.map +1 -0
- package/dist/record/run-step.d.ts +7 -0
- package/dist/record/run-step.d.ts.map +1 -0
- package/dist/record/run-step.js +49 -0
- package/dist/record/run-step.js.map +1 -0
- package/dist/record/screencast.d.ts +9 -0
- package/dist/record/screencast.d.ts.map +1 -0
- package/dist/record/screencast.js +38 -0
- package/dist/record/screencast.js.map +1 -0
- package/dist/record/steps.d.ts +71 -0
- package/dist/record/steps.d.ts.map +1 -0
- package/dist/record/steps.js +29 -0
- package/dist/record/steps.js.map +1 -0
- package/dist/register-with-kvcoder.d.ts +3 -0
- package/dist/register-with-kvcoder.d.ts.map +1 -0
- package/dist/register-with-kvcoder.js +15 -0
- package/dist/register-with-kvcoder.js.map +1 -0
- package/dist/settings.d.ts +29 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +27 -0
- package/dist/settings.js.map +1 -0
- package/dist/setup/browser-readiness.d.ts +14 -0
- package/dist/setup/browser-readiness.d.ts.map +1 -0
- package/dist/setup/browser-readiness.js +16 -0
- package/dist/setup/browser-readiness.js.map +1 -0
- package/dist/setup/ffmpeg-readiness.d.ts +19 -0
- package/dist/setup/ffmpeg-readiness.d.ts.map +1 -0
- package/dist/setup/ffmpeg-readiness.js +33 -0
- package/dist/setup/ffmpeg-readiness.js.map +1 -0
- package/dist/setup/narration-readiness.d.ts +21 -0
- package/dist/setup/narration-readiness.d.ts.map +1 -0
- package/dist/setup/narration-readiness.js +18 -0
- package/dist/setup/narration-readiness.js.map +1 -0
- package/dist/setup/register-setup.d.ts +3 -0
- package/dist/setup/register-setup.d.ts.map +1 -0
- package/dist/setup/register-setup.js +51 -0
- package/dist/setup/register-setup.js.map +1 -0
- package/dist/ui.d.ts +3 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +25 -0
- package/dist/ui.js.map +1 -0
- package/dist/video-start.d.ts +3 -0
- package/dist/video-start.d.ts.map +1 -0
- package/dist/video-start.js +28 -0
- package/dist/video-start.js.map +1 -0
- package/dist/web/components/player.css +2 -0
- package/dist/web/components/player.js +43 -0
- package/docs/guide.md +16 -0
- package/fonts/Amiri-Bold.ttf +0 -0
- package/fonts/IBMPlexSansArabic-Bold.ttf +0 -0
- package/fonts/Lato-Bold.ttf +0 -0
- package/fonts/OFL-Amiri.txt +94 -0
- package/fonts/OFL-IBMPlexSansArabic.txt +93 -0
- package/fonts/OFL-Lato.txt +93 -0
- package/fonts/OFL-Poppins.txt +93 -0
- package/fonts/Poppins-Bold.ttf +0 -0
- package/locales/ar.json +37 -0
- package/locales/en.json +37 -0
- package/package.json +67 -3
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PlannedScene } from './scene-plan.ts';
|
|
2
|
+
export type Size = {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
};
|
|
6
|
+
/** The ASS file of a scene with captions, relative to the work folder. */
|
|
7
|
+
export declare function assName(scene: PlannedScene): string;
|
|
8
|
+
export declare function sceneArgs(scene: PlannedScene, size: Size, output: string): string[];
|
|
9
|
+
/** The concat demuxer's list of the parts, in order. */
|
|
10
|
+
export declare function joinList(parts: readonly string[]): string;
|
|
11
|
+
export declare function joinArgs(list: string, output: string): string[];
|
|
12
|
+
//# sourceMappingURL=scene-args.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-args.d.ts","sourceRoot":"","sources":["../../src/compose/scene-args.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAMpD,MAAM,MAAM,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAgBrD,0EAA0E;AAC1E,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAEnD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBnF;AAED,wDAAwD;AACxD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEzD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/D"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { framesPerSecond } from "../record/frame-writer.js";
|
|
2
|
+
const seconds = (ms) => (ms / 1000).toFixed(3);
|
|
3
|
+
const quiet = ['-hide_banner', '-loglevel', 'error'];
|
|
4
|
+
function clipInput(scene) {
|
|
5
|
+
if (scene.kind === 'image')
|
|
6
|
+
return ['-loop', '1', '-framerate', String(framesPerSecond), '-t', seconds(scene.lengthMs), '-i', scene.clip];
|
|
7
|
+
return ['-ss', seconds(scene.startMs), '-t', seconds(scene.partMs), '-i', scene.clip];
|
|
8
|
+
}
|
|
9
|
+
function soundInput(scene) {
|
|
10
|
+
if (scene.narration !== undefined)
|
|
11
|
+
return ['-i', scene.narration];
|
|
12
|
+
return ['-f', 'lavfi', '-t', seconds(scene.lengthMs), '-i', 'anullsrc=channel_layout=stereo:sample_rate=48000'];
|
|
13
|
+
}
|
|
14
|
+
/** The ASS file of a scene with captions, relative to the work folder. */
|
|
15
|
+
export function assName(scene) {
|
|
16
|
+
return `scene-${String(scene.number)}.ass`;
|
|
17
|
+
}
|
|
18
|
+
export function sceneArgs(scene, size, output) {
|
|
19
|
+
const { width, height } = size;
|
|
20
|
+
const fit = `scale=${String(width)}:${String(height)}:force_original_aspect_ratio=decrease,pad=${String(width)}:${String(height)}:(ow-iw)/2:(oh-ih)/2:color=black`;
|
|
21
|
+
const hold = `tpad=stop_mode=clone:stop_duration=${seconds(scene.lengthMs)}`;
|
|
22
|
+
const captions = scene.captions.length === 0 ? '' : `,subtitles=filename=${assName(scene)}:fontsdir=fonts`;
|
|
23
|
+
const graph = `[0:v]${fit},fps=${String(framesPerSecond)},format=yuv420p,${hold}${captions}[v];[1:a]aresample=48000,apad[a]`;
|
|
24
|
+
return [
|
|
25
|
+
...quiet,
|
|
26
|
+
...clipInput(scene),
|
|
27
|
+
...soundInput(scene),
|
|
28
|
+
'-filter_complex', graph,
|
|
29
|
+
'-map', '[v]', '-map', '[a]',
|
|
30
|
+
'-c:v', 'libx264', '-preset', 'medium', '-crf', '20', '-pix_fmt', 'yuv420p', '-r', String(framesPerSecond),
|
|
31
|
+
'-c:a', 'aac', '-b:a', '160k', '-ar', '48000', '-ac', '2',
|
|
32
|
+
'-t', seconds(scene.lengthMs), '-y', output,
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
/** The concat demuxer's list of the parts, in order. */
|
|
36
|
+
export function joinList(parts) {
|
|
37
|
+
return parts.map((part) => `file '${part.replace(/'/g, "'\\''")}'\n`).join('');
|
|
38
|
+
}
|
|
39
|
+
export function joinArgs(list, output) {
|
|
40
|
+
return [...quiet, '-f', 'concat', '-safe', '0', '-i', list, '-c', 'copy', '-movflags', '+faststart', '-y', output];
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=scene-args.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-args.js","sourceRoot":"","sources":["../../src/compose/scene-args.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Caption } from '../narration/captions.ts';
|
|
2
|
+
import type { Scene } from './compose-input.ts';
|
|
3
|
+
export declare const videoExtensions: string[];
|
|
4
|
+
export declare const imageExtensions: string[];
|
|
5
|
+
export declare const audioExtensions: string[];
|
|
6
|
+
export type PlannedScene = {
|
|
7
|
+
number: number;
|
|
8
|
+
kind: 'video' | 'image';
|
|
9
|
+
clip: string;
|
|
10
|
+
startMs: number;
|
|
11
|
+
partMs: number;
|
|
12
|
+
lengthMs: number;
|
|
13
|
+
narration: string | undefined;
|
|
14
|
+
captions: Caption[];
|
|
15
|
+
};
|
|
16
|
+
export type SceneFiles = {
|
|
17
|
+
clip: string;
|
|
18
|
+
narration: string | undefined;
|
|
19
|
+
};
|
|
20
|
+
export type SceneDurations = {
|
|
21
|
+
clipMs: number | undefined;
|
|
22
|
+
narrationMs: number | undefined;
|
|
23
|
+
};
|
|
24
|
+
export declare function isImage(file: string): boolean;
|
|
25
|
+
/** Checks what a scene needs before any file is read: an image has no part and has a length. */
|
|
26
|
+
export declare function checkScene(number: number, scene: Scene): void;
|
|
27
|
+
export declare function planScene(number: number, scene: Scene, files: SceneFiles, durations: SceneDurations): PlannedScene;
|
|
28
|
+
//# sourceMappingURL=scene-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-plan.d.ts","sourceRoot":"","sources":["../../src/compose/scene-plan.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAKhD,eAAO,MAAM,eAAe,UAAoC,CAAC;AACjE,eAAO,MAAM,eAAe,UAAqC,CAAC;AAClE,eAAO,MAAM,eAAe,UAA2B,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC;AAE5L,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAEzE,MAAM,MAAM,cAAc,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE7F,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAI7D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,GAAG,YAAY,CASlH"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { invalid } from "../problems.js";
|
|
3
|
+
// A scene's length (plan 16 §16.7): its `durationMs`, else its narration's, else its video part's. A video part
|
|
4
|
+
// shorter than the scene holds its last frame, and a longer one is cut.
|
|
5
|
+
export const videoExtensions = ['.webm', '.mp4', '.mov', '.mkv'];
|
|
6
|
+
export const imageExtensions = ['.png', '.jpg', '.jpeg', '.webp'];
|
|
7
|
+
export const audioExtensions = ['.mp3', '.wav', '.m4a'];
|
|
8
|
+
export function isImage(file) {
|
|
9
|
+
return imageExtensions.includes(path.extname(file).toLowerCase());
|
|
10
|
+
}
|
|
11
|
+
/** Checks what a scene needs before any file is read: an image has no part and has a length. */
|
|
12
|
+
export function checkScene(number, scene) {
|
|
13
|
+
if (!isImage(scene.clip))
|
|
14
|
+
return;
|
|
15
|
+
if (scene.from !== undefined || scene.to !== undefined)
|
|
16
|
+
throw invalid(`Scene ${String(number)} is an image, which has no from or to.`, { scene: number });
|
|
17
|
+
if (scene.durationMs === undefined && scene.narration === undefined)
|
|
18
|
+
throw invalid(`Scene ${String(number)} is an image without a narration or durationMs, so it has no length.`, { scene: number });
|
|
19
|
+
}
|
|
20
|
+
export function planScene(number, scene, files, durations) {
|
|
21
|
+
checkScene(number, scene);
|
|
22
|
+
const base = { number, clip: files.clip, narration: files.narration, captions: scene.captions ?? [] };
|
|
23
|
+
if (isImage(files.clip))
|
|
24
|
+
return { ...base, kind: 'image', startMs: 0, partMs: 0, lengthMs: scene.durationMs ?? durations.narrationMs ?? 0 };
|
|
25
|
+
const clipMs = durations.clipMs ?? 0;
|
|
26
|
+
const startMs = scene.from ?? 0;
|
|
27
|
+
if (startMs >= clipMs)
|
|
28
|
+
throw invalid(`Scene ${String(number)} starts at ${String(startMs)} ms, past its clip's end.`, { scene: number });
|
|
29
|
+
const partMs = Math.min(scene.to ?? clipMs, clipMs) - startMs;
|
|
30
|
+
return { ...base, kind: 'video', startMs, partMs, lengthMs: scene.durationMs ?? durations.narrationMs ?? partMs };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=scene-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene-plan.js","sourceRoot":"","sources":["../../src/compose/scene-plan.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAIzC,gHAAgH;AAChH,wEAAwE;AAExE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAQxD,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,gGAAgG;AAChG,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,KAAY;IACrD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO;IACjC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS;QAAE,MAAM,OAAO,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,wCAAwC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1J,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;QAAE,MAAM,OAAO,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,sEAAsE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AACvM,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,KAAY,EAAE,KAAiB,EAAE,SAAyB;IAClG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;IACtG,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS,CAAC,WAAW,IAAI,CAAC,EAAE,CAAC;IAC5I,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;IAChC,IAAI,OAAO,IAAI,MAAM;QAAE,MAAM,OAAO,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACzI,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC;IAC9D,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS,CAAC,WAAW,IAAI,MAAM,EAAE,CAAC;AACpH,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export declare const connectorName = "video";
|
|
2
|
+
export declare const videoConnector: {
|
|
3
|
+
name: string;
|
|
4
|
+
optIn: true;
|
|
5
|
+
description: string;
|
|
6
|
+
commands: ({
|
|
7
|
+
name: string;
|
|
8
|
+
command: string;
|
|
9
|
+
examples: {
|
|
10
|
+
description: string;
|
|
11
|
+
input: {};
|
|
12
|
+
}[];
|
|
13
|
+
card?: never;
|
|
14
|
+
} | {
|
|
15
|
+
name: string;
|
|
16
|
+
command: string;
|
|
17
|
+
examples: {
|
|
18
|
+
description: string;
|
|
19
|
+
input: {
|
|
20
|
+
url: string;
|
|
21
|
+
file: string;
|
|
22
|
+
steps: ({
|
|
23
|
+
do: string;
|
|
24
|
+
target: string;
|
|
25
|
+
text: string;
|
|
26
|
+
ms?: never;
|
|
27
|
+
} | {
|
|
28
|
+
do: string;
|
|
29
|
+
target: string;
|
|
30
|
+
text?: never;
|
|
31
|
+
ms?: never;
|
|
32
|
+
} | {
|
|
33
|
+
do: string;
|
|
34
|
+
ms: number;
|
|
35
|
+
target?: never;
|
|
36
|
+
text?: never;
|
|
37
|
+
})[];
|
|
38
|
+
};
|
|
39
|
+
}[];
|
|
40
|
+
card?: never;
|
|
41
|
+
} | {
|
|
42
|
+
name: string;
|
|
43
|
+
command: string;
|
|
44
|
+
examples: {
|
|
45
|
+
description: string;
|
|
46
|
+
input: {
|
|
47
|
+
text: string;
|
|
48
|
+
file: string;
|
|
49
|
+
};
|
|
50
|
+
}[];
|
|
51
|
+
card?: never;
|
|
52
|
+
} | {
|
|
53
|
+
name: string;
|
|
54
|
+
command: string;
|
|
55
|
+
card: string;
|
|
56
|
+
examples: {
|
|
57
|
+
description: string;
|
|
58
|
+
input: {
|
|
59
|
+
file: string;
|
|
60
|
+
scenes: ({
|
|
61
|
+
clip: string;
|
|
62
|
+
durationMs: number;
|
|
63
|
+
narration?: never;
|
|
64
|
+
captions?: never;
|
|
65
|
+
} | {
|
|
66
|
+
clip: string;
|
|
67
|
+
narration: string;
|
|
68
|
+
captions: {
|
|
69
|
+
text: string;
|
|
70
|
+
startMs: number;
|
|
71
|
+
endMs: number;
|
|
72
|
+
}[];
|
|
73
|
+
durationMs?: never;
|
|
74
|
+
})[];
|
|
75
|
+
};
|
|
76
|
+
}[];
|
|
77
|
+
})[];
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=connector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,UAAU,CAAC;AAErC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwC1B,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// The `video` connector (plan 16 §16.1 and §16.3; ADR 0107, 11): `optIn`, so a chat has it only after `/video`.
|
|
2
|
+
export const connectorName = 'video';
|
|
3
|
+
export const videoConnector = {
|
|
4
|
+
name: connectorName,
|
|
5
|
+
optIn: true,
|
|
6
|
+
description: 'Make videos: record pages of an app running on this computer, narrate a script, and join them with captions into an MP4. Use it when the person asks for a video, a tutorial, a demo, or a promotion.',
|
|
7
|
+
commands: [
|
|
8
|
+
{ name: 'check', command: 'kvvideo.setup.get', examples: [{ description: 'See what is ready before making a video', input: {} }] },
|
|
9
|
+
{ name: 'fonts', command: 'kvvideo.font.list', examples: [{ description: 'List the bundled caption fonts', input: {} }] },
|
|
10
|
+
{
|
|
11
|
+
name: 'record',
|
|
12
|
+
command: 'kvvideo.clip.record',
|
|
13
|
+
examples: [
|
|
14
|
+
{
|
|
15
|
+
description: 'Record signing in to the app on its dev server',
|
|
16
|
+
input: { url: 'http://localhost:5173/', file: 'videos/tour/01-sign-in.mp4', steps: [{ do: 'type', target: 'role=textbox[name="Email"]', text: 'sam@example.com' }, { do: 'click', target: 'role=button[name="Sign in"]' }, { do: 'wait', ms: 1500 }] },
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'narrate',
|
|
22
|
+
command: 'kvvideo.narration.make',
|
|
23
|
+
examples: [{ description: "Narrate the first scene's script", input: { text: 'This is Notes. Sign in with your email to see your notes.', file: 'videos/tour/01-sign-in.mp3' } }],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'compose',
|
|
27
|
+
command: 'kvvideo.video.compose',
|
|
28
|
+
card: 'kvvideo.player',
|
|
29
|
+
examples: [
|
|
30
|
+
{
|
|
31
|
+
description: 'Join a title image and a narrated recording, with captions',
|
|
32
|
+
input: {
|
|
33
|
+
file: 'videos/tour.mp4',
|
|
34
|
+
scenes: [
|
|
35
|
+
{ clip: 'videos/tour/00-title.png', durationMs: 2000 },
|
|
36
|
+
{ clip: 'videos/tour/01-sign-in.mp4', narration: 'videos/tour/01-sign-in.mp3', captions: [{ text: 'This is Notes.', startMs: 0, endMs: 1200 }] },
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=connector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector.js","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAAA,gHAAgH;AAEhH,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AAErC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,IAAa;IACpB,WAAW,EAAE,uMAAuM;IACpN,QAAQ,EAAE;QACR,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,yCAAyC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE;QAClI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,gCAAgC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE;QACzH;YACE,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,qBAAqB;YAC9B,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,gDAAgD;oBAC7D,KAAK,EAAE,EAAE,GAAG,EAAE,wBAAwB,EAAE,IAAI,EAAE,4BAA4B,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,4BAA4B,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,6BAA6B,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;iBACvP;aACF;SACF;QACD;YACE,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,wBAAwB;YACjC,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,kCAAkC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,2DAA2D,EAAE,IAAI,EAAE,4BAA4B,EAAE,EAAE,CAAC;SAClL;QACD;YACE,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,uBAAuB;YAChC,IAAI,EAAE,gBAAgB;YACtB,QAAQ,EAAE;gBACR;oBACE,WAAW,EAAE,4DAA4D;oBACzE,KAAK,EAAE;wBACL,IAAI,EAAE,iBAAiB;wBACvB,MAAM,EAAE;4BACN,EAAE,IAAI,EAAE,0BAA0B,EAAE,UAAU,EAAE,IAAI,EAAE;4BACtD,EAAE,IAAI,EAAE,4BAA4B,EAAE,SAAS,EAAE,4BAA4B,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE;yBACjJ;qBACF;iBACF;aACF;SACF;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answer-path.d.ts","sourceRoot":"","sources":["../../src/files/answer-path.ts"],"names":[],"mappings":"AAEA,+FAA+F;AAC/F,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEjE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
/** A workspace file as an answer names it: relative to the workspace, with `/` on every OS. */
|
|
3
|
+
export function answerPath(root, absolute) {
|
|
4
|
+
return path.relative(root, absolute).split(path.sep).join('/');
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=answer-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"answer-path.js","sourceRoot":"","sources":["../../src/files/answer-path.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,+FAA+F;AAC/F,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,QAAgB;IACvD,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** A temporary folder for one call's work, deleted with `remove`. */
|
|
2
|
+
export declare function workFolder(): {
|
|
3
|
+
folder: string;
|
|
4
|
+
remove(): void;
|
|
5
|
+
};
|
|
6
|
+
/** Puts a finished file at its output path. */
|
|
7
|
+
export declare function placeOutput(made: string, output: string): void;
|
|
8
|
+
//# sourceMappingURL=place-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"place-output.d.ts","sourceRoot":"","sources":["../../src/files/place-output.ts"],"names":[],"mappings":"AASA,qEAAqE;AACrE,wBAAgB,UAAU,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,IAAI,IAAI,CAAA;CAAE,CAG/D;AAED,+CAA+C;AAC/C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAQ9D"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { copyFileSync, mkdtempSync, renameSync, rmSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
// Outputs are made in a temporary folder and placed beside their path under a temporary name, then renamed over it,
|
|
6
|
+
// so a failed call leaves no file and the old one in place (plan 16 §16.3). The temporary folder may be on another
|
|
7
|
+
// disk, so the file is copied beside its path first.
|
|
8
|
+
/** A temporary folder for one call's work, deleted with `remove`. */
|
|
9
|
+
export function workFolder() {
|
|
10
|
+
const folder = mkdtempSync(path.join(tmpdir(), 'kvvideo-'));
|
|
11
|
+
return { folder, remove: () => rmSync(folder, { recursive: true, force: true }) };
|
|
12
|
+
}
|
|
13
|
+
/** Puts a finished file at its output path. */
|
|
14
|
+
export function placeOutput(made, output) {
|
|
15
|
+
const beside = path.join(path.dirname(output), `.${path.basename(output)}.${randomUUID()}.tmp`);
|
|
16
|
+
try {
|
|
17
|
+
copyFileSync(made, beside);
|
|
18
|
+
renameSync(beside, output);
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
rmSync(beside, { force: true });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=place-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"place-output.js","sourceRoot":"","sources":["../../src/files/place-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,oHAAoH;AACpH,mHAAmH;AACnH,qDAAqD;AAErD,qEAAqE;AACrE,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACpF,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAc;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,UAAU,EAAE,MAAM,CAAC,CAAC;IAChG,IAAI,CAAC;QACH,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3B,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAClC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** A path of the workspace, made absolute; one that leaves it fails `VALIDATION_FAILED`. */
|
|
2
|
+
export declare function workspacePath(root: string, file: string): string;
|
|
3
|
+
/** An existing input file of one of the extensions. */
|
|
4
|
+
export declare function inputPath(root: string, file: string, extensions: readonly string[]): string;
|
|
5
|
+
/** An output file with the extension, its folders made; an existing one only with `replace`. */
|
|
6
|
+
export declare function outputPath(root: string, file: string, extension: string, replace: boolean): string;
|
|
7
|
+
//# sourceMappingURL=workspace-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-paths.d.ts","sourceRoot":"","sources":["../../src/files/workspace-paths.ts"],"names":[],"mappings":"AAmBA,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhE;AAMD,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAK3F;AAED,gGAAgG;AAChG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAMlG"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, realpathSync, statSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { invalid, notFound } from "../problems.js";
|
|
4
|
+
// Where kvvideo reads and writes (plan 16 §16.3): every path is inside the workspace folder, through `..` and symlinks
|
|
5
|
+
// alike. An input must exist; an output has its command's extension and is replaced only when asked.
|
|
6
|
+
function inside(root, candidate) {
|
|
7
|
+
const relative = path.relative(root, candidate);
|
|
8
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
9
|
+
}
|
|
10
|
+
// The real path of the nearest part of `absolute` that exists, so a symlink anywhere along it is followed.
|
|
11
|
+
function realOfNearest(absolute) {
|
|
12
|
+
let existing = absolute;
|
|
13
|
+
while (!existsSync(existing))
|
|
14
|
+
existing = path.dirname(existing);
|
|
15
|
+
return path.join(realpathSync(existing), path.relative(existing, absolute));
|
|
16
|
+
}
|
|
17
|
+
/** A path of the workspace, made absolute; one that leaves it fails `VALIDATION_FAILED`. */
|
|
18
|
+
export function workspacePath(root, file) {
|
|
19
|
+
if (file.trim() === '')
|
|
20
|
+
throw invalid('The path is empty.', { path: file });
|
|
21
|
+
const absolute = path.resolve(root, file);
|
|
22
|
+
if (!inside(root, absolute) || !inside(realpathSync(root), realOfNearest(absolute)))
|
|
23
|
+
throw invalid(`${file} is outside the workspace folder.`, { path: file });
|
|
24
|
+
return absolute;
|
|
25
|
+
}
|
|
26
|
+
function hasExtension(file, extensions) {
|
|
27
|
+
return extensions.includes(path.extname(file).toLowerCase());
|
|
28
|
+
}
|
|
29
|
+
/** An existing input file of one of the extensions. */
|
|
30
|
+
export function inputPath(root, file, extensions) {
|
|
31
|
+
const absolute = workspacePath(root, file);
|
|
32
|
+
if (!hasExtension(file, extensions))
|
|
33
|
+
throw invalid(`${file} isn't one of ${extensions.join(', ')}.`, { path: file, extensions: [...extensions] });
|
|
34
|
+
if (!existsSync(absolute) || !statSync(absolute).isFile())
|
|
35
|
+
throw notFound(`${file} doesn't exist.`, { path: file });
|
|
36
|
+
return absolute;
|
|
37
|
+
}
|
|
38
|
+
/** An output file with the extension, its folders made; an existing one only with `replace`. */
|
|
39
|
+
export function outputPath(root, file, extension, replace) {
|
|
40
|
+
const absolute = workspacePath(root, file);
|
|
41
|
+
if (!hasExtension(file, [extension]))
|
|
42
|
+
throw invalid(`${file} must end with ${extension}.`, { path: file, extension });
|
|
43
|
+
if (existsSync(absolute) && !replace)
|
|
44
|
+
throw invalid(`${file} exists; set replace to true to write over it.`, { path: file });
|
|
45
|
+
mkdirSync(path.dirname(absolute), { recursive: true });
|
|
46
|
+
return absolute;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=workspace-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-paths.js","sourceRoot":"","sources":["../../src/files/workspace-paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type FontScript = 'latin' | 'arabic';
|
|
2
|
+
export type BundledFont = {
|
|
3
|
+
name: string;
|
|
4
|
+
file: string;
|
|
5
|
+
scripts: FontScript[];
|
|
6
|
+
};
|
|
7
|
+
export declare const bundledFonts: readonly BundledFont[];
|
|
8
|
+
/** The folder that holds the bundled fonts, from the source and the build alike. */
|
|
9
|
+
export declare const fontsFolder: string;
|
|
10
|
+
//# sourceMappingURL=bundled-fonts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundled-fonts.d.ts","sourceRoot":"","sources":["../../src/fonts/bundled-fonts.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC;AAEhF,eAAO,MAAM,YAAY,EAAE,SAAS,WAAW,EAK9C,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,WAAW,QAA0D,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
export const bundledFonts = [
|
|
3
|
+
{ name: 'Amiri', file: 'Amiri-Bold.ttf', scripts: ['arabic', 'latin'] },
|
|
4
|
+
{ name: 'IBM Plex Sans Arabic', file: 'IBMPlexSansArabic-Bold.ttf', scripts: ['arabic', 'latin'] },
|
|
5
|
+
{ name: 'Lato', file: 'Lato-Bold.ttf', scripts: ['latin'] },
|
|
6
|
+
{ name: 'Poppins', file: 'Poppins-Bold.ttf', scripts: ['latin'] },
|
|
7
|
+
];
|
|
8
|
+
/** The folder that holds the bundled fonts, from the source and the build alike. */
|
|
9
|
+
export const fontsFolder = fileURLToPath(new URL('../../fonts/', import.meta.url));
|
|
10
|
+
//# sourceMappingURL=bundled-fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundled-fonts.js","sourceRoot":"","sources":["../../src/fonts/bundled-fonts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAQzC,MAAM,CAAC,MAAM,YAAY,GAA2B;IAClD,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE;IACvE,EAAE,IAAI,EAAE,sBAAsB,EAAE,IAAI,EAAE,4BAA4B,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE;IAClG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;IAC3D,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;CAClE,CAAC;AAEF,oFAAoF;AACpF,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-family.d.ts","sourceRoot":"","sources":["../../src/fonts/font-family.ts"],"names":[],"mappings":"AAoCA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAS7D"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { invalid } from "../problems.js";
|
|
2
|
+
function nameTableOffset(font) {
|
|
3
|
+
if (font.length < 12)
|
|
4
|
+
return undefined;
|
|
5
|
+
const version = font.readUInt32BE(0);
|
|
6
|
+
if (version !== 0x00010000 && version !== 0x4f54544f && version !== 0x74727565)
|
|
7
|
+
return undefined;
|
|
8
|
+
const tables = font.readUInt16BE(4);
|
|
9
|
+
for (let index = 0; index < tables; index += 1) {
|
|
10
|
+
const at = 12 + index * 16;
|
|
11
|
+
if (at + 16 > font.length)
|
|
12
|
+
return undefined;
|
|
13
|
+
if (font.toString('latin1', at, at + 4) === 'name')
|
|
14
|
+
return font.readUInt32BE(at + 8);
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
function recordsOf(font, table) {
|
|
19
|
+
const count = font.readUInt16BE(table + 2);
|
|
20
|
+
const strings = table + font.readUInt16BE(table + 4);
|
|
21
|
+
const records = Array.from({ length: count }, (_, index) => {
|
|
22
|
+
const at = table + 6 + index * 12;
|
|
23
|
+
return { platform: font.readUInt16BE(at), encoding: font.readUInt16BE(at + 2), language: font.readUInt16BE(at + 4), nameId: font.readUInt16BE(at + 6), length: font.readUInt16BE(at + 8), offset: font.readUInt16BE(at + 10) };
|
|
24
|
+
});
|
|
25
|
+
return { records, strings };
|
|
26
|
+
}
|
|
27
|
+
function decode(font, strings, record) {
|
|
28
|
+
const bytes = font.subarray(strings + record.offset, strings + record.offset + record.length);
|
|
29
|
+
return record.platform === 3 ? Buffer.from(bytes).swap16().toString('utf16le') : bytes.toString('latin1');
|
|
30
|
+
}
|
|
31
|
+
export function fontFamily(font, file) {
|
|
32
|
+
const table = nameTableOffset(font);
|
|
33
|
+
if (table === undefined || table + 6 > font.length)
|
|
34
|
+
throw invalid(`${file} isn't a TrueType or OpenType font.`, { path: file });
|
|
35
|
+
const { records, strings } = recordsOf(font, table);
|
|
36
|
+
const families = records.filter((record) => record.nameId === 1);
|
|
37
|
+
const windows = families.filter((record) => record.platform === 3 && (record.encoding === 1 || record.encoding === 10));
|
|
38
|
+
const chosen = windows.find((record) => record.language === 0x409) ?? windows[0] ?? families.find((record) => record.platform === 1 && record.encoding === 0);
|
|
39
|
+
if (chosen === undefined || strings + chosen.offset + chosen.length > font.length)
|
|
40
|
+
throw invalid(`${file} has no family name.`, { path: file });
|
|
41
|
+
return decode(font, strings, chosen);
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=font-family.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"font-family.js","sourceRoot":"","sources":["../../src/fonts/font-family.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-fonts.d.ts","sourceRoot":"","sources":["../../src/fonts/register-fonts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AAGzC,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAQ5C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from '@kvman/sdk';
|
|
2
|
+
import { bundledFonts } from "./bundled-fonts.js";
|
|
3
|
+
export function registerFonts(ctx) {
|
|
4
|
+
ctx.registerQuery('kvvideo.font.list', {
|
|
5
|
+
description: 'Lists the fonts bundled for captions, with the scripts each one writes.',
|
|
6
|
+
input: z.object({}),
|
|
7
|
+
output: z.array(z.object({ name: z.string(), scripts: z.array(z.enum(['latin', 'arabic'])) })),
|
|
8
|
+
public: true,
|
|
9
|
+
handle: () => bundledFonts.map(({ name, scripts }) => ({ name, scripts })),
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=register-fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-fonts.js","sourceRoot":"","sources":["../../src/fonts/register-fonts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAY,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,GAAG,CAAC,aAAa,CAAC,mBAAmB,EAAE;QACrC,WAAW,EAAE,yEAAyE;QACtF,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACnB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC9F,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;KAC3E,CAAC,CAAC;AACL,CAAC"}
|
package/dist/guide.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guide.d.ts","sourceRoot":"","sources":["../src/guide.ts"],"names":[],"mappings":"AAEA,wFAAwF;AACxF,wBAAgB,SAAS,IAAI,MAAM,CAElC"}
|
package/dist/guide.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
/** The guide `/video` puts in a chat's prompt (plan 16 §16.1), from `docs/guide.md`. */
|
|
3
|
+
export function readGuide() {
|
|
4
|
+
return readFileSync(new URL('../docs/guide.md', import.meta.url), 'utf8');
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=guide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guide.js","sourceRoot":"","sources":["../src/guide.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,wFAAwF;AACxF,MAAM,UAAU,SAAS;IACvB,OAAO,YAAY,CAAC,IAAI,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AAC5E,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAWtC,YAAY,EAAE,MAAM,UAAU,CAAC;yBAKf,KAAK,GAAG,KAAG,IAAI;AAA/B,wBAUE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { registerCompose } from "./compose/register-compose.js";
|
|
2
|
+
import { registerFonts } from "./fonts/register-fonts.js";
|
|
3
|
+
import { registerNarration } from "./narration/register-narration.js";
|
|
4
|
+
import { registerRecord } from "./record/register-record.js";
|
|
5
|
+
import { registerWithKvcoder } from "./register-with-kvcoder.js";
|
|
6
|
+
import { registerSettings } from "./settings.js";
|
|
7
|
+
import { registerSetup } from "./setup/register-setup.js";
|
|
8
|
+
import { registerUi } from "./ui.js";
|
|
9
|
+
import { registerVideoStart } from "./video-start.js";
|
|
10
|
+
// kvvideo (plan 16): makes videos of the person's app, recorded in the installed browser, narrated, and captioned. It
|
|
11
|
+
// has no loop of its own; it extends kvcoder with the `video` connector and its guide, which a chat has once the
|
|
12
|
+
// person runs `/video` in it (ADR 0107).
|
|
13
|
+
export default (ctx) => {
|
|
14
|
+
registerSettings(ctx);
|
|
15
|
+
registerUi(ctx);
|
|
16
|
+
registerSetup(ctx);
|
|
17
|
+
registerFonts(ctx);
|
|
18
|
+
registerRecord(ctx);
|
|
19
|
+
registerNarration(ctx);
|
|
20
|
+
registerCompose(ctx);
|
|
21
|
+
registerVideoStart(ctx);
|
|
22
|
+
registerWithKvcoder(ctx);
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAItD,sHAAsH;AACtH,iHAAiH;AACjH,yCAAyC;AACzC,eAAe,CAAC,GAAQ,EAAQ,EAAE;IAChC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtB,UAAU,CAAC,GAAG,CAAC,CAAC;IAChB,aAAa,CAAC,GAAG,CAAC,CAAC;IACnB,aAAa,CAAC,GAAG,CAAC,CAAC;IACnB,cAAc,CAAC,GAAG,CAAC,CAAC;IACpB,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACvB,eAAe,CAAC,GAAG,CAAC,CAAC;IACrB,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACxB,mBAAmB,CAAC,GAAG,CAAC,CAAC;AAC3B,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Caption = {
|
|
2
|
+
text: string;
|
|
3
|
+
startMs: number;
|
|
4
|
+
endMs: number;
|
|
5
|
+
};
|
|
6
|
+
/** The caption lines of a text, in order. */
|
|
7
|
+
export declare function captionLines(text: string): string[];
|
|
8
|
+
/** The text's captions over a narration of `durationMs`. */
|
|
9
|
+
export declare function timedCaptions(text: string, durationMs: number): Caption[];
|
|
10
|
+
//# sourceMappingURL=captions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captions.d.ts","sourceRoot":"","sources":["../../src/narration/captions.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AA0BvE,6CAA6C;AAC7C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAGnD;AAED,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,EAAE,CAUzE"}
|