@pixerate/editor 0.159.0 → 0.161.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/dist/{chunk-VKF3PWKR.cjs → chunk-3OSXHLIT.cjs} +259 -28
- package/dist/chunk-6DM3PUQD.cjs +767 -0
- package/dist/{chunk-IQ6KKXOU.js → chunk-YN4AYYBJ.js} +243 -12
- package/dist/chunk-ZGOHKS3X.js +767 -0
- package/dist/effects/index.cjs +16 -767
- package/dist/effects/index.js +5 -756
- package/dist/image-editor/controller.d.cts +7 -0
- package/dist/image-editor/controller.d.ts +7 -0
- package/dist/image-editor/index.cjs +49 -10
- package/dist/image-editor/index.js +48 -9
- package/dist/image-editor/layers/transform-ui.d.cts +14 -6
- package/dist/image-editor/layers/transform-ui.d.ts +14 -6
- package/dist/paint-editor/index.cjs +2 -2
- package/dist/paint-editor/index.js +1 -1
- package/dist/video-editor/audio.d.cts +9 -0
- package/dist/video-editor/audio.d.ts +9 -0
- package/dist/video-editor/check.d.cts +1 -1
- package/dist/video-editor/check.d.ts +1 -1
- package/dist/video-editor/controller.d.cts +47 -0
- package/dist/video-editor/controller.d.ts +47 -0
- package/dist/video-editor/dialogue-tools.d.cts +19 -0
- package/dist/video-editor/dialogue-tools.d.ts +19 -0
- package/dist/video-editor/effect-authoring.d.cts +54 -0
- package/dist/video-editor/effect-authoring.d.ts +54 -0
- package/dist/video-editor/evaluate.d.cts +11 -0
- package/dist/video-editor/evaluate.d.ts +11 -0
- package/dist/video-editor/export.d.cts +7 -1
- package/dist/video-editor/export.d.ts +7 -1
- package/dist/video-editor/index.cjs +1853 -528
- package/dist/video-editor/index.d.cts +7 -0
- package/dist/video-editor/index.d.ts +7 -0
- package/dist/video-editor/index.js +1512 -187
- package/dist/video-editor/lut.d.cts +12 -2
- package/dist/video-editor/lut.d.ts +12 -2
- package/dist/video-editor/mask.d.cts +48 -0
- package/dist/video-editor/mask.d.ts +48 -0
- package/dist/video-editor/mix.d.cts +107 -0
- package/dist/video-editor/mix.d.ts +107 -0
- package/dist/video-editor/music-tools.d.cts +19 -0
- package/dist/video-editor/music-tools.d.ts +19 -0
- package/dist/video-editor/parse.d.cts +3 -1
- package/dist/video-editor/parse.d.ts +3 -1
- package/dist/video-editor/plan.d.cts +75 -0
- package/dist/video-editor/plan.d.ts +75 -0
- package/dist/video-editor/render.d.cts +1 -1
- package/dist/video-editor/render.d.ts +1 -1
- package/dist/video-editor/timeline.d.cts +2 -0
- package/dist/video-editor/timeline.d.ts +2 -0
- package/dist/video-editor/tools.d.cts +90 -0
- package/dist/video-editor/tools.d.ts +90 -0
- package/dist/video-editor/transcript-controller.d.cts +106 -0
- package/dist/video-editor/transcript-controller.d.ts +106 -0
- package/dist/video-editor/transcript.d.cts +40 -0
- package/dist/video-editor/transcript.d.ts +40 -0
- package/dist/video-editor/types.d.cts +62 -2
- package/dist/video-editor/types.d.ts +62 -2
- package/dist/video-editor/ui.d.cts +21 -1
- package/dist/video-editor/ui.d.ts +21 -1
- package/package.json +1 -1
- package/skills/README.md +2 -0
- package/skills/pixerate-bgm-alignment/SKILL.md +82 -0
- package/skills/pixerate-talking-head-edit/SKILL.md +80 -0
- package/skills/pixerate-video-editor/SKILL.md +40 -2
|
@@ -85,3 +85,43 @@ export declare function videoWordsRange(words: readonly VideoTimelineWord[], a:
|
|
|
85
85
|
export declare function videoTranscriptEdit(assetId: string, text: string): VideoEdit;
|
|
86
86
|
/** The word playing at a timeline time, as its index in `words`, or -1. */
|
|
87
87
|
export declare function videoWordAt(words: readonly VideoTimelineWord[], time: number): number;
|
|
88
|
+
export interface VideoRepetitionOptions {
|
|
89
|
+
/** Longest phrase to look for repeated (words, default 3). */
|
|
90
|
+
maxPhrase?: number;
|
|
91
|
+
/** Longest gap between a phrase and its repeat that still counts as a stutter (ms, default 1000). */
|
|
92
|
+
maxGap?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Words said twice in a row ("I I think", "we should we should"), as timeline ranges covering the
|
|
96
|
+
* first saying and the gap up to the repeat, so cutting them leaves the phrase said once. Longer
|
|
97
|
+
* phrases are tried first; "I I I" gives two ranges. Some repeats are meant ("very very"): check them.
|
|
98
|
+
*/
|
|
99
|
+
export declare function findVideoRepetitions(words: readonly VideoTimelineWord[], options?: VideoRepetitionOptions): VideoTranscriptRange[];
|
|
100
|
+
export type VideoDisfluencyKind = 'filler' | 'pause' | 'repetition';
|
|
101
|
+
export declare const VIDEO_DISFLUENCY_KINDS: readonly ["filler", "pause", "repetition"];
|
|
102
|
+
/** Something to tidy out of speech: where it is (timeline ms), what kind and what was said. */
|
|
103
|
+
export interface VideoDisfluency extends VideoTranscriptRange {
|
|
104
|
+
kind: VideoDisfluencyKind;
|
|
105
|
+
/** Indexes in the word list of the first and last word it covers (for a pause: the words either side). */
|
|
106
|
+
words: [number, number];
|
|
107
|
+
}
|
|
108
|
+
export interface VideoDisfluencyOptions {
|
|
109
|
+
/** Which kinds to look for (default all). */
|
|
110
|
+
kinds?: readonly VideoDisfluencyKind[];
|
|
111
|
+
/** Filler words and phrases (default `VIDEO_DEFAULT_FILLERS`). */
|
|
112
|
+
fillers?: readonly string[];
|
|
113
|
+
/** How pauses are measured (default: over 700 ms, keeping 150 ms of breath either side). */
|
|
114
|
+
pauses?: VideoPauseOptions;
|
|
115
|
+
repetitions?: VideoRepetitionOptions;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Fillers, long pauses and stutters in one pass, in time order, each with the words it covers, so
|
|
119
|
+
* a transcript can mark them and an agent can review them before cutting. Overlapping finds are
|
|
120
|
+
* all kept (a filler inside a repetition): `mergeVideoRanges` joins them when they are cut.
|
|
121
|
+
*/
|
|
122
|
+
export declare function detectVideoDisfluencies(words: readonly VideoTimelineWord[], options?: VideoDisfluencyOptions): VideoDisfluency[];
|
|
123
|
+
/** Cut ranges shrunk by `keep` ms at each end, so a little breath stays either side; ranges that vanish are dropped. */
|
|
124
|
+
export declare function videoCutsWithMargin<T extends {
|
|
125
|
+
from: number;
|
|
126
|
+
to: number;
|
|
127
|
+
}>(ranges: readonly T[], keep: number): T[];
|
|
@@ -160,6 +160,12 @@ export interface VideoGradeLut {
|
|
|
160
160
|
strength?: number;
|
|
161
161
|
/** A label for the look (default the file's TITLE or name). */
|
|
162
162
|
name?: string;
|
|
163
|
+
/**
|
|
164
|
+
* How much of the LUT's change to hold back on skin tones, 0–1 (default 0): at 1 a pixel that
|
|
165
|
+
* looks like skin keeps its graded-but-un-LUT'd colour, so a heavy creative look leaves faces
|
|
166
|
+
* natural. Skin is found by chroma (see `videoSkinToneWeight`), with a soft edge.
|
|
167
|
+
*/
|
|
168
|
+
preserveSkinTones?: number;
|
|
163
169
|
}
|
|
164
170
|
/**
|
|
165
171
|
* Colour correction for a clip's picture (see `VIDEO_GRADE_CONTROLS` for ranges). Applied in a fixed
|
|
@@ -222,6 +228,41 @@ interface VideoClipBase {
|
|
|
222
228
|
transition?: VideoTransition;
|
|
223
229
|
/** Provider effects on the picture, applied in order (see `VideoClipEffect`). */
|
|
224
230
|
effects?: VideoClipEffect[];
|
|
231
|
+
/** A shape that cuts the picture out (see `VideoClipMask`). */
|
|
232
|
+
mask?: VideoClipMask;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* The shape of a clip mask: `rectangle` (with `cornerRadius`), `ellipse`, `linear` (a straight
|
|
236
|
+
* split: what is on the side the angle points away from shows) or `polygon` (`points`).
|
|
237
|
+
*/
|
|
238
|
+
export type VideoMaskShape = 'rectangle' | 'ellipse' | 'linear' | 'polygon';
|
|
239
|
+
export declare const VIDEO_MASK_SHAPES: readonly ["rectangle", "ellipse", "linear", "polygon"];
|
|
240
|
+
/**
|
|
241
|
+
* A parametric mask on a clip's picture: only the inside of the shape shows (the outside with
|
|
242
|
+
* `inverted`). Positions and sizes are fractions of the clip's placed picture (0–1 across its
|
|
243
|
+
* width and height), so the mask moves, scales and turns with the clip.
|
|
244
|
+
*/
|
|
245
|
+
export interface VideoClipMask {
|
|
246
|
+
shape: VideoMaskShape;
|
|
247
|
+
/** Centre of the shape (or a point on a linear split's edge), as fractions of the picture (default 0.5, 0.5). */
|
|
248
|
+
x?: number;
|
|
249
|
+
y?: number;
|
|
250
|
+
/** Size as fractions of the picture's width and height (default 0.5 each; unused by linear). */
|
|
251
|
+
width?: number;
|
|
252
|
+
height?: number;
|
|
253
|
+
/** Degrees clockwise (default 0). For linear, 0 shows the top half. */
|
|
254
|
+
rotation?: number;
|
|
255
|
+
/** Soft edge width, in frame pixels (default 0). */
|
|
256
|
+
feather?: number;
|
|
257
|
+
/** Rectangle corners, as a fraction of half the shorter side (0–1, default 0). */
|
|
258
|
+
cornerRadius?: number;
|
|
259
|
+
/** Show the outside of the shape instead. */
|
|
260
|
+
inverted?: boolean;
|
|
261
|
+
/** For polygon: at least 3 points, as fractions of the picture. */
|
|
262
|
+
points?: {
|
|
263
|
+
x: number;
|
|
264
|
+
y: number;
|
|
265
|
+
}[];
|
|
225
266
|
}
|
|
226
267
|
/**
|
|
227
268
|
* The shape of a sound fade, the same curves ffmpeg's `afade` draws, so previews and exports agree.
|
|
@@ -306,7 +347,26 @@ export interface VideoSequenceClip extends VideoClipBase {
|
|
|
306
347
|
export interface VideoEffectClip extends VideoClipBase, VideoEffectRef {
|
|
307
348
|
type: 'effect';
|
|
308
349
|
}
|
|
309
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Which pictures an adjustment clip changes: `underneath` (every video track below its own, the
|
|
352
|
+
* default, as adjustment layers work in most editors), `all` (the whole frame, tracks above it
|
|
353
|
+
* included) or `track` (only the pictures of `targetTrack`).
|
|
354
|
+
*/
|
|
355
|
+
export type VideoAdjustmentScope = 'underneath' | 'all' | 'track';
|
|
356
|
+
export declare const VIDEO_ADJUSTMENT_SCOPES: readonly ["underneath", "all", "track"];
|
|
357
|
+
/**
|
|
358
|
+
* An adjustment clip: no picture of its own, but while it plays its grade, provider effects and
|
|
359
|
+
* mask apply to the composite of the pictures in its scope (see `VideoAdjustmentScope`). Its
|
|
360
|
+
* opacity (and fades) mix the adjusted picture over the unadjusted one. Lives on a video track.
|
|
361
|
+
*/
|
|
362
|
+
export interface VideoAdjustmentClip extends VideoClipBase {
|
|
363
|
+
type: 'adjustment';
|
|
364
|
+
/** Default `underneath`. */
|
|
365
|
+
scope?: VideoAdjustmentScope;
|
|
366
|
+
/** For scope `track`: the id of the track whose pictures it changes. */
|
|
367
|
+
targetTrack?: string;
|
|
368
|
+
}
|
|
369
|
+
export type VideoClip = VideoMediaClip | VideoTextClip | VideoColorClip | VideoSequenceClip | VideoEffectClip | VideoAdjustmentClip;
|
|
310
370
|
export type VideoClipType = VideoClip['type'];
|
|
311
371
|
/**
|
|
312
372
|
* How a clip is placed where others already are: `refuse` an overlap (the default), `overwrite`
|
|
@@ -315,7 +375,7 @@ export type VideoClipType = VideoClip['type'];
|
|
|
315
375
|
*/
|
|
316
376
|
export type VideoPlacementMode = 'refuse' | 'overwrite' | 'insert';
|
|
317
377
|
export declare const VIDEO_PLACEMENT_MODES: readonly ["refuse", "overwrite", "insert"];
|
|
318
|
-
export declare const VIDEO_CLIP_TYPES: readonly ["media", "text", "color", "sequence", "effect"];
|
|
378
|
+
export declare const VIDEO_CLIP_TYPES: readonly ["media", "text", "color", "sequence", "effect", "adjustment"];
|
|
319
379
|
export interface VideoMarker {
|
|
320
380
|
id: string;
|
|
321
381
|
time: number;
|
|
@@ -160,6 +160,12 @@ export interface VideoGradeLut {
|
|
|
160
160
|
strength?: number;
|
|
161
161
|
/** A label for the look (default the file's TITLE or name). */
|
|
162
162
|
name?: string;
|
|
163
|
+
/**
|
|
164
|
+
* How much of the LUT's change to hold back on skin tones, 0–1 (default 0): at 1 a pixel that
|
|
165
|
+
* looks like skin keeps its graded-but-un-LUT'd colour, so a heavy creative look leaves faces
|
|
166
|
+
* natural. Skin is found by chroma (see `videoSkinToneWeight`), with a soft edge.
|
|
167
|
+
*/
|
|
168
|
+
preserveSkinTones?: number;
|
|
163
169
|
}
|
|
164
170
|
/**
|
|
165
171
|
* Colour correction for a clip's picture (see `VIDEO_GRADE_CONTROLS` for ranges). Applied in a fixed
|
|
@@ -222,6 +228,41 @@ interface VideoClipBase {
|
|
|
222
228
|
transition?: VideoTransition;
|
|
223
229
|
/** Provider effects on the picture, applied in order (see `VideoClipEffect`). */
|
|
224
230
|
effects?: VideoClipEffect[];
|
|
231
|
+
/** A shape that cuts the picture out (see `VideoClipMask`). */
|
|
232
|
+
mask?: VideoClipMask;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* The shape of a clip mask: `rectangle` (with `cornerRadius`), `ellipse`, `linear` (a straight
|
|
236
|
+
* split: what is on the side the angle points away from shows) or `polygon` (`points`).
|
|
237
|
+
*/
|
|
238
|
+
export type VideoMaskShape = 'rectangle' | 'ellipse' | 'linear' | 'polygon';
|
|
239
|
+
export declare const VIDEO_MASK_SHAPES: readonly ["rectangle", "ellipse", "linear", "polygon"];
|
|
240
|
+
/**
|
|
241
|
+
* A parametric mask on a clip's picture: only the inside of the shape shows (the outside with
|
|
242
|
+
* `inverted`). Positions and sizes are fractions of the clip's placed picture (0–1 across its
|
|
243
|
+
* width and height), so the mask moves, scales and turns with the clip.
|
|
244
|
+
*/
|
|
245
|
+
export interface VideoClipMask {
|
|
246
|
+
shape: VideoMaskShape;
|
|
247
|
+
/** Centre of the shape (or a point on a linear split's edge), as fractions of the picture (default 0.5, 0.5). */
|
|
248
|
+
x?: number;
|
|
249
|
+
y?: number;
|
|
250
|
+
/** Size as fractions of the picture's width and height (default 0.5 each; unused by linear). */
|
|
251
|
+
width?: number;
|
|
252
|
+
height?: number;
|
|
253
|
+
/** Degrees clockwise (default 0). For linear, 0 shows the top half. */
|
|
254
|
+
rotation?: number;
|
|
255
|
+
/** Soft edge width, in frame pixels (default 0). */
|
|
256
|
+
feather?: number;
|
|
257
|
+
/** Rectangle corners, as a fraction of half the shorter side (0–1, default 0). */
|
|
258
|
+
cornerRadius?: number;
|
|
259
|
+
/** Show the outside of the shape instead. */
|
|
260
|
+
inverted?: boolean;
|
|
261
|
+
/** For polygon: at least 3 points, as fractions of the picture. */
|
|
262
|
+
points?: {
|
|
263
|
+
x: number;
|
|
264
|
+
y: number;
|
|
265
|
+
}[];
|
|
225
266
|
}
|
|
226
267
|
/**
|
|
227
268
|
* The shape of a sound fade, the same curves ffmpeg's `afade` draws, so previews and exports agree.
|
|
@@ -306,7 +347,26 @@ export interface VideoSequenceClip extends VideoClipBase {
|
|
|
306
347
|
export interface VideoEffectClip extends VideoClipBase, VideoEffectRef {
|
|
307
348
|
type: 'effect';
|
|
308
349
|
}
|
|
309
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Which pictures an adjustment clip changes: `underneath` (every video track below its own, the
|
|
352
|
+
* default, as adjustment layers work in most editors), `all` (the whole frame, tracks above it
|
|
353
|
+
* included) or `track` (only the pictures of `targetTrack`).
|
|
354
|
+
*/
|
|
355
|
+
export type VideoAdjustmentScope = 'underneath' | 'all' | 'track';
|
|
356
|
+
export declare const VIDEO_ADJUSTMENT_SCOPES: readonly ["underneath", "all", "track"];
|
|
357
|
+
/**
|
|
358
|
+
* An adjustment clip: no picture of its own, but while it plays its grade, provider effects and
|
|
359
|
+
* mask apply to the composite of the pictures in its scope (see `VideoAdjustmentScope`). Its
|
|
360
|
+
* opacity (and fades) mix the adjusted picture over the unadjusted one. Lives on a video track.
|
|
361
|
+
*/
|
|
362
|
+
export interface VideoAdjustmentClip extends VideoClipBase {
|
|
363
|
+
type: 'adjustment';
|
|
364
|
+
/** Default `underneath`. */
|
|
365
|
+
scope?: VideoAdjustmentScope;
|
|
366
|
+
/** For scope `track`: the id of the track whose pictures it changes. */
|
|
367
|
+
targetTrack?: string;
|
|
368
|
+
}
|
|
369
|
+
export type VideoClip = VideoMediaClip | VideoTextClip | VideoColorClip | VideoSequenceClip | VideoEffectClip | VideoAdjustmentClip;
|
|
310
370
|
export type VideoClipType = VideoClip['type'];
|
|
311
371
|
/**
|
|
312
372
|
* How a clip is placed where others already are: `refuse` an overlap (the default), `overwrite`
|
|
@@ -315,7 +375,7 @@ export type VideoClipType = VideoClip['type'];
|
|
|
315
375
|
*/
|
|
316
376
|
export type VideoPlacementMode = 'refuse' | 'overwrite' | 'insert';
|
|
317
377
|
export declare const VIDEO_PLACEMENT_MODES: readonly ["refuse", "overwrite", "insert"];
|
|
318
|
-
export declare const VIDEO_CLIP_TYPES: readonly ["media", "text", "color", "sequence", "effect"];
|
|
378
|
+
export declare const VIDEO_CLIP_TYPES: readonly ["media", "text", "color", "sequence", "effect", "adjustment"];
|
|
319
379
|
export interface VideoMarker {
|
|
320
380
|
id: string;
|
|
321
381
|
time: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { VideoEdit } from './edit.cjs';
|
|
2
2
|
import { type VideoKeyframeProperty } from './keyframes.cjs';
|
|
3
|
-
import type { VideoClipAnimationEffect, VideoTransitionType, VideoAsset, VideoAssetKind, VideoBlendMode, VideoClip, VideoFadeCurve, VideoGradeLut, VideoPlacementMode, VideoProject, VideoSequence } from './types.cjs';
|
|
3
|
+
import type { VideoAdjustmentScope, VideoClipMask, VideoMaskShape, VideoClipAnimationEffect, VideoTransitionType, VideoAsset, VideoAssetKind, VideoBlendMode, VideoClip, VideoFadeCurve, VideoGradeLut, VideoPlacementMode, VideoProject, VideoSequence } from './types.cjs';
|
|
4
4
|
export interface VideoRulerTick {
|
|
5
5
|
time: number;
|
|
6
6
|
/** Pixels from the timeline's left edge. */
|
|
@@ -125,3 +125,23 @@ export declare function videoKeyframeToggleEdit(project: VideoProject, clipId: s
|
|
|
125
125
|
* `null`. Clips without a grade change are left out; one `controller.apply` makes it one undo step.
|
|
126
126
|
*/
|
|
127
127
|
export declare function videoLutEdits(project: VideoProject, clips: readonly string[], lut: VideoGradeLut | null): VideoEdit[];
|
|
128
|
+
/** Labels for adjustment scopes, for inspectors. */
|
|
129
|
+
export declare const VIDEO_ADJUSTMENT_SCOPE_LABELS: Readonly<Record<VideoAdjustmentScope, string>>;
|
|
130
|
+
/** Labels for mask shapes, for inspectors. */
|
|
131
|
+
export declare const VIDEO_MASK_SHAPE_LABELS: Readonly<Record<VideoMaskShape, string>>;
|
|
132
|
+
/** What a clip is, for an inspector's heading. */
|
|
133
|
+
export declare const videoClipHeading: (clip: Pick<VideoClip, "type">) => string;
|
|
134
|
+
/**
|
|
135
|
+
* The edits that add an adjustment clip at `time` (default 3 s long) over everything: on the top
|
|
136
|
+
* track when it is a video track free there, else on a new video track added at the top. The clip
|
|
137
|
+
* starts with no look; give it a grade, effects or a mask.
|
|
138
|
+
*/
|
|
139
|
+
export declare function videoAddAdjustmentEdits(project: VideoProject, time: number, options?: {
|
|
140
|
+
duration?: number;
|
|
141
|
+
id?: string;
|
|
142
|
+
grade?: VideoClip['grade'];
|
|
143
|
+
}): VideoEdit[];
|
|
144
|
+
/** The edit that sets (or with `null` removes) a clip's mask. */
|
|
145
|
+
export declare function videoMaskEdit(clip: string, mask: VideoClipMask | null): VideoEdit;
|
|
146
|
+
/** The edits that set how much clips' LUTs hold back on skin (0 turns it off); clips without a LUT are skipped. */
|
|
147
|
+
export declare function videoSkinProtectionEdits(project: VideoProject, clips: readonly string[], amount: number): VideoEdit[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { VideoEdit } from './edit.js';
|
|
2
2
|
import { type VideoKeyframeProperty } from './keyframes.js';
|
|
3
|
-
import type { VideoClipAnimationEffect, VideoTransitionType, VideoAsset, VideoAssetKind, VideoBlendMode, VideoClip, VideoFadeCurve, VideoGradeLut, VideoPlacementMode, VideoProject, VideoSequence } from './types.js';
|
|
3
|
+
import type { VideoAdjustmentScope, VideoClipMask, VideoMaskShape, VideoClipAnimationEffect, VideoTransitionType, VideoAsset, VideoAssetKind, VideoBlendMode, VideoClip, VideoFadeCurve, VideoGradeLut, VideoPlacementMode, VideoProject, VideoSequence } from './types.js';
|
|
4
4
|
export interface VideoRulerTick {
|
|
5
5
|
time: number;
|
|
6
6
|
/** Pixels from the timeline's left edge. */
|
|
@@ -125,3 +125,23 @@ export declare function videoKeyframeToggleEdit(project: VideoProject, clipId: s
|
|
|
125
125
|
* `null`. Clips without a grade change are left out; one `controller.apply` makes it one undo step.
|
|
126
126
|
*/
|
|
127
127
|
export declare function videoLutEdits(project: VideoProject, clips: readonly string[], lut: VideoGradeLut | null): VideoEdit[];
|
|
128
|
+
/** Labels for adjustment scopes, for inspectors. */
|
|
129
|
+
export declare const VIDEO_ADJUSTMENT_SCOPE_LABELS: Readonly<Record<VideoAdjustmentScope, string>>;
|
|
130
|
+
/** Labels for mask shapes, for inspectors. */
|
|
131
|
+
export declare const VIDEO_MASK_SHAPE_LABELS: Readonly<Record<VideoMaskShape, string>>;
|
|
132
|
+
/** What a clip is, for an inspector's heading. */
|
|
133
|
+
export declare const videoClipHeading: (clip: Pick<VideoClip, "type">) => string;
|
|
134
|
+
/**
|
|
135
|
+
* The edits that add an adjustment clip at `time` (default 3 s long) over everything: on the top
|
|
136
|
+
* track when it is a video track free there, else on a new video track added at the top. The clip
|
|
137
|
+
* starts with no look; give it a grade, effects or a mask.
|
|
138
|
+
*/
|
|
139
|
+
export declare function videoAddAdjustmentEdits(project: VideoProject, time: number, options?: {
|
|
140
|
+
duration?: number;
|
|
141
|
+
id?: string;
|
|
142
|
+
grade?: VideoClip['grade'];
|
|
143
|
+
}): VideoEdit[];
|
|
144
|
+
/** The edit that sets (or with `null` removes) a clip's mask. */
|
|
145
|
+
export declare function videoMaskEdit(clip: string, mask: VideoClipMask | null): VideoEdit;
|
|
146
|
+
/** The edits that set how much clips' LUTs hold back on skin (0 turns it off); clips without a LUT are skipped. */
|
|
147
|
+
export declare function videoSkinProtectionEdits(project: VideoProject, clips: readonly string[], amount: number): VideoEdit[];
|
package/package.json
CHANGED
package/skills/README.md
CHANGED
|
@@ -18,6 +18,8 @@ that uses the tools can load the matching skill.
|
|
|
18
18
|
| [`pixerate-paint-editor`](pixerate-paint-editor/SKILL.md) | Natural-media painting: paper and grain, dry-media brushes, the brush library, strokes as data, pigment mixing. |
|
|
19
19
|
| [`pixerate-animation-editor`](pixerate-animation-editor/SKILL.md) | Vector animation: shots, commands, timing, Flair and Lottie. |
|
|
20
20
|
| [`pixerate-video-editor`](pixerate-video-editor/SKILL.md) | Non-linear video editing: tracks, clips, transitions, export. |
|
|
21
|
+
| [`pixerate-talking-head-edit`](pixerate-talking-head-edit/SKILL.md) | Talking-head cleanup by transcript: fillers, long pauses and stutters found in one pass and cut as one plan reviewed before it applies. |
|
|
22
|
+
| [`pixerate-bgm-alignment`](pixerate-bgm-alignment/SKILL.md) | Background music: beats and cuts on the beat, ducking under speech, loudness in LUFS. |
|
|
21
23
|
| [`pixerate-generation`](pixerate-generation/SKILL.md) | Planning, estimating and running paid media generation. |
|
|
22
24
|
| [`pixerate-parameters`](pixerate-parameters/SKILL.md) | Effect parameters, presets and keyframes. |
|
|
23
25
|
| [`pixerate-tokens`](pixerate-tokens/SKILL.md) | Design tokens: collections, modes, variables and aliases, through the whole-set document tools. |
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixerate-bgm-alignment
|
|
3
|
+
description: How to work with background music in the Pixerate video editor - finding a music track's tempo and beats, proposing cuts snapped to the beat as an edit plan for review, ducking music under speech with eased volume keyframes, measuring loudness in LUFS and normalising clips to streaming, podcast or broadcast targets, and shaping music outros. Use when asked to cut to the music, sync edits to a beat, lower music under dialogue, balance or normalise levels, or when find_video_beats, duck_video_music or normalize_video_loudness are available.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pixerate music and the mix
|
|
7
|
+
|
|
8
|
+
Music sits on its own audio track under the picture and dialogue. Three jobs make it work:
|
|
9
|
+
**cutting to it** (cuts that land on beats feel deliberate), **ducking it** (dipping it under
|
|
10
|
+
speech so words stay clear) and **levelling it** (every clip at a consistent loudness, the mix
|
|
11
|
+
at the delivery target). The tools here measure the sound itself, from the peaks the editor
|
|
12
|
+
already decodes for waveforms, so the numbers match what the timeline shows.
|
|
13
|
+
|
|
14
|
+
Loudness is in **LUFS** (ITU-R BS.1770, gated): what streaming services, podcasts and
|
|
15
|
+
broadcasters measure. -14 LUFS for streaming and social, -16 for podcasts, -23 for EBU R128
|
|
16
|
+
broadcast. Peaks in dBFS should stay under -1.
|
|
17
|
+
|
|
18
|
+
This skill works with the video editor's own tools (`pixerate-video-editor`): tracks, clips,
|
|
19
|
+
`set_video_keyframes`, `update_video_clip` fades, `apply_video_edit_plan`, `export_video_ffmpeg`
|
|
20
|
+
loudness. See `pixerate-agent-tools` for errors and undo.
|
|
21
|
+
|
|
22
|
+
## Working method
|
|
23
|
+
|
|
24
|
+
1. **Find the music.** `get_video_project`: the music clip is usually on its own audio track.
|
|
25
|
+
Turn that track's `syncLocked` off (`update_video_track`) so ripple cuts in the dialogue do not
|
|
26
|
+
cut the music.
|
|
27
|
+
2. **Find the beat.** `find_video_beats` with `clip` (timeline times) returns the `bpm`, a steady
|
|
28
|
+
`beats` grid and the `onsets` (each hit). If `bpm` is null the music has no steady pulse:
|
|
29
|
+
cut on the strongest onsets instead.
|
|
30
|
+
3. **Cut on the beat.** `plan_video_beat_snap` with `music` (or `beats`) and the picture
|
|
31
|
+
`track` proposes rolling each cut to the nearest beat within `tolerance` (default 150 ms) as
|
|
32
|
+
one plan; it lists cuts it left (no beat near, already on one, not enough media). Show the
|
|
33
|
+
plan, then `apply_video_edit_plan`.
|
|
34
|
+
4. **Duck under speech.** Once dialogue is final, `duck_video_music` with the music clips:
|
|
35
|
+
speech comes from the transcript (or from the dialogue track's sound with
|
|
36
|
+
`speech: "audio"`), and each music clip gets eased volume keyframes dipping `duck_db` under it.
|
|
37
|
+
5. **Level.** `measure_video_loudness` on dialogue and music clips; `normalize_video_loudness`
|
|
38
|
+
sets clip volumes so each plays at a target (dialogue at -16 to -14 LUFS; music beds lower,
|
|
39
|
+
around -24 to -20 under speech). Normalise before ducking: ducking keys are relative to the
|
|
40
|
+
clip's volume when it is applied.
|
|
41
|
+
6. **Finish.** A music bed ends on a fade: `update_video_clip` `fadeOut` 2000-4000 ms with
|
|
42
|
+
`fadeOutCurve` `exponential` (natural to silence) or `s-curve`. For delivery, export with
|
|
43
|
+
two-pass loudness (`export_video_loudness_measure`, then `export_video_ffmpeg` with
|
|
44
|
+
`loudness.measured`).
|
|
45
|
+
|
|
46
|
+
## Best practices
|
|
47
|
+
|
|
48
|
+
- **Cut on the downbeat for big changes.** Section changes land on the first beat of a bar
|
|
49
|
+
(every 4th beat in 4/4); shot changes inside a section can take any beat. Fast montages cut
|
|
50
|
+
every 1-2 beats, slower pieces every 4-8.
|
|
51
|
+
- **Lead the beat slightly.** A cut a frame or two before the beat reads as on it; the eye takes
|
|
52
|
+
a moment to register a new shot.
|
|
53
|
+
- **Duck by -12 to -18 dB.** -14 dB is a good default; quieter music needs less. An attack of
|
|
54
|
+
150-300 ms and a release of 300-600 ms sound natural; short releases pump.
|
|
55
|
+
- **Keep gaps ducked.** `merge_gap` (default 600 ms) stops the music bobbing up between
|
|
56
|
+
sentences; raise it to 1000-1500 ms for slow, measured speech.
|
|
57
|
+
- **Normalise clips, not the master.** Bring each clip to a sensible level so the mix is
|
|
58
|
+
balanced, then let the export's loudness pass set the final target.
|
|
59
|
+
|
|
60
|
+
## Tool reference
|
|
61
|
+
|
|
62
|
+
| Tool | When and how to use it |
|
|
63
|
+
| --- | --- |
|
|
64
|
+
| `find_video_beats` | Read-only. The tempo (`bpm`, null when the hits do not repeat), a steady `beats` grid and the `onsets` of a `clip` (timeline ms) or `asset` (source ms), optionally between `from` and `to`. `sensitivity` (default 1.5; lower finds more hits), `min_bpm` / `max_bpm` (default 60-200). Decodes the asset the first time. Use the beats for `plan_video_beat_snap`, markers or title timing. |
|
|
65
|
+
| `plan_video_beat_snap` | Proposes rolling each cut on a `track` (default the first video track) to the nearest beat within `tolerance` ms (default 150), with beats from a `music` clip or given as `beats` (timeline ms). Roll edits keep everything else in place. Returns the plan (id, summary, `text`), how many cuts `moved` and the `skipped` ones with a reason. Nothing changes until `apply_video_edit_plan`. |
|
|
66
|
+
| `duck_video_music` | Dips `music` clips under speech with volume keyframes (one undo step): `duck_db` (default -14), `attack` (default 200 ms), `release` (default 400 ms), `merge_gap` (default 600 ms). Speech from the transcript (`speech: "transcript"`, the default when there is one) or from where `dialogue_track`'s sound is above -40 dBFS (`speech: "audio"`). Refuses clips with volume keyframes unless `replace: true`. Returns the speech stretches and each clip's keys. |
|
|
67
|
+
| `measure_video_loudness` | Read-only. Integrated loudness (`lufs`, null for silence) and sample `peakDb` of a `clip` or `asset` stretch, before clip volume, with `toStreaming` (the gain to -14 LUFS that keeps the peak under -1 dBFS). |
|
|
68
|
+
| `normalize_video_loudness` | Sets each of `clips`' volume so it plays at `target` LUFS (default -14) with its peak under `ceiling` (default -1 dBFS) and at most 4x gain (one undo step). Skips silent clips; refuses volume keyframes unless `replace: true`. Returns each clip's `lufs`, `gain`, `gainDb` and `limitedBy` when a cap held it short. |
|
|
69
|
+
|
|
70
|
+
## Pitfalls
|
|
71
|
+
|
|
72
|
+
- **Ducking before the dialogue is final.** Ducking keys are placed at the speech as it is now.
|
|
73
|
+
Clean up and re-time dialogue first, then duck; if speech moves later, duck again with
|
|
74
|
+
`replace: true`.
|
|
75
|
+
- **Normalising a ducked clip.** `normalize_video_loudness` sets a constant volume, which would
|
|
76
|
+
replace ducking keys; it refuses unless `replace: true`. Normalise first, then duck.
|
|
77
|
+
- **Beat grids drift on live music.** A steady grid suits programmed music. For a live band, snap
|
|
78
|
+
to `onsets` (pass them as `beats`) instead of the grid.
|
|
79
|
+
- **Sync-locked music gets cut.** A ripple cut or extract on dialogue cuts every sync-locked
|
|
80
|
+
track, including the music. Turn the music track's `syncLocked` off first.
|
|
81
|
+
- **Peaks, not true peaks.** The tools measure sample peaks; the export's `loudnorm` limits true
|
|
82
|
+
peaks. Leave a decibel of headroom.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixerate-talking-head-edit
|
|
3
|
+
description: How to clean up talking-head, interview, podcast and voiceover video in the Pixerate video editor by its transcript - finding filler words, long pauses and stutters in one pass, reviewing them, proposing the cuts as one edit plan the user previews before it applies, keeping breath around cuts, and checking the result. Use when asked to tighten dialogue, remove ums and ahs, cut dead air, clean up a talking head or make a rough cut of an interview, or when find_video_disfluencies or plan_video_dialogue_cleanup are available.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pixerate talking-head cleanup
|
|
7
|
+
|
|
8
|
+
Spoken media in a video project carries a **transcript**: each word with its start and end in
|
|
9
|
+
the source. The editor maps the words through the clips onto the timeline, so a word's place is
|
|
10
|
+
always where it plays now, however the clips were cut. Cleaning up speech is then a matter of
|
|
11
|
+
finding stretches of the timeline (fillers, long pauses, stutters) and cutting them out on every
|
|
12
|
+
sync-locked track at once, so picture, sound and B-roll stay in sync.
|
|
13
|
+
|
|
14
|
+
Cleanup is **plan first**: propose the cuts as one plan, let the user review it (the editor
|
|
15
|
+
shows the plan with its length change and every stretch it cuts), then apply it as one undo step.
|
|
16
|
+
Never cut a whole interview's disfluencies without a review.
|
|
17
|
+
|
|
18
|
+
This skill works with the video editor's own tools (`pixerate-video-editor`): transcripts,
|
|
19
|
+
`get_video_transcript`, `remove_video_ranges`, `apply_video_edit_plan`, `render_video_frame`.
|
|
20
|
+
See `pixerate-agent-tools` for errors and undo.
|
|
21
|
+
|
|
22
|
+
## Working method
|
|
23
|
+
|
|
24
|
+
1. **Make sure there is a transcript.** `get_video_project` shows which assets have one; if the
|
|
25
|
+
speech has none, ask the host or user for a Whisper-style JSON, `.srt` or `.vtt` file and
|
|
26
|
+
attach it with `set_video_transcript`. Captions without word timings are approximate: cuts
|
|
27
|
+
on them may clip words, so prefer word-timed transcripts.
|
|
28
|
+
2. **Read the speech.** `get_video_transcript` for the text and the word list (the indexes the
|
|
29
|
+
find tool returns refer to it).
|
|
30
|
+
3. **Find what to tidy.** `find_video_disfluencies` lists fillers (um, uh, er, you know, I
|
|
31
|
+
mean…), pauses longer than `min_pause` (default 700 ms, keeping `keep` ms of breath either
|
|
32
|
+
side) and repeated words or phrases ("I I think", "we should we should"), with a total per
|
|
33
|
+
kind and how much time the cuts would remove.
|
|
34
|
+
4. **Review.** Read the list against the transcript. Keep repeats that are meant ("very very"),
|
|
35
|
+
pauses that land a point, and fillers that carry meaning ("like" and "so" are not in the
|
|
36
|
+
defaults for that reason). Note the `from` times of finds to keep.
|
|
37
|
+
5. **Propose.** `plan_video_dialogue_cleanup` with the same options and `exclude` (the `from`
|
|
38
|
+
times to keep) proposes the cuts as one plan; nothing changes yet. Tell the user what it does
|
|
39
|
+
(its `text`: stretches and seconds removed) and ask them to review it in the editor.
|
|
40
|
+
6. **Apply.** Once they agree, `apply_video_edit_plan` with the plan id (or
|
|
41
|
+
`discard_video_edit_plan`). If they edited meanwhile, the plan is re-checked; if it no longer
|
|
42
|
+
applies, find and plan again.
|
|
43
|
+
7. **Check.** `get_video_transcript` again (every time after a cut moved), listen at a few cuts
|
|
44
|
+
with `get_video_frame` (audio gains) and look with `render_video_frame` for jump cuts in the
|
|
45
|
+
picture: cover those with B-roll on a higher track or a slight push-in (`set_video_keyframes`
|
|
46
|
+
`scale` 1 to 1.05).
|
|
47
|
+
|
|
48
|
+
## Best practices
|
|
49
|
+
|
|
50
|
+
- **Breath matters.** Cut pauses down, not out: keep 150-250 ms either side (`keep`) so speech
|
|
51
|
+
does not sound breathless. For fillers and stutters, `margin` 20-60 ms avoids clipping the
|
|
52
|
+
words around a cut when word timings are loose.
|
|
53
|
+
- **Brisk or relaxed.** For social clips and explainers, `min_pause` 500-600 ms; for
|
|
54
|
+
interviews and documentary, 900-1200 ms so thinking pauses stay.
|
|
55
|
+
- **One plan, one undo.** Propose the whole cleanup as one plan rather than many small cuts:
|
|
56
|
+
the user reviews it once and can undo it in one step.
|
|
57
|
+
- **Words cut with their picture.** The cut runs across every unlocked sync-locked track. A
|
|
58
|
+
music bed that should keep playing must have `syncLocked: false` (`update_video_track`)
|
|
59
|
+
before the plan is applied, or it is cut too.
|
|
60
|
+
- **Duck music after cleanup.** Speech has moved, so duck background music once the dialogue
|
|
61
|
+
is final (`duck_video_music`, in `pixerate-bgm-alignment`).
|
|
62
|
+
|
|
63
|
+
## Tool reference
|
|
64
|
+
|
|
65
|
+
| Tool | When and how to use it |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `find_video_disfluencies` | Read-only. Lists fillers, long pauses and stutters in time order as `{ kind, from, to, text, words }` (timeline ms; `words` are the first and last indexes in `get_video_transcript`'s list; for a pause, the words either side), with `totals` per kind and `removable` time once merged. Options: `track`, `kinds` (`filler`, `pause`, `repetition`), `fillers` (your own list), `min_pause` (ms, default 700), `keep` (breath either side of a pause cut, default 150), `max_phrase` (longest repeat checked, default 3 words). Review it before planning. |
|
|
68
|
+
| `plan_video_dialogue_cleanup` | Proposes cutting the finds as one plan for review (nothing changes): the same options as the find tool, plus `exclude` (the `from` times of finds to keep), `margin` (ms left at each end of filler and stutter cuts, default 0) and a `title`. Returns the plan (id, title, summary with the length change, `text`) and a hint. Apply with `apply_video_edit_plan`, or `discard_video_edit_plan`. Fails when nothing is left to cut. |
|
|
69
|
+
|
|
70
|
+
## Pitfalls
|
|
71
|
+
|
|
72
|
+
- **Overlapping finds.** A filler inside a stutter is listed twice; the plan merges the ranges,
|
|
73
|
+
so it is cut once. Do not add the same stretch again through `remove_video_ranges`.
|
|
74
|
+
- **Stale plans.** Applying a plan after other edits re-checks it; if it is refused, run the find
|
|
75
|
+
and plan again rather than applying old times by hand.
|
|
76
|
+
- **Approximate transcripts.** Captions spread words evenly over each cue, so a "filler" may be a
|
|
77
|
+
neighbour's syllable. Check the find's `text` against `get_video_transcript`, and prefer
|
|
78
|
+
word-timed transcripts for cleanup.
|
|
79
|
+
- **Transcripts come from the host.** Speech recognition is the host's job: the editor never sends
|
|
80
|
+
media anywhere. Ask for a transcript rather than guessing words from audio levels.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pixerate-video-editor
|
|
3
|
-
description: How to edit video projects in the Pixerate non-linear video editor through its agent tools - adding video, audio and image assets, building a rough cut on video and audio tracks, inserting, overwriting, moving, trimming, splitting and ripple-deleting clips, slip, slide and roll edits, lift and extract of a time range, razor cuts across tracks, sync-locked tracks, keyframed opacity, volume and transform, closing gaps, titles and colour clips, fades, volume and speed, crossfade, dip and wipe transitions with handles, J and L cuts, markers, checking the project, provider effects (clip effects, effect clips, effect transitions), rendering frames and contact sheets, and exporting an ffmpeg command or a CMX 3600 EDL. Use when video tools such as get_video_project, add_video_clip or edit_video are available, or when asked to cut, trim, assemble, sequence or export footage on a timeline.
|
|
3
|
+
description: How to edit video projects in the Pixerate non-linear video editor through its agent tools - adding video, audio and image assets, building a rough cut on video and audio tracks, inserting, overwriting, moving, trimming, splitting and ripple-deleting clips, slip, slide and roll edits, lift and extract of a time range, razor cuts across tracks, sync-locked tracks, keyframed opacity, volume and transform, closing gaps, titles and colour clips, fades, volume and speed, crossfade, dip and wipe transitions with handles, J and L cuts, markers, checking the project, adjustment clips over tracks, clip masks, skin-tone protected LUTs, edit plans proposed for review before they apply, provider effects (clip effects, effect clips, effect transitions), rendering frames and contact sheets, and exporting an ffmpeg command or a CMX 3600 EDL. Use when video tools such as get_video_project, add_video_clip or edit_video are available, or when asked to cut, trim, assemble, sequence or export footage on a timeline.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Pixerate video editor
|
|
@@ -60,7 +60,13 @@ For errors, namespaced tool names and undo conventions, see `pixerate-agent-tool
|
|
|
60
60
|
`export_video_edl` (one track) for finishing elsewhere. Read the returned notes. For a
|
|
61
61
|
delivery loudness, have the host run `export_video_loudness_measure` first and pass what it
|
|
62
62
|
prints as `loudness.measured`; one pass (`loudness` without `measured`) is fine for a draft.
|
|
63
|
-
10. **
|
|
63
|
+
10. **Plan first when the user should see it.** For anything big or judgement-heavy (a rough cut,
|
|
64
|
+
a cleanup, cutting to music), propose it with `plan_video_edits` (or a `plan_*` tool from
|
|
65
|
+
the dialogue and music skills) instead of applying it: the project does not change, the
|
|
66
|
+
editor shows the plan with its length change and the stretches it cuts, and you apply it
|
|
67
|
+
with `apply_video_edit_plan` once the user agrees (or `discard_video_edit_plan`).
|
|
68
|
+
`list_video_edit_plans` shows what is waiting and whether the project changed since.
|
|
69
|
+
11. **Effects** (only when the host registered an effects provider; `search_effects` says
|
|
64
70
|
`available: false` otherwise): `search_effects` with a `use`, then `describe_effect` for its
|
|
65
71
|
controls, then `apply_effect` (filters and overlays on a clip), `set_video_effect_transition`
|
|
66
72
|
or `add_video_effect_clip` (generators and titles). Tune with `update_effect` and
|
|
@@ -135,6 +141,21 @@ For errors, namespaced tool names and undo conventions, see `pixerate-agent-tool
|
|
|
135
141
|
full strength). A LUT runs after the grade's settings, so correct exposure and white balance
|
|
136
142
|
first; LUTs built for log footage expect a flat picture and look crushed on normal video. Check with `render_video_frame` at a
|
|
137
143
|
few times side by side. Skin tones are the reference: avoid strong `hue` or `tint` on people.
|
|
144
|
+
- **Adjustment clips for looks across shots.** Rather than grading every clip of a scene the
|
|
145
|
+
same, `add_video_adjustment_clip` on a track above them with the look (`grade`, a `preset` at
|
|
146
|
+
an `amount`, or effects with `apply_effect` on the adjustment clip): it changes everything
|
|
147
|
+
underneath while it plays, so trims and new shots pick the look up. Scope `all` includes
|
|
148
|
+
titles and tracks above it; scope `track` limits it to one track. Fade it in and out
|
|
149
|
+
(`fadeIn` / `fadeOut`) to ease a look on, and give it a mask to limit it to part of the frame.
|
|
150
|
+
- **Masks for spot changes.** `set_video_clip_mask` cuts a clip to a shape (`ellipse` for a
|
|
151
|
+
face or a vignette, `rectangle` with `corner_radius` for picture-in-picture, `linear` for a
|
|
152
|
+
split screen or a graduated sky, `polygon` for anything else) with a `feather` of 20-80 px so
|
|
153
|
+
the edge does not show. On an adjustment clip the mask limits the adjustment, so a feathered
|
|
154
|
+
ellipse over a face brightens just the face.
|
|
155
|
+
- **Protect skin under heavy looks.** Creative LUTs push faces orange or green. Give the LUT
|
|
156
|
+
`preserve_skin_tones` (0.5-0.8) in `set_video_lut`, or `set_video_skin_protection` afterwards,
|
|
157
|
+
so skin keeps its colour while the rest takes the look. Skin is found by colour, so warm
|
|
158
|
+
beige props are protected too; check with `render_video_frame`.
|
|
138
159
|
- **Measure, don't eyeball.** Where the host shows a preview, `get_video_scopes` reads the real
|
|
139
160
|
picture: keep `clipped.highlights` under about 1% and `clipped.shadows` under about 2% unless
|
|
140
161
|
the look calls for it, and aim for a mean luma of roughly 0.35-0.55 for ordinary scenes. A
|
|
@@ -219,6 +240,10 @@ For errors, namespaced tool names and undo conventions, see `pixerate-agent-tool
|
|
|
219
240
|
| `delete_video_clips` | Remove `clips`; `ripple: true` pulls later clips up to close the gaps (a ripple delete). |
|
|
220
241
|
| `update_video_clip` | Change properties via `set`: opacity, transform (`x`, `y` px from centre, `scale`, `rotation`), `fit` (contain default for media, cover, fill, none), `animateIn` / `animateOut` (`{ effect: fade, rise, drop, slide-left, slide-right, zoom or pop, duration ms default 500 }`), `grade` (`exposure` stops -3-3, `contrast`, `saturation`, `temperature`, `tint` -1-1, `hue` degrees; replaces the whole grade), `blend` (normal, multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, add), `fadeIn` / `fadeOut`, name; media `volume` (0-4), `muted`, `fadeInCurve` / `fadeOutCurve` (the sound's fade shape: linear, equal-power, s-curve, exponential, logarithmic), `speed` (0.05-20, keeps the source range so the length changes), `asset`; title text and style; colour. `remove` resets to defaults. Not for timing. |
|
|
221
242
|
| `set_video_lut` | Give `clips` (on video tracks) a 3D LUT: `src` a `.cube` file the host can load and ffmpeg can read, `strength` 0-1 (default 1). Reads the file first and fails without changing anything if it cannot be loaded or is not a 3D `.cube`. Keeps the clips' other grade settings; the LUT runs after them. One undo step; returns the LUT's `title` and `size` and each clip's grade. Copies with `copy_video_grade`. |
|
|
243
|
+
| `set_video_skin_protection` | Hold the LUT back on skin tones for `clips` that already have one: `amount` 0-1 (0 turns protection off). Fails for clips without a LUT (add one with `set_video_lut`). One undo step; returns each clip's LUT setting. The preview and frame renders apply it; ffmpeg's `lut3d` cannot, so the export notes it. |
|
|
244
|
+
| `add_video_adjustment_clip` | Add an adjustment clip on a video `track` (`start`, `duration` default 3000 ms): no picture of its own, but its `grade` (or a `preset` at `amount`), effects (`apply_effect` on it) and mask change the pictures in its `scope` while it plays: `underneath` (tracks below it, default), `all` (the whole frame) or `track` with `target_track`. Returns the clip; a hint says when it has nothing to apply yet. Edit it like any clip (`update_video_clip` `grade`, `scope`, `targetTrack`; trims; fades). |
|
|
245
|
+
| `set_video_clip_mask` | Cut a clip's picture to a `shape` (`rectangle`, `ellipse`, `linear`, `polygon` with `points`): `x`, `y` centre and `width`, `height` as fractions of the clip's placed picture (default 0.5 each), `rotation` degrees, `feather` px, `corner_radius` 0-1 (rectangles), `inverted` to keep the outside. Replaces any mask; one undo step; returns the clip. On an adjustment clip it limits the adjustment. ffmpeg exports then need rendered frames. |
|
|
246
|
+
| `remove_video_clip_mask` | Take a clip's mask off (one undo step). Fails if it has none. |
|
|
222
247
|
| `remove_video_lut` | Take the LUT off `clips`' grades, keeping their other settings (one undo step). Fails if none has one. |
|
|
223
248
|
| `apply_video_grade_preset` | Give `clips` (on video tracks) a named look at an `amount` 0-1 (default 1), replacing their grade settings (a LUT stays): warm, cool, punchy, faded, black-and-white, bleach-bypass, day-for-night. One undo step; returns each clip's grade to fine-tune with `update_video_clip`. |
|
|
224
249
|
| `copy_video_grade` | Match shots: give the `to` clips the grade of the `from` clip (one undo step; a source with no grade clears theirs). Returns the grade copied. |
|
|
@@ -231,6 +256,10 @@ For errors, namespaced tool names and undo conventions, see `pixerate-agent-tool
|
|
|
231
256
|
| `close_video_gaps` | Slide clips on a `track` earlier so no gaps remain, from time `from` (default the start). Returns the clips that moved. |
|
|
232
257
|
| `add_video_marker` | Add a marker at `time` with `label`, `color` and optional `id`, for beats, sections or review notes. Returns its id. |
|
|
233
258
|
| `remove_video_marker` | Remove a `marker` by id. |
|
|
259
|
+
| `plan_video_edits` | Propose `ops` (as for `edit_video`) with a `title` (also the undo label), an optional `description` and the `ranges` it cuts, without applying them. Fails, keeping nothing, if they do not apply. Returns the plan: id, summary (`durationBefore`, `durationAfter`, `durationDelta`, `clipsAdded`, `clipsRemoved`, `clipsChanged`, `newIssues`), ranges and a one-line `text`. The editor shows it for review. Follow with `apply_video_edit_plan` or `discard_video_edit_plan`. |
|
|
260
|
+
| `list_video_edit_plans` | The plans waiting for review, oldest first, each with its summary, ranges and `stale` (the project changed since it was made; it is re-checked when applied). |
|
|
261
|
+
| `apply_video_edit_plan` | Apply an open `plan` as one undo step labelled with its title and close it. A stale plan is checked again and refused, changing nothing, if its edits no longer apply. Returns the outcomes, length, issues and `stale`. |
|
|
262
|
+
| `discard_video_edit_plan` | Close an open `plan` without applying it. Returns the plans still open. |
|
|
234
263
|
| `edit_video` | Apply up to 200 ops in order as one all-or-nothing undo step: `set_settings`, `add_asset { asset }`, `update_asset`, `remove_asset`, `add_track { track: { kind, id }, at }`, `update_track`, `remove_track`, `move_track`, `add_clip { track, clip, mode }`, `move_clip { clip, start, track, mode }`, `trim_clip`, `split_clip`, `delete_clips`, `update_clip`, `set_transition`, `slip_clip`, `roll_edit`, `slide_clip`, `lift_range`, `extract_range`, `split_at`, `set_keyframes { clip, property, keys }` (null keys remove), `set_time_remap { clip, keys (clip ms to source ms after the in point; null removes), duration, ripple }`, `close_gaps`, `add_marker { marker: { time, label } }`, `update_marker`, `remove_marker`; other fields match the single tools. `dry_run: true` validates only. The default for a rough cut. |
|
|
235
264
|
| `undo_video` | Undo your last edit (one tool call or one `edit_video` batch). |
|
|
236
265
|
| `redo_video` | Redo the edit you just undid. |
|
|
@@ -268,6 +297,15 @@ The host may add the shared document tools (see `pixerate-agent-tools`). A video
|
|
|
268
297
|
|
|
269
298
|
## Pitfalls
|
|
270
299
|
|
|
300
|
+
- **An adjustment clip changes only tracks below it** (scope `underneath`). Put it on a new top
|
|
301
|
+
track (`add_video_track` with `at: 0`), or use scope `all`. Adjustment clips have no sound and
|
|
302
|
+
are left out of EDLs; ffmpeg exports draw a plain grade or full-strength LUT at full opacity
|
|
303
|
+
over what is underneath or the whole frame, and refuse anything else (fades, part opacity,
|
|
304
|
+
scope `track`, masks) unless the host renders frames with `renderVideoFrameExact`.
|
|
305
|
+
- **Plans go stale.** A plan is worked out against the project as it was. Applying it after
|
|
306
|
+
other edits re-checks it; if it no longer applies, discard it and plan again rather than
|
|
307
|
+
forcing the old ops through `edit_video`.
|
|
308
|
+
|
|
271
309
|
- With agent playback on, the cursor drags a moved or trimmed clip to its new time, clicks a track where a clip goes in, and clicks the ruler where a split, seek or marker lands. Give real `start` / `at` times in ms; results are unchanged.
|
|
272
310
|
- **Effects need rendered frames to export.** ffmpeg cannot draw provider effects, so
|
|
273
311
|
`export_video_ffmpeg` refuses a project with enabled effects unless the host renders the
|