@tongue-core/project 0.1.0-rc.4 → 0.1.0-rc.5
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/dist/build/extract.d.ts +13 -6
- package/dist/doc/assemble.d.ts +39 -18
- package/dist/doc/assemble.js +14 -7
- package/dist/doc/check.d.ts +26 -12
- package/dist/doc/check.js +15 -0
- package/dist/doc/film-doc.d.ts +48 -0
- package/dist/doc/film-doc.js +6 -0
- package/dist/doc/from-plan.d.ts +13 -6
- package/dist/doc/from-plan.js +4 -4
- package/dist/doc/index.d.ts +1 -1
- package/dist/doc/index.js +1 -1
- package/dist/doc/plan-doc.d.ts +13 -6
- package/package.json +2 -2
package/dist/build/extract.d.ts
CHANGED
|
@@ -109,13 +109,9 @@ export declare const extractFilm: (project: LoadedProject, options?: ExtractOpti
|
|
|
109
109
|
readonly fit: "cover" | "contain";
|
|
110
110
|
readonly blend?: "multiply" | "screen" | "overlay" | "soft-light" | "color-dodge" | "normal" | undefined;
|
|
111
111
|
} | {
|
|
112
|
-
readonly asset: string;
|
|
113
112
|
readonly in: number;
|
|
114
113
|
readonly out: number;
|
|
115
|
-
readonly
|
|
116
|
-
readonly gain: number;
|
|
117
|
-
readonly fadeIn: number;
|
|
118
|
-
readonly fadeOut: number;
|
|
114
|
+
readonly kind: "audio";
|
|
119
115
|
readonly id: string;
|
|
120
116
|
readonly start: number;
|
|
121
117
|
readonly duration: number;
|
|
@@ -124,7 +120,18 @@ export declare const extractFilm: (project: LoadedProject, options?: ExtractOpti
|
|
|
124
120
|
readonly file: string;
|
|
125
121
|
readonly line: number;
|
|
126
122
|
} | null;
|
|
127
|
-
readonly
|
|
123
|
+
readonly asset: string;
|
|
124
|
+
readonly speed: number;
|
|
125
|
+
readonly gain: number;
|
|
126
|
+
readonly fadeIn: number;
|
|
127
|
+
readonly fadeOut: number;
|
|
128
|
+
readonly voice?: {
|
|
129
|
+
readonly words: readonly {
|
|
130
|
+
readonly text: string;
|
|
131
|
+
readonly start: number;
|
|
132
|
+
readonly end: number;
|
|
133
|
+
}[];
|
|
134
|
+
} | undefined;
|
|
128
135
|
})[];
|
|
129
136
|
readonly transitions: readonly ({
|
|
130
137
|
readonly from: string;
|
package/dist/doc/assemble.d.ts
CHANGED
|
@@ -107,13 +107,9 @@ export declare const assembleFilm: (doc: {
|
|
|
107
107
|
readonly fit: "cover" | "contain";
|
|
108
108
|
readonly blend?: "multiply" | "screen" | "overlay" | "soft-light" | "color-dodge" | "normal" | undefined;
|
|
109
109
|
} | {
|
|
110
|
-
readonly asset: string;
|
|
111
110
|
readonly in: number;
|
|
112
111
|
readonly out: number;
|
|
113
|
-
readonly
|
|
114
|
-
readonly gain: number;
|
|
115
|
-
readonly fadeIn: number;
|
|
116
|
-
readonly fadeOut: number;
|
|
112
|
+
readonly kind: "audio";
|
|
117
113
|
readonly id: string;
|
|
118
114
|
readonly start: number;
|
|
119
115
|
readonly duration: number;
|
|
@@ -122,7 +118,18 @@ export declare const assembleFilm: (doc: {
|
|
|
122
118
|
readonly file: string;
|
|
123
119
|
readonly line: number;
|
|
124
120
|
} | null;
|
|
125
|
-
readonly
|
|
121
|
+
readonly asset: string;
|
|
122
|
+
readonly speed: number;
|
|
123
|
+
readonly gain: number;
|
|
124
|
+
readonly fadeIn: number;
|
|
125
|
+
readonly fadeOut: number;
|
|
126
|
+
readonly voice?: {
|
|
127
|
+
readonly words: readonly {
|
|
128
|
+
readonly text: string;
|
|
129
|
+
readonly start: number;
|
|
130
|
+
readonly end: number;
|
|
131
|
+
}[];
|
|
132
|
+
} | undefined;
|
|
126
133
|
})[];
|
|
127
134
|
readonly transitions: readonly ({
|
|
128
135
|
readonly from: string;
|
|
@@ -322,13 +329,9 @@ export declare const sceneFilmDoc: (doc: {
|
|
|
322
329
|
readonly fit: "cover" | "contain";
|
|
323
330
|
readonly blend?: "multiply" | "screen" | "overlay" | "soft-light" | "color-dodge" | "normal" | undefined;
|
|
324
331
|
} | {
|
|
325
|
-
readonly asset: string;
|
|
326
332
|
readonly in: number;
|
|
327
333
|
readonly out: number;
|
|
328
|
-
readonly
|
|
329
|
-
readonly gain: number;
|
|
330
|
-
readonly fadeIn: number;
|
|
331
|
-
readonly fadeOut: number;
|
|
334
|
+
readonly kind: "audio";
|
|
332
335
|
readonly id: string;
|
|
333
336
|
readonly start: number;
|
|
334
337
|
readonly duration: number;
|
|
@@ -337,7 +340,18 @@ export declare const sceneFilmDoc: (doc: {
|
|
|
337
340
|
readonly file: string;
|
|
338
341
|
readonly line: number;
|
|
339
342
|
} | null;
|
|
340
|
-
readonly
|
|
343
|
+
readonly asset: string;
|
|
344
|
+
readonly speed: number;
|
|
345
|
+
readonly gain: number;
|
|
346
|
+
readonly fadeIn: number;
|
|
347
|
+
readonly fadeOut: number;
|
|
348
|
+
readonly voice?: {
|
|
349
|
+
readonly words: readonly {
|
|
350
|
+
readonly text: string;
|
|
351
|
+
readonly start: number;
|
|
352
|
+
readonly end: number;
|
|
353
|
+
}[];
|
|
354
|
+
} | undefined;
|
|
341
355
|
})[];
|
|
342
356
|
readonly transitions: readonly ({
|
|
343
357
|
readonly from: string;
|
|
@@ -534,13 +548,9 @@ export declare const sceneFilmDoc: (doc: {
|
|
|
534
548
|
readonly fit: "cover" | "contain";
|
|
535
549
|
readonly blend?: "multiply" | "screen" | "overlay" | "soft-light" | "color-dodge" | "normal" | undefined;
|
|
536
550
|
} | {
|
|
537
|
-
readonly asset: string;
|
|
538
551
|
readonly in: number;
|
|
539
552
|
readonly out: number;
|
|
540
|
-
readonly
|
|
541
|
-
readonly gain: number;
|
|
542
|
-
readonly fadeIn: number;
|
|
543
|
-
readonly fadeOut: number;
|
|
553
|
+
readonly kind: "audio";
|
|
544
554
|
readonly id: string;
|
|
545
555
|
readonly start: number;
|
|
546
556
|
readonly duration: number;
|
|
@@ -549,7 +559,18 @@ export declare const sceneFilmDoc: (doc: {
|
|
|
549
559
|
readonly file: string;
|
|
550
560
|
readonly line: number;
|
|
551
561
|
} | null;
|
|
552
|
-
readonly
|
|
562
|
+
readonly asset: string;
|
|
563
|
+
readonly speed: number;
|
|
564
|
+
readonly gain: number;
|
|
565
|
+
readonly fadeIn: number;
|
|
566
|
+
readonly fadeOut: number;
|
|
567
|
+
readonly voice?: {
|
|
568
|
+
readonly words: readonly {
|
|
569
|
+
readonly text: string;
|
|
570
|
+
readonly start: number;
|
|
571
|
+
readonly end: number;
|
|
572
|
+
}[];
|
|
573
|
+
} | undefined;
|
|
553
574
|
})[];
|
|
554
575
|
readonly transitions: readonly ({
|
|
555
576
|
readonly from: string;
|
package/dist/doc/assemble.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { audio, Clip, Film, font, fromJson, image, SchemaError, Track, Transition, video, } from "@tongue-core/film";
|
|
1
|
+
import { audio, Clip, Film, font, fromJson, image, narration, SchemaError, Track, Transition, video, } from "@tongue-core/film";
|
|
2
2
|
import { setOrigin } from "@tongue-core/film/model";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
import { DocError } from "../errors.js";
|
|
@@ -62,7 +62,7 @@ function kitOf(doc, reader) {
|
|
|
62
62
|
return doc.kit === null || !declaring ? undefined : reader.read(reader.scene(declaring.id, "kit").kitSchema, doc.kit, "kit");
|
|
63
63
|
}
|
|
64
64
|
const isKind = (asset, kind) => asset.kind === kind;
|
|
65
|
-
function clipNode(clip, path, reader) {
|
|
65
|
+
function clipNode(clip, path, reader, fps) {
|
|
66
66
|
const placed = { id: clip.id, from: clip.start, duration: clip.duration };
|
|
67
67
|
switch (clip.kind) {
|
|
68
68
|
case "scene": {
|
|
@@ -73,8 +73,15 @@ function clipNode(clip, path, reader) {
|
|
|
73
73
|
return Clip({ ...placed, video: reader.asset("video", clip.asset, `${path}.asset`), in: clip.in, out: clip.out, speed: clip.speed, reverse: clip.reverse, freeze: clip.freeze, fit: clip.fit, opacity: clip.opacity, blend: clip.blend ?? "normal" });
|
|
74
74
|
case "image":
|
|
75
75
|
return Clip({ ...placed, image: reader.asset("image", clip.asset, `${path}.asset`), fit: clip.fit, opacity: clip.opacity, blend: clip.blend ?? "normal" });
|
|
76
|
-
case "audio":
|
|
77
|
-
|
|
76
|
+
case "audio": {
|
|
77
|
+
const asset = reader.asset("audio", clip.asset, `${path}.asset`);
|
|
78
|
+
// Narration is the clip's words, in frames from its start: a voiceover over the file from `in`.
|
|
79
|
+
if (clip.voice !== undefined) {
|
|
80
|
+
const voice = narration(asset, { fps, frames: clip.duration, words: clip.voice.words }, clip.in);
|
|
81
|
+
return Clip({ ...placed, voice, gain: clip.gain, fadeIn: clip.fadeIn, fadeOut: clip.fadeOut });
|
|
82
|
+
}
|
|
83
|
+
return Clip({ ...placed, audio: asset, in: clip.in, out: clip.out, speed: clip.speed, gain: clip.gain, fadeIn: clip.fadeIn, fadeOut: clip.fadeOut });
|
|
84
|
+
}
|
|
78
85
|
}
|
|
79
86
|
}
|
|
80
87
|
function transitionNode(t) {
|
|
@@ -93,11 +100,11 @@ function placedAt(node, origin) {
|
|
|
93
100
|
return node;
|
|
94
101
|
}
|
|
95
102
|
/** A track's clips in order, each transition just before the clip it brings in. */
|
|
96
|
-
function trackNode(track, path, reader) {
|
|
103
|
+
function trackNode(track, path, reader, fps) {
|
|
97
104
|
const into = new Map(track.transitions.map((t) => [t.to, t]));
|
|
98
105
|
const children = track.clips.flatMap((clip, i) => {
|
|
99
106
|
const t = into.get(clip.id);
|
|
100
|
-
const node = placedAt(clipNode(clip, `${path}.clips[${i}]`, reader), clip.origin);
|
|
107
|
+
const node = placedAt(clipNode(clip, `${path}.clips[${i}]`, reader, fps), clip.origin);
|
|
101
108
|
return t ? [placedAt(transitionNode(t), t.origin), node] : [node];
|
|
102
109
|
});
|
|
103
110
|
return Track({ id: track.id, children });
|
|
@@ -117,7 +124,7 @@ export const assembleFilm = Effect.fn("assembleFilm")(function* (doc, scenes) {
|
|
|
117
124
|
kit: kitOf(doc, reader),
|
|
118
125
|
tail: doc.film.tail,
|
|
119
126
|
assets,
|
|
120
|
-
children: doc.tracks.map((track, i) => trackNode(track, `tracks[${i}]`, reader)),
|
|
127
|
+
children: doc.tracks.map((track, i) => trackNode(track, `tracks[${i}]`, reader, doc.film.fps)),
|
|
121
128
|
});
|
|
122
129
|
},
|
|
123
130
|
catch: (e) => (e instanceof DocError ? e : docError("film.json couldn't be assembled", [{ path: "", message: e instanceof Error ? e.message : String(e) }])),
|
package/dist/doc/check.d.ts
CHANGED
|
@@ -101,13 +101,9 @@ export declare const decodeFilmDoc: (json: unknown) => Effect.Effect<{
|
|
|
101
101
|
readonly fit: "cover" | "contain";
|
|
102
102
|
readonly blend?: "multiply" | "screen" | "overlay" | "soft-light" | "color-dodge" | "normal" | undefined;
|
|
103
103
|
} | {
|
|
104
|
-
readonly asset: string;
|
|
105
104
|
readonly in: number;
|
|
106
105
|
readonly out: number;
|
|
107
|
-
readonly
|
|
108
|
-
readonly gain: number;
|
|
109
|
-
readonly fadeIn: number;
|
|
110
|
-
readonly fadeOut: number;
|
|
106
|
+
readonly kind: "audio";
|
|
111
107
|
readonly id: string;
|
|
112
108
|
readonly start: number;
|
|
113
109
|
readonly duration: number;
|
|
@@ -116,7 +112,18 @@ export declare const decodeFilmDoc: (json: unknown) => Effect.Effect<{
|
|
|
116
112
|
readonly file: string;
|
|
117
113
|
readonly line: number;
|
|
118
114
|
} | null;
|
|
119
|
-
readonly
|
|
115
|
+
readonly asset: string;
|
|
116
|
+
readonly speed: number;
|
|
117
|
+
readonly gain: number;
|
|
118
|
+
readonly fadeIn: number;
|
|
119
|
+
readonly fadeOut: number;
|
|
120
|
+
readonly voice?: {
|
|
121
|
+
readonly words: readonly {
|
|
122
|
+
readonly text: string;
|
|
123
|
+
readonly start: number;
|
|
124
|
+
readonly end: number;
|
|
125
|
+
}[];
|
|
126
|
+
} | undefined;
|
|
120
127
|
})[];
|
|
121
128
|
readonly transitions: readonly ({
|
|
122
129
|
readonly from: string;
|
|
@@ -315,13 +322,9 @@ export declare const parseFilmDoc: (text: string) => Effect.Effect<{
|
|
|
315
322
|
readonly fit: "cover" | "contain";
|
|
316
323
|
readonly blend?: "multiply" | "screen" | "overlay" | "soft-light" | "color-dodge" | "normal" | undefined;
|
|
317
324
|
} | {
|
|
318
|
-
readonly asset: string;
|
|
319
325
|
readonly in: number;
|
|
320
326
|
readonly out: number;
|
|
321
|
-
readonly
|
|
322
|
-
readonly gain: number;
|
|
323
|
-
readonly fadeIn: number;
|
|
324
|
-
readonly fadeOut: number;
|
|
327
|
+
readonly kind: "audio";
|
|
325
328
|
readonly id: string;
|
|
326
329
|
readonly start: number;
|
|
327
330
|
readonly duration: number;
|
|
@@ -330,7 +333,18 @@ export declare const parseFilmDoc: (text: string) => Effect.Effect<{
|
|
|
330
333
|
readonly file: string;
|
|
331
334
|
readonly line: number;
|
|
332
335
|
} | null;
|
|
333
|
-
readonly
|
|
336
|
+
readonly asset: string;
|
|
337
|
+
readonly speed: number;
|
|
338
|
+
readonly gain: number;
|
|
339
|
+
readonly fadeIn: number;
|
|
340
|
+
readonly fadeOut: number;
|
|
341
|
+
readonly voice?: {
|
|
342
|
+
readonly words: readonly {
|
|
343
|
+
readonly text: string;
|
|
344
|
+
readonly start: number;
|
|
345
|
+
readonly end: number;
|
|
346
|
+
}[];
|
|
347
|
+
} | undefined;
|
|
334
348
|
})[];
|
|
335
349
|
readonly transitions: readonly ({
|
|
336
350
|
readonly from: string;
|
package/dist/doc/check.js
CHANGED
|
@@ -25,6 +25,8 @@ function checkTrack(track, at, scenes, assets, out) {
|
|
|
25
25
|
out.push({ path: `${path}.asset`, message: `there is no ${clip.kind} asset named "${clip.asset}" in assets` });
|
|
26
26
|
if ((clip.kind === "video" || clip.kind === "audio") && !(clip.out > clip.in))
|
|
27
27
|
out.push({ path: `${path}.out`, message: `must be after in (${clip.in} s)` });
|
|
28
|
+
if (clip.kind === "audio" && clip.voice !== undefined)
|
|
29
|
+
checkWords(clip.voice.words, clip.duration, `${path}.voice.words`, out);
|
|
28
30
|
if (clip.kind === "scene" && (typeof clip.props !== "object" || clip.props === null || Array.isArray(clip.props)))
|
|
29
31
|
out.push({ path: `${path}.props`, message: "must be an object" });
|
|
30
32
|
previous = clip;
|
|
@@ -64,6 +66,19 @@ function checkTrack(track, at, scenes, assets, out) {
|
|
|
64
66
|
out.push({ path: `${path}.frames`, message: `lasts ${t.frames} frames, longer than "${b.id}" (${b.duration})` });
|
|
65
67
|
});
|
|
66
68
|
}
|
|
69
|
+
/** Narration's words: each ends after it starts, inside the clip, and they come in order. */
|
|
70
|
+
function checkWords(words, duration, at, out) {
|
|
71
|
+
let previous = 0;
|
|
72
|
+
words.forEach((word, i) => {
|
|
73
|
+
if (word.end < word.start)
|
|
74
|
+
out.push({ path: `${at}[${i}].end`, message: `"${word.text}" ends at ${word.end}, before it starts (${word.start})` });
|
|
75
|
+
if (word.end > duration + EPSILON)
|
|
76
|
+
out.push({ path: `${at}[${i}].end`, message: `"${word.text}" ends at ${word.end}, after the clip (${duration} frames)` });
|
|
77
|
+
if (word.start < previous - EPSILON)
|
|
78
|
+
out.push({ path: `${at}[${i}].start`, message: `"${word.text}" starts at ${word.start}, before the word before it (${previous}); words come in order` });
|
|
79
|
+
previous = Math.max(previous, word.start);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
67
82
|
/** Every problem with how the document holds together (none: it does). */
|
|
68
83
|
export function filmDocProblems(doc) {
|
|
69
84
|
const out = [];
|
package/dist/doc/film-doc.d.ts
CHANGED
|
@@ -121,6 +121,22 @@ export declare const ImageClipDoc: Schema.Struct<{
|
|
|
121
121
|
readonly kind: Schema.Literal<"image">;
|
|
122
122
|
}>;
|
|
123
123
|
export type ImageClipDoc = typeof ImageClipDoc.Type;
|
|
124
|
+
/** A spoken word: its text, and when it starts and ends, in frames from the clip's start. */
|
|
125
|
+
export declare const WordDoc: Schema.Struct<{
|
|
126
|
+
readonly text: Schema.String;
|
|
127
|
+
readonly start: Schema.Finite;
|
|
128
|
+
readonly end: Schema.Finite;
|
|
129
|
+
}>;
|
|
130
|
+
export type WordDoc = typeof WordDoc.Type;
|
|
131
|
+
/** The narration an audio clip plays (a `<Clip voice>`): its words. Left out of a plain audio clip. */
|
|
132
|
+
export declare const VoiceDoc: Schema.Struct<{
|
|
133
|
+
readonly words: Schema.$Array<Schema.Struct<{
|
|
134
|
+
readonly text: Schema.String;
|
|
135
|
+
readonly start: Schema.Finite;
|
|
136
|
+
readonly end: Schema.Finite;
|
|
137
|
+
}>>;
|
|
138
|
+
}>;
|
|
139
|
+
export type VoiceDoc = typeof VoiceDoc.Type;
|
|
124
140
|
export declare const AudioClipDoc: Schema.Struct<{
|
|
125
141
|
readonly asset: Schema.String;
|
|
126
142
|
readonly in: Schema.Finite;
|
|
@@ -131,6 +147,14 @@ export declare const AudioClipDoc: Schema.Struct<{
|
|
|
131
147
|
/** Frames. */
|
|
132
148
|
readonly fadeIn: Schema.Finite;
|
|
133
149
|
readonly fadeOut: Schema.Finite;
|
|
150
|
+
/** Its words, when it plays narration: a player can show what is being said. */
|
|
151
|
+
readonly voice: Schema.optionalKey<Schema.Struct<{
|
|
152
|
+
readonly words: Schema.$Array<Schema.Struct<{
|
|
153
|
+
readonly text: Schema.String;
|
|
154
|
+
readonly start: Schema.Finite;
|
|
155
|
+
readonly end: Schema.Finite;
|
|
156
|
+
}>>;
|
|
157
|
+
}>>;
|
|
134
158
|
readonly id: Schema.String;
|
|
135
159
|
readonly start: Schema.Finite;
|
|
136
160
|
readonly duration: Schema.Finite;
|
|
@@ -200,6 +224,14 @@ export declare const ClipDoc: Schema.Union<readonly [Schema.Struct<{
|
|
|
200
224
|
/** Frames. */
|
|
201
225
|
readonly fadeIn: Schema.Finite;
|
|
202
226
|
readonly fadeOut: Schema.Finite;
|
|
227
|
+
/** Its words, when it plays narration: a player can show what is being said. */
|
|
228
|
+
readonly voice: Schema.optionalKey<Schema.Struct<{
|
|
229
|
+
readonly words: Schema.$Array<Schema.Struct<{
|
|
230
|
+
readonly text: Schema.String;
|
|
231
|
+
readonly start: Schema.Finite;
|
|
232
|
+
readonly end: Schema.Finite;
|
|
233
|
+
}>>;
|
|
234
|
+
}>>;
|
|
203
235
|
readonly id: Schema.String;
|
|
204
236
|
readonly start: Schema.Finite;
|
|
205
237
|
readonly duration: Schema.Finite;
|
|
@@ -478,6 +510,14 @@ export declare const TrackDoc: Schema.Struct<{
|
|
|
478
510
|
/** Frames. */
|
|
479
511
|
readonly fadeIn: Schema.Finite;
|
|
480
512
|
readonly fadeOut: Schema.Finite;
|
|
513
|
+
/** Its words, when it plays narration: a player can show what is being said. */
|
|
514
|
+
readonly voice: Schema.optionalKey<Schema.Struct<{
|
|
515
|
+
readonly words: Schema.$Array<Schema.Struct<{
|
|
516
|
+
readonly text: Schema.String;
|
|
517
|
+
readonly start: Schema.Finite;
|
|
518
|
+
readonly end: Schema.Finite;
|
|
519
|
+
}>>;
|
|
520
|
+
}>>;
|
|
481
521
|
readonly id: Schema.String;
|
|
482
522
|
readonly start: Schema.Finite;
|
|
483
523
|
readonly duration: Schema.Finite;
|
|
@@ -714,6 +754,14 @@ export declare const FilmDoc: Schema.Struct<{
|
|
|
714
754
|
/** Frames. */
|
|
715
755
|
readonly fadeIn: Schema.Finite;
|
|
716
756
|
readonly fadeOut: Schema.Finite;
|
|
757
|
+
/** Its words, when it plays narration: a player can show what is being said. */
|
|
758
|
+
readonly voice: Schema.optionalKey<Schema.Struct<{
|
|
759
|
+
readonly words: Schema.$Array<Schema.Struct<{
|
|
760
|
+
readonly text: Schema.String;
|
|
761
|
+
readonly start: Schema.Finite;
|
|
762
|
+
readonly end: Schema.Finite;
|
|
763
|
+
}>>;
|
|
764
|
+
}>>;
|
|
717
765
|
readonly id: Schema.String;
|
|
718
766
|
readonly start: Schema.Finite;
|
|
719
767
|
readonly duration: Schema.Finite;
|
package/dist/doc/film-doc.js
CHANGED
|
@@ -98,6 +98,10 @@ export const VideoClipDoc = Schema.Struct({
|
|
|
98
98
|
blend: Schema.optionalKey(Blend),
|
|
99
99
|
});
|
|
100
100
|
export const ImageClipDoc = Schema.Struct({ kind: Schema.Literal("image"), ...placement, asset: Name, fit: Fit, opacity: Unit, blend: Schema.optionalKey(Blend) });
|
|
101
|
+
/** A spoken word: its text, and when it starts and ends, in frames from the clip's start. */
|
|
102
|
+
export const WordDoc = Schema.Struct({ text: Schema.String, start: Frames, end: Frames });
|
|
103
|
+
/** The narration an audio clip plays (a `<Clip voice>`): its words. Left out of a plain audio clip. */
|
|
104
|
+
export const VoiceDoc = Schema.Struct({ words: Schema.Array(WordDoc) });
|
|
101
105
|
export const AudioClipDoc = Schema.Struct({
|
|
102
106
|
kind: Schema.Literal("audio"),
|
|
103
107
|
...placement,
|
|
@@ -110,6 +114,8 @@ export const AudioClipDoc = Schema.Struct({
|
|
|
110
114
|
/** Frames. */
|
|
111
115
|
fadeIn: Frames,
|
|
112
116
|
fadeOut: Frames,
|
|
117
|
+
/** Its words, when it plays narration: a player can show what is being said. */
|
|
118
|
+
voice: Schema.optionalKey(VoiceDoc),
|
|
113
119
|
});
|
|
114
120
|
export const ClipDoc = Schema.Union([SceneClipDoc, VideoClipDoc, ImageClipDoc, AudioClipDoc]);
|
|
115
121
|
// ---------------------------------------------------------------- transitions
|
package/dist/doc/from-plan.d.ts
CHANGED
|
@@ -106,13 +106,9 @@ export declare const filmDocOf: (plan: FilmPlan, background: string, scenes: rea
|
|
|
106
106
|
readonly fit: "cover" | "contain";
|
|
107
107
|
readonly blend?: "multiply" | "screen" | "overlay" | "soft-light" | "color-dodge" | "normal" | undefined;
|
|
108
108
|
} | {
|
|
109
|
-
readonly asset: string;
|
|
110
109
|
readonly in: number;
|
|
111
110
|
readonly out: number;
|
|
112
|
-
readonly
|
|
113
|
-
readonly gain: number;
|
|
114
|
-
readonly fadeIn: number;
|
|
115
|
-
readonly fadeOut: number;
|
|
111
|
+
readonly kind: "audio";
|
|
116
112
|
readonly id: string;
|
|
117
113
|
readonly start: number;
|
|
118
114
|
readonly duration: number;
|
|
@@ -121,7 +117,18 @@ export declare const filmDocOf: (plan: FilmPlan, background: string, scenes: rea
|
|
|
121
117
|
readonly file: string;
|
|
122
118
|
readonly line: number;
|
|
123
119
|
} | null;
|
|
124
|
-
readonly
|
|
120
|
+
readonly asset: string;
|
|
121
|
+
readonly speed: number;
|
|
122
|
+
readonly gain: number;
|
|
123
|
+
readonly fadeIn: number;
|
|
124
|
+
readonly fadeOut: number;
|
|
125
|
+
readonly voice?: {
|
|
126
|
+
readonly words: readonly {
|
|
127
|
+
readonly text: string;
|
|
128
|
+
readonly start: number;
|
|
129
|
+
readonly end: number;
|
|
130
|
+
}[];
|
|
131
|
+
} | undefined;
|
|
125
132
|
})[];
|
|
126
133
|
readonly transitions: readonly ({
|
|
127
134
|
readonly from: string;
|
package/dist/doc/from-plan.js
CHANGED
|
@@ -38,10 +38,10 @@ function clipDoc(clip, ids) {
|
|
|
38
38
|
return { kind: "video", ...placed, asset: s.asset.name, in: s.in, out: s.out, speed: s.speed, reverse: s.reverse, freeze: s.freeze, fit: s.fit, opacity: clip.opacity, ...blended };
|
|
39
39
|
case "image":
|
|
40
40
|
return { kind: "image", ...placed, asset: s.asset.name, fit: s.fit, opacity: clip.opacity, ...blended };
|
|
41
|
-
case "audio":
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
case "audio": {
|
|
42
|
+
const voice = s.voice === null ? {} : { voice: { words: s.voice.words.map((w) => ({ text: w.text, start: w.start, end: w.end })) } };
|
|
43
|
+
return { kind: "audio", ...placed, asset: s.asset.name, in: s.in, out: s.out, speed: s.speed, gain: s.gain, fadeIn: s.fadeIn, fadeOut: s.fadeOut, ...voice };
|
|
44
|
+
}
|
|
45
45
|
case "inline":
|
|
46
46
|
throw new Refusal(clip.id, `Clip "${clip.id}" is inline markup, which film.json can't hold; make it a scene in scenes/.`);
|
|
47
47
|
}
|
package/dist/doc/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { FilmDoc, FilmFacts, TrackDoc, ClipDoc, SceneClipDoc, VideoClipDoc, ImageClipDoc, AudioClipDoc, TransitionDoc, FadeDoc, SlideDoc, MorphDoc, SceneDoc, AssetDoc, Origin, Id, EaseName, Fit, Direction, FILM_FORMAT, FILM_VERSION, formatFilmDoc, } from "./film-doc.js";
|
|
1
|
+
export { FilmDoc, FilmFacts, TrackDoc, ClipDoc, SceneClipDoc, VideoClipDoc, ImageClipDoc, AudioClipDoc, VoiceDoc, WordDoc, TransitionDoc, FadeDoc, SlideDoc, MorphDoc, SceneDoc, AssetDoc, Origin, Id, EaseName, Fit, Direction, FILM_FORMAT, FILM_VERSION, formatFilmDoc, } from "./film-doc.js";
|
|
2
2
|
export { decodeFilmDoc, parseFilmDoc, filmDocProblems } from "./check.js";
|
|
3
3
|
export { assembleFilm, assetsOf, assetLookup, sceneFilmDoc, type SceneModules } from "./assemble.js";
|
|
4
4
|
export { filmDocOf, type ProjectScene } from "./from-plan.js";
|
package/dist/doc/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @tongue-core/project/doc: film.json. Its schema and types (what timeline UIs program against), the
|
|
2
2
|
// checks that it holds together, turning a planned film into it, and turning it back into a film.
|
|
3
3
|
// Light on purpose: no compiler, nothing that touches files.
|
|
4
|
-
export { FilmDoc, FilmFacts, TrackDoc, ClipDoc, SceneClipDoc, VideoClipDoc, ImageClipDoc, AudioClipDoc, TransitionDoc, FadeDoc, SlideDoc, MorphDoc, SceneDoc, AssetDoc, Origin, Id, EaseName, Fit, Direction, FILM_FORMAT, FILM_VERSION, formatFilmDoc, } from "./film-doc.js";
|
|
4
|
+
export { FilmDoc, FilmFacts, TrackDoc, ClipDoc, SceneClipDoc, VideoClipDoc, ImageClipDoc, AudioClipDoc, VoiceDoc, WordDoc, TransitionDoc, FadeDoc, SlideDoc, MorphDoc, SceneDoc, AssetDoc, Origin, Id, EaseName, Fit, Direction, FILM_FORMAT, FILM_VERSION, formatFilmDoc, } from "./film-doc.js";
|
|
5
5
|
export { decodeFilmDoc, parseFilmDoc, filmDocProblems } from "./check.js";
|
|
6
6
|
export { assembleFilm, assetsOf, assetLookup, sceneFilmDoc } from "./assemble.js";
|
|
7
7
|
export { filmDocOf } from "./from-plan.js";
|
package/dist/doc/plan-doc.d.ts
CHANGED
|
@@ -100,13 +100,9 @@ export declare const planFilmDoc: (doc: {
|
|
|
100
100
|
readonly fit: "cover" | "contain";
|
|
101
101
|
readonly blend?: "multiply" | "screen" | "overlay" | "soft-light" | "color-dodge" | "normal" | undefined;
|
|
102
102
|
} | {
|
|
103
|
-
readonly asset: string;
|
|
104
103
|
readonly in: number;
|
|
105
104
|
readonly out: number;
|
|
106
|
-
readonly
|
|
107
|
-
readonly gain: number;
|
|
108
|
-
readonly fadeIn: number;
|
|
109
|
-
readonly fadeOut: number;
|
|
105
|
+
readonly kind: "audio";
|
|
110
106
|
readonly id: string;
|
|
111
107
|
readonly start: number;
|
|
112
108
|
readonly duration: number;
|
|
@@ -115,7 +111,18 @@ export declare const planFilmDoc: (doc: {
|
|
|
115
111
|
readonly file: string;
|
|
116
112
|
readonly line: number;
|
|
117
113
|
} | null;
|
|
118
|
-
readonly
|
|
114
|
+
readonly asset: string;
|
|
115
|
+
readonly speed: number;
|
|
116
|
+
readonly gain: number;
|
|
117
|
+
readonly fadeIn: number;
|
|
118
|
+
readonly fadeOut: number;
|
|
119
|
+
readonly voice?: {
|
|
120
|
+
readonly words: readonly {
|
|
121
|
+
readonly text: string;
|
|
122
|
+
readonly start: number;
|
|
123
|
+
readonly end: number;
|
|
124
|
+
}[];
|
|
125
|
+
} | undefined;
|
|
119
126
|
})[];
|
|
120
127
|
readonly transitions: readonly ({
|
|
121
128
|
readonly from: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tongue-core/project",
|
|
3
|
-
"version": "0.1.0-rc.
|
|
3
|
+
"version": "0.1.0-rc.5",
|
|
4
4
|
"description": "Film projects: their shape, building one into film.json and a bundle per scene, film.json's schema and checks, and turning it back into a film. No Bun, Node or ffmpeg: runs in Bun, browsers and Workers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"README.md"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@tongue-core/film": "0.1.0-rc.
|
|
43
|
+
"@tongue-core/film": "0.1.0-rc.5",
|
|
44
44
|
"sucrase": "3.35.1"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|