@kvman/kvvideo 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/api.d.ts +31 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/brand/brand.d.ts +17 -0
- package/dist/brand/brand.d.ts.map +1 -0
- package/dist/brand/brand.js +44 -0
- package/dist/brand/brand.js.map +1 -0
- package/dist/browser/launch.d.ts +2 -0
- package/dist/browser/launch.d.ts.map +1 -1
- package/dist/browser/launch.js +7 -1
- package/dist/browser/launch.js.map +1 -1
- package/dist/compose/ass-file.d.ts +5 -0
- package/dist/compose/ass-file.d.ts.map +1 -1
- package/dist/compose/ass-file.js +32 -3
- package/dist/compose/ass-file.js.map +1 -1
- package/dist/compose/background.d.ts +23 -0
- package/dist/compose/background.d.ts.map +1 -0
- package/dist/compose/background.js +31 -0
- package/dist/compose/background.js.map +1 -0
- package/dist/compose/camera.d.ts +32 -0
- package/dist/compose/camera.d.ts.map +1 -0
- package/dist/compose/camera.js +98 -0
- package/dist/compose/camera.js.map +1 -0
- package/dist/compose/caption-font.d.ts +2 -0
- package/dist/compose/caption-font.d.ts.map +1 -1
- package/dist/compose/caption-font.js +2 -1
- package/dist/compose/caption-font.js.map +1 -1
- package/dist/compose/compose-drawing.d.ts +19 -0
- package/dist/compose/compose-drawing.d.ts.map +1 -0
- package/dist/compose/compose-drawing.js +38 -0
- package/dist/compose/compose-drawing.js.map +1 -0
- package/dist/compose/compose-input.d.ts +139 -0
- package/dist/compose/compose-input.d.ts.map +1 -1
- package/dist/compose/compose-input.js +48 -9
- package/dist/compose/compose-input.js.map +1 -1
- package/dist/compose/compose-plan.d.ts +36 -0
- package/dist/compose/compose-plan.d.ts.map +1 -0
- package/dist/compose/compose-plan.js +55 -0
- package/dist/compose/compose-plan.js.map +1 -0
- package/dist/compose/compose-size.d.ts +49 -0
- package/dist/compose/compose-size.d.ts.map +1 -0
- package/dist/compose/compose-size.js +67 -0
- package/dist/compose/compose-size.js.map +1 -0
- package/dist/compose/drawn-images.d.ts +19 -0
- package/dist/compose/drawn-images.d.ts.map +1 -0
- package/dist/compose/drawn-images.js +75 -0
- package/dist/compose/drawn-images.js.map +1 -0
- package/dist/compose/final-pass.d.ts +34 -0
- package/dist/compose/final-pass.d.ts.map +1 -0
- package/dist/compose/final-pass.js +106 -0
- package/dist/compose/final-pass.js.map +1 -0
- package/dist/compose/frame-layout.d.ts +30 -0
- package/dist/compose/frame-layout.d.ts.map +1 -0
- package/dist/compose/frame-layout.js +33 -0
- package/dist/compose/frame-layout.js.map +1 -0
- package/dist/compose/overlays.d.ts +20 -0
- package/dist/compose/overlays.d.ts.map +1 -0
- package/dist/compose/overlays.js +30 -0
- package/dist/compose/overlays.js.map +1 -0
- package/dist/compose/page-again.d.ts +26 -0
- package/dist/compose/page-again.d.ts.map +1 -0
- package/dist/compose/page-again.js +50 -0
- package/dist/compose/page-again.js.map +1 -0
- package/dist/compose/player-copies.d.ts +5 -1
- package/dist/compose/player-copies.d.ts.map +1 -1
- package/dist/compose/player-copies.js +19 -16
- package/dist/compose/player-copies.js.map +1 -1
- package/dist/compose/register-compose.d.ts.map +1 -1
- package/dist/compose/register-compose.js +104 -20
- package/dist/compose/register-compose.js.map +1 -1
- package/dist/compose/render.d.ts +13 -4
- package/dist/compose/render.d.ts.map +1 -1
- package/dist/compose/render.js +48 -22
- package/dist/compose/render.js.map +1 -1
- package/dist/compose/scene-args.d.ts +32 -7
- package/dist/compose/scene-args.d.ts.map +1 -1
- package/dist/compose/scene-args.js +77 -16
- package/dist/compose/scene-args.js.map +1 -1
- package/dist/compose/scene-look.d.ts +31 -0
- package/dist/compose/scene-look.d.ts.map +1 -0
- package/dist/compose/scene-look.js +46 -0
- package/dist/compose/scene-look.js.map +1 -0
- package/dist/compose/scene-plan.d.ts +0 -2
- package/dist/compose/scene-plan.d.ts.map +1 -1
- package/dist/compose/scene-plan.js +7 -5
- package/dist/compose/scene-plan.js.map +1 -1
- package/dist/compose/sound-effects.d.ts +23 -0
- package/dist/compose/sound-effects.d.ts.map +1 -0
- package/dist/compose/sound-effects.js +40 -0
- package/dist/compose/sound-effects.js.map +1 -0
- package/dist/compose/transitions.d.ts +16 -0
- package/dist/compose/transitions.d.ts.map +1 -0
- package/dist/compose/transitions.js +38 -0
- package/dist/compose/transitions.js.map +1 -0
- package/dist/connector.d.ts +79 -14
- package/dist/connector.d.ts.map +1 -1
- package/dist/connector.js +33 -8
- package/dist/connector.js.map +1 -1
- package/dist/files/sidecar.d.ts +209 -0
- package/dist/files/sidecar.d.ts.map +1 -0
- package/dist/files/sidecar.js +66 -0
- package/dist/files/sidecar.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/look/look-at.d.ts +15 -0
- package/dist/look/look-at.d.ts.map +1 -0
- package/dist/look/look-at.js +20 -0
- package/dist/look/look-at.js.map +1 -0
- package/dist/look/look-input.d.ts +22 -0
- package/dist/look/look-input.d.ts.map +1 -0
- package/dist/look/look-input.js +25 -0
- package/dist/look/look-input.js.map +1 -0
- package/dist/look/register-look.d.ts +3 -0
- package/dist/look/register-look.d.ts.map +1 -0
- package/dist/look/register-look.js +52 -0
- package/dist/look/register-look.js.map +1 -0
- package/dist/narration/alignment.d.ts +15 -0
- package/dist/narration/alignment.d.ts.map +1 -0
- package/dist/narration/alignment.js +21 -0
- package/dist/narration/alignment.js.map +1 -0
- package/dist/narration/captions.d.ts +22 -4
- package/dist/narration/captions.d.ts.map +1 -1
- package/dist/narration/captions.js +44 -16
- package/dist/narration/captions.js.map +1 -1
- package/dist/narration/join-args.d.ts +3 -0
- package/dist/narration/join-args.d.ts.map +1 -0
- package/dist/narration/join-args.js +19 -0
- package/dist/narration/join-args.js.map +1 -0
- package/dist/narration/narration-cache.d.ts +25 -0
- package/dist/narration/narration-cache.d.ts.map +1 -0
- package/dist/narration/narration-cache.js +36 -0
- package/dist/narration/narration-cache.js.map +1 -0
- package/dist/narration/piper.d.ts +2 -6
- package/dist/narration/piper.d.ts.map +1 -1
- package/dist/narration/piper.js +9 -15
- package/dist/narration/piper.js.map +1 -1
- package/dist/narration/pronunciations.d.ts +11 -0
- package/dist/narration/pronunciations.d.ts.map +1 -0
- package/dist/narration/pronunciations.js +40 -0
- package/dist/narration/pronunciations.js.map +1 -0
- package/dist/narration/register-narration.d.ts +8 -0
- package/dist/narration/register-narration.d.ts.map +1 -1
- package/dist/narration/register-narration.js +54 -26
- package/dist/narration/register-narration.js.map +1 -1
- package/dist/narration/register-voice.d.ts +27 -0
- package/dist/narration/register-voice.d.ts.map +1 -0
- package/dist/narration/register-voice.js +82 -0
- package/dist/narration/register-voice.js.map +1 -0
- package/dist/narration/sentence-speaker.d.ts +35 -0
- package/dist/narration/sentence-speaker.d.ts.map +1 -0
- package/dist/narration/sentence-speaker.js +44 -0
- package/dist/narration/sentence-speaker.js.map +1 -0
- package/dist/narration/speech-services.d.ts +23 -3
- package/dist/narration/speech-services.d.ts.map +1 -1
- package/dist/narration/speech-services.js +27 -10
- package/dist/narration/speech-services.js.map +1 -1
- package/dist/narration/voice-args.d.ts +3 -0
- package/dist/narration/voice-args.d.ts.map +1 -0
- package/dist/narration/voice-args.js +10 -0
- package/dist/narration/voice-args.js.map +1 -0
- package/dist/programs/media-duration.d.ts +12 -0
- package/dist/programs/media-duration.d.ts.map +1 -1
- package/dist/programs/media-duration.js +13 -0
- package/dist/programs/media-duration.js.map +1 -1
- package/dist/programs/run-program.d.ts +1 -0
- package/dist/programs/run-program.d.ts.map +1 -1
- package/dist/programs/run-program.js +1 -0
- package/dist/programs/run-program.js.map +1 -1
- package/dist/record/address.d.ts +1 -1
- package/dist/record/address.d.ts.map +1 -1
- package/dist/record/address.js +5 -7
- package/dist/record/address.js.map +1 -1
- package/dist/record/cursor-script.d.ts +2 -1
- package/dist/record/cursor-script.d.ts.map +1 -1
- package/dist/record/cursor-script.js +52 -14
- package/dist/record/cursor-script.js.map +1 -1
- package/dist/record/encoder-args.js +1 -1
- package/dist/record/motion.d.ts +19 -0
- package/dist/record/motion.d.ts.map +1 -0
- package/dist/record/motion.js +59 -0
- package/dist/record/motion.js.map +1 -0
- package/dist/record/narration-cues.d.ts +14 -0
- package/dist/record/narration-cues.d.ts.map +1 -0
- package/dist/record/narration-cues.js +12 -0
- package/dist/record/narration-cues.js.map +1 -0
- package/dist/record/page-clock.d.ts +7 -0
- package/dist/record/page-clock.d.ts.map +1 -0
- package/dist/record/page-clock.js +13 -0
- package/dist/record/page-clock.js.map +1 -0
- package/dist/record/page-ready.d.ts +4 -0
- package/dist/record/page-ready.d.ts.map +1 -0
- package/dist/record/page-ready.js +15 -0
- package/dist/record/page-ready.js.map +1 -0
- package/dist/record/page-route.d.ts +13 -0
- package/dist/record/page-route.d.ts.map +1 -0
- package/dist/record/page-route.js +64 -0
- package/dist/record/page-route.js.map +1 -0
- package/dist/record/pointer.d.ts +6 -7
- package/dist/record/pointer.d.ts.map +1 -1
- package/dist/record/pointer.js +11 -10
- package/dist/record/pointer.js.map +1 -1
- package/dist/record/record-source.d.ts +16 -0
- package/dist/record/record-source.d.ts.map +1 -0
- package/dist/record/record-source.js +11 -0
- package/dist/record/record-source.js.map +1 -0
- package/dist/record/recorder.d.ts +19 -7
- package/dist/record/recorder.d.ts.map +1 -1
- package/dist/record/recorder.js +52 -18
- package/dist/record/recorder.js.map +1 -1
- package/dist/record/register-record.d.ts.map +1 -1
- package/dist/record/register-record.js +45 -13
- package/dist/record/register-record.js.map +1 -1
- package/dist/record/run-step.d.ts +16 -3
- package/dist/record/run-step.d.ts.map +1 -1
- package/dist/record/run-step.js +43 -23
- package/dist/record/run-step.js.map +1 -1
- package/dist/record/screencast.js +1 -1
- package/dist/record/steps.d.ts +56 -1
- package/dist/record/steps.d.ts.map +1 -1
- package/dist/record/steps.js +36 -18
- package/dist/record/steps.js.map +1 -1
- package/dist/review/analysis.d.ts +19 -0
- package/dist/review/analysis.d.ts.map +1 -0
- package/dist/review/analysis.js +36 -0
- package/dist/review/analysis.js.map +1 -0
- package/dist/review/frames.d.ts +9 -0
- package/dist/review/frames.d.ts.map +1 -0
- package/dist/review/frames.js +28 -0
- package/dist/review/frames.js.map +1 -0
- package/dist/review/register-review.d.ts +24 -0
- package/dist/review/register-review.d.ts.map +1 -0
- package/dist/review/register-review.js +81 -0
- package/dist/review/register-review.js.map +1 -0
- package/dist/review/sheet-args.d.ts +11 -0
- package/dist/review/sheet-args.d.ts.map +1 -0
- package/dist/review/sheet-args.js +24 -0
- package/dist/review/sheet-args.js.map +1 -0
- package/dist/settings.d.ts +4 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +4 -2
- package/dist/settings.js.map +1 -1
- package/dist/setup/ffmpeg-readiness.js +1 -1
- package/dist/setup/ffmpeg-readiness.js.map +1 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +3 -2
- package/dist/ui.js.map +1 -1
- package/dist/web/components/player.css +1 -1
- package/dist/web/components/player.js +33 -21
- package/docs/guide.md +39 -10
- package/locales/ar.json +12 -1
- package/locales/en.json +12 -1
- package/package.json +11 -5
- package/sounds/SOURCES.md +13 -0
- package/sounds/click.wav +0 -0
- package/sounds/keys.wav +0 -0
- package/sounds/pop.wav +0 -0
- package/sounds/whoosh.wav +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @kvman/kvvideo
|
|
2
2
|
|
|
3
|
-
The [kvman](https://github.com/ibndeif/kvman) extension that makes
|
|
3
|
+
The [kvman](https://github.com/ibndeif/kvman) extension that makes any kind of video from a chat (a lesson, an explainer, a tutorial, a promotion, a story, a social clip): it records websites and HTML pages in the installed Chrome or Edge, narrates a script with ElevenLabs, OpenAI, or Piper, and joins them with burned-in captions into an MP4 with ffmpeg. It is bundled with kvman, and needs `@kvman/kvcoder` and `@kvman/kvwebui`. Type `/video` in a chat to turn it on.
|
|
4
4
|
|
|
5
5
|
## Fonts
|
|
6
6
|
|
package/dist/api.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { z } from '@kvman/sdk';
|
|
2
2
|
import type { composeInputSchema, composeOutputSchema } from './compose/compose-input.ts';
|
|
3
|
+
import type { lookInputSchema, lookOutputSchema } from './look/look-input.ts';
|
|
3
4
|
import type { narrateInputSchema, narrateOutputSchema } from './narration/register-narration.ts';
|
|
4
5
|
import type { recordInputSchema, recordOutputSchema } from './record/steps.ts';
|
|
6
|
+
import type { reviewOutputSchema } from './review/register-review.ts';
|
|
7
|
+
import type { voiceInputSchema, voiceOutputSchema } from './narration/register-voice.ts';
|
|
8
|
+
import type { Brand } from './brand/brand.ts';
|
|
5
9
|
import type { BrowserChoice, NarrationService } from './settings.ts';
|
|
6
10
|
type Empty = Record<string, never>;
|
|
7
11
|
type Channel = 'chrome' | 'msedge';
|
|
@@ -26,6 +30,24 @@ declare module '@kvman/sdk' {
|
|
|
26
30
|
input: z.input<typeof recordInputSchema>;
|
|
27
31
|
output: z.output<typeof recordOutputSchema>;
|
|
28
32
|
};
|
|
33
|
+
'kvvideo.frame.capture': {
|
|
34
|
+
input: z.input<typeof lookInputSchema>;
|
|
35
|
+
output: z.output<typeof lookOutputSchema>;
|
|
36
|
+
};
|
|
37
|
+
'kvvideo.brand.set': {
|
|
38
|
+
input: Brand;
|
|
39
|
+
output: Empty;
|
|
40
|
+
};
|
|
41
|
+
'kvvideo.voice.make': {
|
|
42
|
+
input: z.input<typeof voiceInputSchema>;
|
|
43
|
+
output: z.output<typeof voiceOutputSchema>;
|
|
44
|
+
};
|
|
45
|
+
'kvvideo.video.review': {
|
|
46
|
+
input: {
|
|
47
|
+
file: string;
|
|
48
|
+
};
|
|
49
|
+
output: z.output<typeof reviewOutputSchema>;
|
|
50
|
+
};
|
|
29
51
|
}
|
|
30
52
|
interface Queries {
|
|
31
53
|
'kvvideo.setup.get': {
|
|
@@ -64,11 +86,20 @@ declare module '@kvman/sdk' {
|
|
|
64
86
|
scripts: ('latin' | 'arabic')[];
|
|
65
87
|
}[];
|
|
66
88
|
};
|
|
89
|
+
'kvvideo.brand.get': {
|
|
90
|
+
input: Empty;
|
|
91
|
+
output: Brand | null;
|
|
92
|
+
};
|
|
67
93
|
}
|
|
68
94
|
interface Settings {
|
|
69
95
|
'kvvideo.narration.service': NarrationService | null;
|
|
70
96
|
'kvvideo.narration.voice': string | null;
|
|
71
97
|
'kvvideo.narration.model': string | null;
|
|
98
|
+
'kvvideo.narration.pronunciations': {
|
|
99
|
+
word: string;
|
|
100
|
+
say: string;
|
|
101
|
+
}[];
|
|
102
|
+
'kvvideo.brand': Brand | null;
|
|
72
103
|
'kvvideo.browser': BrowserChoice;
|
|
73
104
|
'kvvideo.programs.ffmpeg': string;
|
|
74
105
|
'kvvideo.programs.ffprobe': string;
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACjG,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKrE,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACnC,KAAK,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnC,OAAO,QAAQ,YAAY,CAAC;IAC1B,UAAU,QAAQ;QAChB,qBAAqB,EAAE;YAAE,KAAK,EAAE;gBAAE,SAAS,EAAE,MAAM,CAAC;gBAAC,QAAQ,EAAE,MAAM,CAAA;aAAE,CAAC;YAAC,MAAM,EAAE,KAAK,CAAA;SAAE,CAAC;QACzF,uBAAuB,EAAE;YAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;YAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAA;SAAE,CAAC;QACrH,wBAAwB,EAAE;YAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;YAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAA;SAAE,CAAC;QACtH,qBAAqB,EAAE;YAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;YAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAA;SAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z, type Ctx } from '@kvman/sdk';
|
|
2
|
+
export declare const brandSchema: z.ZodObject<{
|
|
3
|
+
logo: z.ZodNullable<z.ZodString>;
|
|
4
|
+
colors: z.ZodObject<{
|
|
5
|
+
primary: z.ZodString;
|
|
6
|
+
background: z.ZodString;
|
|
7
|
+
text: z.ZodString;
|
|
8
|
+
}, z.core.$strict>;
|
|
9
|
+
font: z.ZodNullable<z.ZodString>;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
/** A workspace's brand. */
|
|
12
|
+
export type Brand = z.output<typeof brandSchema>;
|
|
13
|
+
export declare const logoExtensions: string[];
|
|
14
|
+
/** Checks a brand's files and font in the workspace `root`. */
|
|
15
|
+
export declare function checkBrand(root: string, brand: Brand): void;
|
|
16
|
+
export declare function registerBrand(ctx: Ctx): void;
|
|
17
|
+
//# sourceMappingURL=brand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../../src/brand/brand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,KAAK,GAAG,EAAE,MAAM,YAAY,CAAC;AASzC,eAAO,MAAM,WAAW;;;;;;;;kBAItB,CAAC;AAEH,2BAA2B;AAC3B,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAEjD,eAAO,MAAM,cAAc,UAA6C,CAAC;AAEzE,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAG3D;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAuB5C"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from '@kvman/sdk';
|
|
2
|
+
import { captionFont } from "../compose/caption-font.js";
|
|
3
|
+
import { inputPath } from "../files/workspace-paths.js";
|
|
4
|
+
// The workspace's brand (plan 16 §16.2 and §16.4; ADR 0115, 21 and 43): its logo, colours, and font, read with
|
|
5
|
+
// `video brand` and set with `video brand-set` without asking, since the person agreed to it in the script.
|
|
6
|
+
const colour = z.string().regex(/^#[0-9a-fA-F]{6}$/, 'A colour is #RRGGBB.');
|
|
7
|
+
export const brandSchema = z.strictObject({
|
|
8
|
+
logo: z.string().min(1).max(1000).nullable().describe('A .png, .svg, .jpg, or .webp file in the workspace, or null.'),
|
|
9
|
+
colors: z.strictObject({ primary: colour, background: colour, text: colour }),
|
|
10
|
+
font: z.string().min(1).max(1000).nullable().describe('A bundled font (video fonts), a .ttf or .otf file in the workspace, or null.'),
|
|
11
|
+
});
|
|
12
|
+
export const logoExtensions = ['.png', '.svg', '.jpg', '.jpeg', '.webp'];
|
|
13
|
+
/** Checks a brand's files and font in the workspace `root`. */
|
|
14
|
+
export function checkBrand(root, brand) {
|
|
15
|
+
if (brand.logo !== null)
|
|
16
|
+
inputPath(root, brand.logo, logoExtensions);
|
|
17
|
+
if (brand.font !== null)
|
|
18
|
+
captionFont(root, brand.font, []);
|
|
19
|
+
}
|
|
20
|
+
export function registerBrand(ctx) {
|
|
21
|
+
ctx.registerSetting('kvvideo.brand', { description: "The workspace's brand for its videos: a logo file, the primary, background, and text colours, and a font; null for none.", schema: brandSchema.nullable(), default: null });
|
|
22
|
+
ctx.registerQuery('kvvideo.brand.get', {
|
|
23
|
+
description: "Gives the workspace's brand for videos: its logo, colours, and font, or null.",
|
|
24
|
+
input: z.strictObject({}),
|
|
25
|
+
output: brandSchema.nullable(),
|
|
26
|
+
public: true,
|
|
27
|
+
timeoutMs: 60_000,
|
|
28
|
+
handle: async () => ctx.settings.get('kvvideo.brand'),
|
|
29
|
+
});
|
|
30
|
+
ctx.registerCommand('kvvideo.brand.set', {
|
|
31
|
+
description: "Sets the workspace's brand for videos: its logo, colours, and font.",
|
|
32
|
+
input: brandSchema,
|
|
33
|
+
output: z.strictObject({}),
|
|
34
|
+
public: true,
|
|
35
|
+
retries: 0,
|
|
36
|
+
timeoutMs: 60_000,
|
|
37
|
+
handle: async (input) => {
|
|
38
|
+
checkBrand(ctx.job.workspace.path, input);
|
|
39
|
+
await ctx.settings.set('kvvideo.brand', input, { scope: 'workspace' });
|
|
40
|
+
return {};
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=brand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand.js","sourceRoot":"","sources":["../../src/brand/brand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAY,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAExD,+GAA+G;AAC/G,4GAA4G;AAE5G,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,CAAC;AAE7E,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,YAAY,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC;IACrH,MAAM,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC7E,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8EAA8E,CAAC;CACtI,CAAC,CAAC;AAKH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAEzE,+DAA+D;AAC/D,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAY;IACnD,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI;QAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACrE,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI;QAAE,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,GAAG,CAAC,eAAe,CAAC,eAAe,EAAE,EAAE,WAAW,EAAE,0HAA0H,EAAE,MAAM,EAAE,WAAW,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACjO,GAAG,CAAC,aAAa,CAAC,mBAAmB,EAAE;QACrC,WAAW,EAAE,+EAA+E;QAC5F,KAAK,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,WAAW,CAAC,QAAQ,EAAE;QAC9B,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,MAAM;QACjB,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC;KACtD,CAAC,CAAC;IACH,GAAG,CAAC,eAAe,CAAC,mBAAmB,EAAE;QACvC,WAAW,EAAE,qEAAqE;QAClF,KAAK,EAAE,WAAW;QAClB,MAAM,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1B,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,CAAC;QACV,SAAS,EAAE,MAAM;QACjB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACtB,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1C,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;YACvE,OAAO,EAAE,CAAC;QACZ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/dist/browser/launch.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Browser } from 'playwright-core';
|
|
2
2
|
import type { Channel } from './channels.ts';
|
|
3
3
|
export declare function launchChannel(channel: Channel): Promise<Browser>;
|
|
4
|
+
/** The browser that draws a scene's frames and overlays, at one pixel per CSS pixel (ADR 0115, 36). */
|
|
5
|
+
export declare function launchDrawing(channel: Channel): Promise<Browser>;
|
|
4
6
|
//# sourceMappingURL=launch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/browser/launch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/browser/launch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAO7C,wBAAsB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtE;AAED,uGAAuG;AACvG,wBAAsB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAGtE"}
|
package/dist/browser/launch.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
// The installed Chrome or Edge, driven headless through playwright-core (ADR 0107, 9): no browser is downloaded.
|
|
1
|
+
// The installed Chrome or Edge, driven headless through playwright-core (ADR 0107, 9): no browser is downloaded. It
|
|
2
|
+
// draws at 2× density, so the screencast's frames are twice the page's CSS size (ADR 0115, 8).
|
|
2
3
|
// playwright-core is imported when a browser starts, not when kvvideo loads, since every worker loads kvvideo and
|
|
3
4
|
// most never record.
|
|
4
5
|
export async function launchChannel(channel) {
|
|
6
|
+
const { chromium } = await import('playwright-core');
|
|
7
|
+
return chromium.launch({ channel, headless: true, args: ['--force-device-scale-factor=2'] });
|
|
8
|
+
}
|
|
9
|
+
/** The browser that draws a scene's frames and overlays, at one pixel per CSS pixel (ADR 0115, 36). */
|
|
10
|
+
export async function launchDrawing(channel) {
|
|
5
11
|
const { chromium } = await import('playwright-core');
|
|
6
12
|
return chromium.launch({ channel, headless: true });
|
|
7
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/browser/launch.ts"],"names":[],"mappings":"AAGA,
|
|
1
|
+
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/browser/launch.ts"],"names":[],"mappings":"AAGA,oHAAoH;AACpH,+FAA+F;AAC/F,kHAAkH;AAClH,qBAAqB;AAErB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAgB;IAClD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACrD,OAAO,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,+BAA+B,CAAC,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED,uGAAuG;AACvG,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAgB;IAClD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACrD,OAAO,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import type { Caption } from '../narration/captions.ts';
|
|
2
|
+
export type CaptionLook = 'boxed' | 'outline' | 'highlight';
|
|
2
3
|
export type CaptionStyle = {
|
|
3
4
|
width: number;
|
|
4
5
|
height: number;
|
|
5
6
|
family: string;
|
|
6
7
|
size: number | undefined;
|
|
7
8
|
position: 'bottom' | 'top';
|
|
9
|
+
look: CaptionLook;
|
|
10
|
+
highlight: string;
|
|
8
11
|
};
|
|
9
12
|
/** A caption's text as ASS shows it: no override braces, no backslashes, one line. */
|
|
10
13
|
export declare function assText(text: string): string;
|
|
14
|
+
/** `#RRGGBB` as an ASS colour, `&HAABBGGRR`, opaque. */
|
|
15
|
+
export declare function assColour(colour: string): string;
|
|
11
16
|
export declare function assFile(style: CaptionStyle, captions: readonly Caption[]): string;
|
|
12
17
|
//# sourceMappingURL=ass-file.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ass-file.d.ts","sourceRoot":"","sources":["../../src/compose/ass-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"ass-file.d.ts","sourceRoot":"","sources":["../../src/compose/ass-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAQxD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;AAE5D,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAWzK,sFAAsF;AACtF,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wDAAwD;AACxD,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhD;AAiCD,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAoBjF"}
|
package/dist/compose/ass-file.js
CHANGED
|
@@ -10,11 +10,39 @@ function timeOf(ms) {
|
|
|
10
10
|
export function assText(text) {
|
|
11
11
|
return text.replace(/[{}\\]/g, '').replace(/\s+/g, ' ').trim();
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
/** `#RRGGBB` as an ASS colour, `&HAABBGGRR`, opaque. */
|
|
14
|
+
export function assColour(colour) {
|
|
15
|
+
return `&H00${`${colour.slice(5, 7)}${colour.slice(3, 5)}${colour.slice(1, 3)}`.toUpperCase()}`;
|
|
16
|
+
}
|
|
17
|
+
const box = '&H59000000';
|
|
18
|
+
function styleLine(name, style, primary, secondary) {
|
|
14
19
|
const size = style.size ?? Math.round(style.height / 18);
|
|
15
20
|
const alignment = style.position === 'top' ? 8 : 2;
|
|
16
21
|
const margin = Math.round(style.height * 0.06);
|
|
17
22
|
const family = style.family.replace(/,/g, ' ');
|
|
23
|
+
const border = style.look === 'outline' ? `0,0,1,3,0` : `0,0,3,${String(Math.round(size / 3))},0`;
|
|
24
|
+
const outline = style.look === 'outline' ? '&H00000000' : box;
|
|
25
|
+
const back = style.look === 'outline' ? '&H00000000' : box;
|
|
26
|
+
return `Style: ${name},${family},${String(size)},${primary},${secondary},${outline},${back},0,0,0,0,100,100,${border},${String(alignment)},40,40,${String(margin)},-1`;
|
|
27
|
+
}
|
|
28
|
+
// A line's words, each held as ASS karaoke from the line's start: the words already spoken take the primary colour.
|
|
29
|
+
function karaoke(caption) {
|
|
30
|
+
const centiseconds = (ms) => Math.max(0, Math.round(ms / 10));
|
|
31
|
+
const first = caption.words[0]?.startMs ?? caption.startMs;
|
|
32
|
+
const parts = first > caption.startMs ? [`{\\k${String(centiseconds(first - caption.startMs))}}`] : [];
|
|
33
|
+
caption.words.forEach((word, index) => {
|
|
34
|
+
const next = caption.words[index + 1]?.startMs ?? caption.endMs;
|
|
35
|
+
parts.push(`{\\k${String(centiseconds(next - word.startMs))}}${assText(word.text)}${index === caption.words.length - 1 ? '' : ' '}`);
|
|
36
|
+
});
|
|
37
|
+
return parts.join('');
|
|
38
|
+
}
|
|
39
|
+
function dialogue(style, caption) {
|
|
40
|
+
const timed = style.look === 'highlight' && caption.words !== undefined && caption.words.length > 0;
|
|
41
|
+
const text = timed && caption.words !== undefined ? karaoke({ ...caption, words: caption.words }) : assText(caption.text);
|
|
42
|
+
return `Dialogue: 0,${timeOf(caption.startMs)},${timeOf(caption.endMs)},${timed ? 'Spoken' : 'Default'},,0,0,0,,${text}`;
|
|
43
|
+
}
|
|
44
|
+
export function assFile(style, captions) {
|
|
45
|
+
const white = '&H00FFFFFF';
|
|
18
46
|
return [
|
|
19
47
|
'[Script Info]',
|
|
20
48
|
'ScriptType: v4.00+',
|
|
@@ -25,11 +53,12 @@ export function assFile(style, captions) {
|
|
|
25
53
|
'',
|
|
26
54
|
'[V4+ Styles]',
|
|
27
55
|
'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding',
|
|
28
|
-
|
|
56
|
+
styleLine('Default', style, white, white),
|
|
57
|
+
...(style.look === 'highlight' ? [styleLine('Spoken', style, assColour(style.highlight), white)] : []),
|
|
29
58
|
'',
|
|
30
59
|
'[Events]',
|
|
31
60
|
'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text',
|
|
32
|
-
...captions.map((caption) =>
|
|
61
|
+
...captions.map((caption) => dialogue(style, caption)),
|
|
33
62
|
'',
|
|
34
63
|
].join('\n');
|
|
35
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ass-file.js","sourceRoot":"","sources":["../../src/compose/ass-file.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ass-file.js","sourceRoot":"","sources":["../../src/compose/ass-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Brand } from '../brand/brand.ts';
|
|
2
|
+
import type { Size } from './frame-layout.ts';
|
|
3
|
+
export type Background = {
|
|
4
|
+
kind: 'image';
|
|
5
|
+
file: string;
|
|
6
|
+
} | {
|
|
7
|
+
kind: 'gradient';
|
|
8
|
+
from: string;
|
|
9
|
+
to: string;
|
|
10
|
+
};
|
|
11
|
+
/** `colour` mixed with `share` of `other`, as #rrggbb. */
|
|
12
|
+
export declare function mixed(colour: string, other: string, share: number): string;
|
|
13
|
+
/** The scene's background, from its `background` (a colour or an image file already checked) and the brand. */
|
|
14
|
+
export declare function backgroundOf(background: {
|
|
15
|
+
colour: string;
|
|
16
|
+
} | {
|
|
17
|
+
file: string;
|
|
18
|
+
} | undefined, brand: Brand | null): Background;
|
|
19
|
+
/** ffmpeg's input for the background, `lengthMs` long at 30 frames a second. */
|
|
20
|
+
export declare function backgroundInput(background: Background, size: Size, lengthMs: number): string[];
|
|
21
|
+
/** The filter that makes the background input the picture's size. */
|
|
22
|
+
export declare function backgroundFit(background: Background, size: Size): string;
|
|
23
|
+
//# sourceMappingURL=background.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../src/compose/background.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAM9C,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAI1G,0DAA0D;AAC1D,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAG1E;AAED,+GAA+G;AAC/G,wBAAgB,YAAY,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,UAAU,CAK3H;AAID,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAK9F;AAED,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAIxE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const channels = (colour) => [1, 3, 5].map((at) => Number.parseInt(colour.slice(at, at + 2), 16));
|
|
2
|
+
/** `colour` mixed with `share` of `other`, as #rrggbb. */
|
|
3
|
+
export function mixed(colour, other, share) {
|
|
4
|
+
const [base, added] = [channels(colour), channels(other)];
|
|
5
|
+
return `#${base.map((value, index) => Math.round(value * (1 - share) + (added[index] ?? 0) * share).toString(16).padStart(2, '0')).join('')}`;
|
|
6
|
+
}
|
|
7
|
+
/** The scene's background, from its `background` (a colour or an image file already checked) and the brand. */
|
|
8
|
+
export function backgroundOf(background, brand) {
|
|
9
|
+
if (background !== undefined && 'file' in background)
|
|
10
|
+
return { kind: 'image', file: background.file };
|
|
11
|
+
const colour = background?.colour ?? brand?.colors.background;
|
|
12
|
+
if (colour === undefined)
|
|
13
|
+
return { kind: 'gradient', from: '#0F172A', to: '#1E293B' };
|
|
14
|
+
return { kind: 'gradient', from: colour, to: brand === null ? colour : mixed(colour, brand.colors.primary, 0.18) };
|
|
15
|
+
}
|
|
16
|
+
const seconds = (ms) => (ms / 1000).toFixed(3);
|
|
17
|
+
/** ffmpeg's input for the background, `lengthMs` long at 30 frames a second. */
|
|
18
|
+
export function backgroundInput(background, size, lengthMs) {
|
|
19
|
+
const { width, height } = size;
|
|
20
|
+
if (background.kind === 'image')
|
|
21
|
+
return ['-loop', '1', '-framerate', '30', '-t', seconds(lengthMs), '-i', background.file];
|
|
22
|
+
const hex = (colour) => `0x${colour.slice(1)}`;
|
|
23
|
+
return ['-f', 'lavfi', '-t', seconds(lengthMs), '-i', `gradients=s=${String(width)}x${String(height)}:r=30:c0=${hex(background.from)}:c1=${hex(background.to)}:x0=0:y0=0:x1=${String(width)}:y1=${String(height)}:n=2:speed=0`];
|
|
24
|
+
}
|
|
25
|
+
/** The filter that makes the background input the picture's size. */
|
|
26
|
+
export function backgroundFit(background, size) {
|
|
27
|
+
const { width, height } = size;
|
|
28
|
+
const fit = background.kind === 'image' ? `scale=${String(width)}:${String(height)}:force_original_aspect_ratio=increase,crop=${String(width)}:${String(height)},` : '';
|
|
29
|
+
return `${fit}fps=30,format=yuv420p`;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=background.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background.js","sourceRoot":"","sources":["../../src/compose/background.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Action } from '../record/steps.ts';
|
|
2
|
+
export type View = {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
zoom: number;
|
|
6
|
+
};
|
|
7
|
+
/** One move of the view, from its start to its end. */
|
|
8
|
+
export type Shot = {
|
|
9
|
+
startMs: number;
|
|
10
|
+
endMs: number;
|
|
11
|
+
from: View;
|
|
12
|
+
to: View;
|
|
13
|
+
easing: 'cubic' | 'even';
|
|
14
|
+
};
|
|
15
|
+
export type CameraPlan = {
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
start: View;
|
|
19
|
+
shots: Shot[];
|
|
20
|
+
};
|
|
21
|
+
/** The camera of a recording of `width` × `height` CSS pixels, from its actions. */
|
|
22
|
+
export declare function cameraOfActions(actions: readonly Action[], width: number, height: number): CameraPlan;
|
|
23
|
+
/** An image's slow zoom over `lengthMs`; its size is the input's, read by ffmpeg. */
|
|
24
|
+
export declare function imageZoom(lengthMs: number): CameraPlan;
|
|
25
|
+
/** The view at `ms`. */
|
|
26
|
+
export declare function viewAt(plan: CameraPlan, ms: number): View;
|
|
27
|
+
/**
|
|
28
|
+
* The `perspective` filter that shows the plan's view of a frame `scale` times the plan's size, or of the input's own
|
|
29
|
+
* size for an image's zoom. `offsetMs` is where the part starts in the recording; the frames are at 30 a second.
|
|
30
|
+
*/
|
|
31
|
+
export declare function perspectiveFilter(plan: CameraPlan, scale: number | 'input', offsetMs: number): string;
|
|
32
|
+
//# sourceMappingURL=camera.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../src/compose/camera.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAO,MAAM,oBAAoB,CAAC;AAQtD,MAAM,MAAM,IAAI,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,uDAAuD;AACvD,MAAM,MAAM,IAAI,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,CAAC;AAEtG,MAAM,MAAM,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,EAAE,CAAA;CAAE,CAAC;AAiBvF,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAuBrG;AAED,qFAAqF;AACrF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAEtD;AAID,wBAAwB;AACxB,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAczD;AAmBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAarG"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const maximumZoom = 1.6;
|
|
2
|
+
const panMs = 600;
|
|
3
|
+
const runGapMs = 2500;
|
|
4
|
+
const holdMs = 1500;
|
|
5
|
+
const outMs = 800;
|
|
6
|
+
const leastInMs = 400;
|
|
7
|
+
const whole = (width, height) => ({ x: width / 2, y: height / 2, zoom: 1 });
|
|
8
|
+
function stopView(box, width, height) {
|
|
9
|
+
const zoom = Math.max(1, Math.min(maximumZoom, (0.8 * width) / box.width, (0.8 * height) / box.height));
|
|
10
|
+
const keep = (center, side) => Math.min(Math.max(center, side / (2 * zoom)), side - side / (2 * zoom));
|
|
11
|
+
return { x: keep(box.x + box.width / 2, width), y: keep(box.y + box.height / 2, height), zoom };
|
|
12
|
+
}
|
|
13
|
+
/** The camera of a recording of `width` × `height` CSS pixels, from its actions. */
|
|
14
|
+
export function cameraOfActions(actions, width, height) {
|
|
15
|
+
const start = whole(width, height);
|
|
16
|
+
const shots = [];
|
|
17
|
+
let current = start;
|
|
18
|
+
let lastEndMs;
|
|
19
|
+
const easeOut = (endMs) => {
|
|
20
|
+
shots.push({ startMs: endMs + holdMs, endMs: endMs + holdMs + outMs, from: current, to: start, easing: 'cubic' });
|
|
21
|
+
current = start;
|
|
22
|
+
};
|
|
23
|
+
for (const action of actions) {
|
|
24
|
+
if ((action.do !== 'click' && action.do !== 'type') || action.box === undefined || action.actMs === undefined)
|
|
25
|
+
continue;
|
|
26
|
+
const target = stopView(action.box, width, height);
|
|
27
|
+
if (lastEndMs !== undefined && action.atMs - lastEndMs <= runGapMs) {
|
|
28
|
+
shots.push({ startMs: action.atMs, endMs: action.atMs + panMs, from: current, to: target, easing: 'cubic' });
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
if (lastEndMs !== undefined)
|
|
32
|
+
easeOut(lastEndMs);
|
|
33
|
+
shots.push({ startMs: action.atMs, endMs: Math.max(action.actMs, action.atMs + leastInMs), from: current, to: target, easing: 'cubic' });
|
|
34
|
+
}
|
|
35
|
+
current = target;
|
|
36
|
+
lastEndMs = action.endMs;
|
|
37
|
+
}
|
|
38
|
+
if (lastEndMs !== undefined)
|
|
39
|
+
easeOut(lastEndMs);
|
|
40
|
+
return { width, height, start, shots };
|
|
41
|
+
}
|
|
42
|
+
/** An image's slow zoom over `lengthMs`; its size is the input's, read by ffmpeg. */
|
|
43
|
+
export function imageZoom(lengthMs) {
|
|
44
|
+
return { width: 1, height: 1, start: whole(1, 1), shots: [{ startMs: 0, endMs: lengthMs, from: whole(1, 1), to: { ...whole(1, 1), zoom: 1.08 }, easing: 'even' }] };
|
|
45
|
+
}
|
|
46
|
+
const cubic = (share) => (share < 0.5 ? 4 * share ** 3 : 1 - (-2 * share + 2) ** 3 / 2);
|
|
47
|
+
/** The view at `ms`. */
|
|
48
|
+
export function viewAt(plan, ms) {
|
|
49
|
+
let view = plan.start;
|
|
50
|
+
for (const shot of plan.shots) {
|
|
51
|
+
if (ms < shot.startMs)
|
|
52
|
+
break;
|
|
53
|
+
if (ms >= shot.endMs) {
|
|
54
|
+
view = shot.to;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const share = (ms - shot.startMs) / (shot.endMs - shot.startMs);
|
|
58
|
+
const eased = shot.easing === 'even' ? share : cubic(share);
|
|
59
|
+
const between = (key) => shot.from[key] + (shot.to[key] - shot.from[key]) * eased;
|
|
60
|
+
return { x: between('x'), y: between('y'), zoom: between('zoom') };
|
|
61
|
+
}
|
|
62
|
+
return view;
|
|
63
|
+
}
|
|
64
|
+
const number = (value) => String(Math.round(value * 10_000) / 10_000);
|
|
65
|
+
// One part of the view (x, y, or zoom) as an ffmpeg expression of the time `T` in ms.
|
|
66
|
+
function partExpression(plan, key, time) {
|
|
67
|
+
let expression = number(plan.shots.at(-1)?.to[key] ?? plan.start[key]);
|
|
68
|
+
for (let index = plan.shots.length - 1; index >= 0; index -= 1) {
|
|
69
|
+
const shot = plan.shots[index];
|
|
70
|
+
if (shot === undefined)
|
|
71
|
+
continue;
|
|
72
|
+
const before = number(plan.shots[index - 1]?.to[key] ?? plan.start[key]);
|
|
73
|
+
const share = `((${time}-${number(shot.startMs)})/${number(shot.endMs - shot.startMs)})`;
|
|
74
|
+
const eased = shot.easing === 'even' ? share : `if(lt(${share},0.5),4*pow(${share},3),1-pow(-2*${share}+2,3)/2)`;
|
|
75
|
+
const moving = `(${number(shot.from[key])}+${number(shot.to[key] - shot.from[key])}*${eased})`;
|
|
76
|
+
expression = `if(lt(${time},${number(shot.startMs)}),${before},if(lt(${time},${number(shot.endMs)}),${moving},${expression}))`;
|
|
77
|
+
}
|
|
78
|
+
return expression;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The `perspective` filter that shows the plan's view of a frame `scale` times the plan's size, or of the input's own
|
|
82
|
+
* size for an image's zoom. `offsetMs` is where the part starts in the recording; the frames are at 30 a second.
|
|
83
|
+
*/
|
|
84
|
+
export function perspectiveFilter(plan, scale, offsetMs) {
|
|
85
|
+
const time = `(in*1000/30+${number(offsetMs)})`;
|
|
86
|
+
const zoom = partExpression(plan, 'zoom', time);
|
|
87
|
+
const [pageWidth, pageHeight] = scale === 'input' ? ['W', 'H'] : [number(plan.width * scale), number(plan.height * scale)];
|
|
88
|
+
const factor = scale === 'input' ? 'W' : number(scale);
|
|
89
|
+
const factorY = scale === 'input' ? 'H' : number(scale);
|
|
90
|
+
const halfWidth = `(${pageWidth}/(2*${zoom}))`;
|
|
91
|
+
const halfHeight = `(${pageHeight}/(2*${zoom}))`;
|
|
92
|
+
const left = `clip(${partExpression(plan, 'x', time)}*${factor}-${halfWidth},0,${pageWidth}-2*${halfWidth})`;
|
|
93
|
+
const top = `clip(${partExpression(plan, 'y', time)}*${factorY}-${halfHeight},0,${pageHeight}-2*${halfHeight})`;
|
|
94
|
+
const right = `${left}+2*${halfWidth}`;
|
|
95
|
+
const bottom = `${top}+2*${halfHeight}`;
|
|
96
|
+
return `perspective=x0='${left}':y0='${top}':x1='${right}':y1='${top}':x2='${left}':y2='${bottom}':x3='${right}':y3='${bottom}':interpolation=cubic:sense=source:eval=frame`;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=camera.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.js","sourceRoot":"","sources":["../../src/compose/camera.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,5 +2,7 @@ export type CaptionFont = {
|
|
|
2
2
|
family: string;
|
|
3
3
|
file: string;
|
|
4
4
|
};
|
|
5
|
+
/** A letter of the Arabic script. */
|
|
6
|
+
export declare const arabicLetter: RegExp;
|
|
5
7
|
export declare function captionFont(root: string, named: string | undefined, texts: readonly string[]): CaptionFont;
|
|
6
8
|
//# sourceMappingURL=caption-font.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"caption-font.d.ts","sourceRoot":"","sources":["../../src/compose/caption-font.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"caption-font.d.ts","sourceRoot":"","sources":["../../src/compose/caption-font.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,qCAAqC;AACrC,eAAO,MAAM,YAAY,QAAyE,CAAC;AAOnG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAS1G"}
|
|
@@ -4,7 +4,8 @@ import { bundledFonts, fontsFolder } from "../fonts/bundled-fonts.js";
|
|
|
4
4
|
import { fontFamily } from "../fonts/font-family.js";
|
|
5
5
|
import { inputPath } from "../files/workspace-paths.js";
|
|
6
6
|
import { invalid } from "../problems.js";
|
|
7
|
-
|
|
7
|
+
/** A letter of the Arabic script. */
|
|
8
|
+
export const arabicLetter = /[\u0600-\u06ff\u0750-\u077f\u08a0-\u08ff\ufb50-\ufdff\ufe70-\ufeff]/u;
|
|
8
9
|
function bundled(name) {
|
|
9
10
|
const font = bundledFonts.find((candidate) => candidate.name === name);
|
|
10
11
|
return font === undefined ? undefined : { family: font.name, file: path.join(fontsFolder, font.file) };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"caption-font.js","sourceRoot":"","sources":["../../src/compose/caption-font.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAQzC,MAAM,YAAY,GAAG,sEAAsE,CAAC;
|
|
1
|
+
{"version":3,"file":"caption-font.js","sourceRoot":"","sources":["../../src/compose/caption-font.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAQzC,qCAAqC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,sEAAsE,CAAC;AAEnG,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACvE,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACzG,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAAyB,EAAE,KAAwB;IAC3F,MAAM,IAAI,GAAG,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3G,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACrD,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;IAChE,CAAC;IACD,MAAM,OAAO,CAAC,4BAA4B,IAAI,2BAA2B,YAAY,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,iDAAiD,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAChQ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Brand } from '../brand/brand.ts';
|
|
2
|
+
import { type Painter } from './drawn-images.ts';
|
|
3
|
+
import type { ScenePicture } from './compose-plan.ts';
|
|
4
|
+
import type { SceneDrawn } from './scene-args.ts';
|
|
5
|
+
export declare const defaultAccent = "#FFD54A";
|
|
6
|
+
/** Whether a scene needs the browser to draw anything. */
|
|
7
|
+
export declare function needsDrawing(picture: ScenePicture): boolean;
|
|
8
|
+
export type DrawingContext = {
|
|
9
|
+
root: string;
|
|
10
|
+
folder: string;
|
|
11
|
+
picture: {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
brand: Brand | null;
|
|
16
|
+
painter: Painter;
|
|
17
|
+
};
|
|
18
|
+
export declare function drawScene(context: DrawingContext, number: number, picture: ScenePicture): Promise<SceneDrawn>;
|
|
19
|
+
//# sourceMappingURL=compose-drawing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-drawing.d.ts","sourceRoot":"","sources":["../../src/compose/compose-drawing.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAoD,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMlD,eAAO,MAAM,aAAa,YAAY,CAAC;AAEvC,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAE3D;AAED,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEjJ,wBAAsB,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CAyBnH"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { captionFont } from "./caption-font.js";
|
|
3
|
+
import { calloutHtml, chromeHtml, highlightHtml, maskHtml } from "./drawn-images.js";
|
|
4
|
+
// The images a scene's frame and overlays need (plan 16 §16.8; ADR 0115, 36 and 60), drawn by the browser into the
|
|
5
|
+
// work folder: a window's or a phone's chrome and the clip's mask at the picture's size, and each callout and
|
|
6
|
+
// highlight at the recording's own size. A blur needs no image.
|
|
7
|
+
export const defaultAccent = '#FFD54A';
|
|
8
|
+
/** Whether a scene needs the browser to draw anything. */
|
|
9
|
+
export function needsDrawing(picture) {
|
|
10
|
+
return picture.layout !== undefined || picture.look.overlays.some((overlay) => overlay.kind !== 'blur');
|
|
11
|
+
}
|
|
12
|
+
export async function drawScene(context, number, picture) {
|
|
13
|
+
const name = (part) => `scene-${String(number)}-${part}.png`;
|
|
14
|
+
const at = (file) => path.join(context.folder, file);
|
|
15
|
+
const { layout, source } = picture;
|
|
16
|
+
let chrome;
|
|
17
|
+
let mask;
|
|
18
|
+
if (layout !== undefined) {
|
|
19
|
+
chrome = name('chrome');
|
|
20
|
+
mask = name('mask');
|
|
21
|
+
await context.painter.draw(at(chrome), context.picture, chromeHtml(layout), true);
|
|
22
|
+
await context.painter.draw(at(mask), { width: layout.screen.width, height: layout.screen.height }, maskHtml({ width: layout.screen.width, height: layout.screen.height }, layout.radius), false);
|
|
23
|
+
}
|
|
24
|
+
const overlayImages = [];
|
|
25
|
+
for (const [index, overlay] of picture.look.overlays.entries()) {
|
|
26
|
+
if (overlay.kind === 'blur' || source === undefined) {
|
|
27
|
+
overlayImages.push(undefined);
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const file = name(`overlay-${String(index + 1)}`);
|
|
31
|
+
const colour = context.brand?.colors.primary ?? defaultAccent;
|
|
32
|
+
const html = overlay.kind === 'highlight' ? highlightHtml(overlay.box, picture.look.scale) : calloutHtml(source, overlay.box, overlay.text ?? '', colour, captionFont(context.root, context.brand?.font ?? undefined, [overlay.text ?? '']));
|
|
33
|
+
await context.painter.draw(at(file), source, html, true);
|
|
34
|
+
overlayImages.push(file);
|
|
35
|
+
}
|
|
36
|
+
return { layout, chrome, mask, overlayImages };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=compose-drawing.js.map
|