playwriter 0.0.63 → 0.0.89
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/a11y-client.js +18 -8
- package/dist/aria-snapshot.d.ts +41 -3
- package/dist/aria-snapshot.d.ts.map +1 -1
- package/dist/aria-snapshot.js +134 -55
- package/dist/aria-snapshot.js.map +1 -1
- package/dist/aria-snapshot.test.js +5 -2
- package/dist/aria-snapshot.test.js.map +1 -1
- package/dist/aria-snapshot.unit.test.js +83 -41
- package/dist/aria-snapshot.unit.test.js.map +1 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts +5 -0
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts.map +1 -0
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js +5 -0
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js.map +1 -0
- package/dist/bippy.js +1 -1
- package/dist/cdp-log.d.ts +1 -1
- package/dist/cdp-log.d.ts.map +1 -1
- package/dist/cdp-log.js +1 -1
- package/dist/cdp-log.js.map +1 -1
- package/dist/cdp-relay.d.ts.map +1 -1
- package/dist/cdp-relay.js +492 -298
- package/dist/cdp-relay.js.map +1 -1
- package/dist/cdp-session.d.ts.map +1 -1
- package/dist/cdp-session.js.map +1 -1
- package/dist/cdp-types.d.ts.map +1 -1
- package/dist/cdp-types.js +7 -7
- package/dist/cdp-types.js.map +1 -1
- package/dist/clean-html.d.ts.map +1 -1
- package/dist/clean-html.js +4 -5
- package/dist/clean-html.js.map +1 -1
- package/dist/cli.js +45 -27
- package/dist/cli.js.map +1 -1
- package/dist/create-logger.d.ts.map +1 -1
- package/dist/create-logger.js +3 -1
- package/dist/create-logger.js.map +1 -1
- package/dist/debugger-examples-types.d.ts.map +1 -1
- package/dist/debugger.d.ts.map +1 -1
- package/dist/debugger.js +1 -3
- package/dist/debugger.js.map +1 -1
- package/dist/diff-utils.d.ts.map +1 -1
- package/dist/diff-utils.js +1 -4
- package/dist/diff-utils.js.map +1 -1
- package/dist/editor-api.md +12 -2
- package/dist/editor-examples.d.ts +1 -1
- package/dist/editor-examples.d.ts.map +1 -1
- package/dist/editor-examples.js +1 -1
- package/dist/editor-examples.js.map +1 -1
- package/dist/editor.d.ts +1 -1
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +1 -1
- package/dist/editor.js.map +1 -1
- package/dist/executor.d.ts +26 -3
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +297 -64
- package/dist/executor.js.map +1 -1
- package/dist/executor.unit.test.js +38 -1
- package/dist/executor.unit.test.js.map +1 -1
- package/dist/extension-connection.test.js +139 -36
- package/dist/extension-connection.test.js.map +1 -1
- package/dist/ffmpeg.d.ts +148 -0
- package/dist/ffmpeg.d.ts.map +1 -0
- package/dist/ffmpeg.js +523 -0
- package/dist/ffmpeg.js.map +1 -0
- package/dist/ghost-browser.d.ts.map +1 -1
- package/dist/ghost-browser.js.map +1 -1
- package/dist/ghost-cursor-client.js +287 -0
- package/dist/ghost-cursor.d.ts +27 -0
- package/dist/ghost-cursor.d.ts.map +1 -0
- package/dist/ghost-cursor.js +63 -0
- package/dist/ghost-cursor.js.map +1 -0
- package/dist/htmlrewrite.d.ts.map +1 -1
- package/dist/htmlrewrite.js +17 -55
- package/dist/htmlrewrite.js.map +1 -1
- package/dist/htmlrewrite.test.js.map +1 -1
- package/dist/kill-port.d.ts.map +1 -1
- package/dist/kill-port.js +1 -3
- package/dist/kill-port.js.map +1 -1
- package/dist/locator-selector.test.d.ts +2 -0
- package/dist/locator-selector.test.d.ts.map +1 -0
- package/dist/locator-selector.test.js +96 -0
- package/dist/locator-selector.test.js.map +1 -0
- package/dist/mcp-client.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +8 -3
- package/dist/mcp.js.map +1 -1
- package/dist/on-mouse-action.test.d.ts +2 -0
- package/dist/on-mouse-action.test.d.ts.map +1 -0
- package/dist/on-mouse-action.test.js +155 -0
- package/dist/on-mouse-action.test.js.map +1 -0
- package/dist/page-markdown.js +4 -4
- package/dist/page-markdown.js.map +1 -1
- package/dist/prompt.md +450 -377
- package/dist/protocol.d.ts +4 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/readability.js +16 -2
- package/dist/recording-ghost-cursor.d.ts +41 -0
- package/dist/recording-ghost-cursor.d.ts.map +1 -0
- package/dist/recording-ghost-cursor.js +79 -0
- package/dist/recording-ghost-cursor.js.map +1 -0
- package/dist/recording-relay.d.ts.map +1 -1
- package/dist/recording-relay.js +8 -8
- package/dist/recording-relay.js.map +1 -1
- package/dist/relay-client.d.ts +17 -4
- package/dist/relay-client.d.ts.map +1 -1
- package/dist/relay-client.js +45 -11
- package/dist/relay-client.js.map +1 -1
- package/dist/relay-core.test.d.ts.map +1 -1
- package/dist/relay-core.test.js +515 -26
- package/dist/relay-core.test.js.map +1 -1
- package/dist/relay-navigation.test.d.ts.map +1 -1
- package/dist/relay-navigation.test.js +169 -31
- package/dist/relay-navigation.test.js.map +1 -1
- package/dist/relay-session.test.d.ts.map +1 -1
- package/dist/relay-session.test.js +113 -65
- package/dist/relay-session.test.js.map +1 -1
- package/dist/relay-state.d.ts +158 -0
- package/dist/relay-state.d.ts.map +1 -0
- package/dist/relay-state.js +306 -0
- package/dist/relay-state.js.map +1 -0
- package/dist/relay-state.test.d.ts +2 -0
- package/dist/relay-state.test.d.ts.map +1 -0
- package/dist/relay-state.test.js +472 -0
- package/dist/relay-state.test.js.map +1 -0
- package/dist/scoped-fs.d.ts.map +1 -1
- package/dist/scoped-fs.js.map +1 -1
- package/dist/screen-recording.d.ts +66 -4
- package/dist/screen-recording.d.ts.map +1 -1
- package/dist/screen-recording.js +150 -13
- package/dist/screen-recording.js.map +1 -1
- package/dist/screen-recording.test.d.ts +2 -0
- package/dist/screen-recording.test.d.ts.map +1 -0
- package/dist/screen-recording.test.js +102 -0
- package/dist/screen-recording.test.js.map +1 -0
- package/dist/selector-generator.js +1 -1
- package/dist/snapshot-tools.test.js +71 -28
- package/dist/snapshot-tools.test.js.map +1 -1
- package/dist/start-relay-server.d.ts +1 -1
- package/dist/start-relay-server.d.ts.map +1 -1
- package/dist/start-relay-server.js +1 -1
- package/dist/start-relay-server.js.map +1 -1
- package/dist/styles-api.md +8 -1
- package/dist/styles-examples.d.ts +1 -1
- package/dist/styles-examples.d.ts.map +1 -1
- package/dist/styles-examples.js +1 -1
- package/dist/styles-examples.js.map +1 -1
- package/dist/styles.d.ts.map +1 -1
- package/dist/styles.js +1 -3
- package/dist/styles.js.map +1 -1
- package/dist/test-declarations.d.ts.map +1 -1
- package/dist/test-utils.d.ts +1 -1
- package/dist/test-utils.d.ts.map +1 -1
- package/dist/test-utils.js +7 -5
- package/dist/test-utils.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/wait-for-page-load.d.ts.map +1 -1
- package/dist/wait-for-page-load.js +1 -1
- package/dist/wait-for-page-load.js.map +1 -1
- package/package.json +4 -3
- package/src/a11y-client.ts +5 -4
- package/src/aria-snapshot.test.ts +5 -2
- package/src/aria-snapshot.ts +306 -117
- package/src/aria-snapshot.unit.test.ts +199 -141
- package/src/aria-snapshots/github-interactive.txt +2 -0
- package/src/aria-snapshots/github-raw.txt +5 -1
- package/src/aria-snapshots/hackernews-interactive.txt +238 -241
- package/src/aria-snapshots/hackernews-raw.txt +265 -269
- package/src/assets/aria-labels-example.png +0 -0
- package/src/assets/aria-labels-github.png +0 -0
- package/src/assets/aria-labels-hacker-news.png +0 -0
- package/src/assets/aria-labels-old-reddit.png +0 -0
- package/src/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.ts +5 -0
- package/src/assets/cursors/screen-studio/pointer-macos-tahoe.svg +18 -0
- package/src/cdp-log.ts +4 -1
- package/src/cdp-relay.ts +1059 -737
- package/src/cdp-session.ts +12 -3
- package/src/cdp-types.ts +51 -51
- package/src/clean-html.ts +4 -5
- package/src/cli.ts +82 -55
- package/src/create-logger.ts +5 -3
- package/src/debugger-examples-types.ts +4 -1
- package/src/debugger.ts +1 -5
- package/src/diff-utils.ts +2 -5
- package/src/editor-examples.ts +11 -1
- package/src/editor.ts +10 -2
- package/src/executor.ts +374 -73
- package/src/executor.unit.test.ts +48 -1
- package/src/extension-connection.test.ts +612 -488
- package/src/ffmpeg.ts +769 -0
- package/src/ghost-browser.ts +4 -6
- package/src/ghost-cursor-client.ts +369 -0
- package/src/ghost-cursor.ts +110 -0
- package/src/htmlrewrite.test.ts +6 -2
- package/src/htmlrewrite.ts +348 -386
- package/src/kill-port.ts +1 -3
- package/src/locator-selector.test.ts +115 -0
- package/src/mcp-client.ts +1 -1
- package/src/mcp.ts +21 -15
- package/src/on-mouse-action.test.ts +196 -0
- package/src/page-markdown.ts +7 -7
- package/src/protocol.ts +73 -57
- package/src/recording-ghost-cursor.ts +113 -0
- package/src/recording-relay.ts +20 -12
- package/src/relay-client.ts +85 -18
- package/src/relay-core.test.ts +1117 -578
- package/src/relay-navigation.test.ts +648 -483
- package/src/relay-session.test.ts +984 -929
- package/src/relay-state.test.ts +570 -0
- package/src/relay-state.ts +497 -0
- package/src/resource.md +21 -49
- package/src/scoped-fs.ts +9 -3
- package/src/screen-recording.test.ts +111 -0
- package/src/screen-recording.ts +256 -31
- package/src/skill.md +476 -396
- package/src/snapshot-tools.test.ts +580 -528
- package/src/snapshots/shadcn-ui-accessibility-full.md +8 -8
- package/src/snapshots/shadcn-ui-accessibility-interactive.md +8 -8
- package/src/start-relay-server.ts +14 -11
- package/src/styles-examples.ts +8 -1
- package/src/styles.ts +20 -21
- package/src/test-declarations.ts +6 -6
- package/src/test-utils.ts +104 -91
- package/src/utils.ts +2 -1
- package/src/wait-for-page-load.ts +6 -1
package/dist/ffmpeg.js
ADDED
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FFmpeg utilities for video concatenation and section-based speed manipulation.
|
|
3
|
+
*
|
|
4
|
+
* Both functions use a single ffmpeg filter_complex pass: trim segments from
|
|
5
|
+
* the input, apply setpts for speed, normalize fps/scale, then concat.
|
|
6
|
+
* No intermediate files, no multi-pass.
|
|
7
|
+
*/
|
|
8
|
+
import { spawn } from 'node:child_process';
|
|
9
|
+
import os from 'node:os';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Constants
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/** Seconds of normal-speed buffer kept before and after each execution (0.5s each side = 1s total) */
|
|
15
|
+
export const INTERACTION_BUFFER_SECONDS = 0.5;
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Hardware encoder detection
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/**
|
|
20
|
+
* Preferred hardware encoders by platform, in priority order.
|
|
21
|
+
* Each is tried via `ffmpeg -f lavfi -i nullsrc -t 0.01 -c:v <encoder> -f null -`
|
|
22
|
+
* to confirm the encoder actually works (drivers present, GPU available, etc).
|
|
23
|
+
*/
|
|
24
|
+
const HW_ENCODER_CANDIDATES = {
|
|
25
|
+
darwin: ['h264_videotoolbox'],
|
|
26
|
+
win32: ['h264_nvenc', 'h264_qsv', 'h264_amf'],
|
|
27
|
+
// h264_vaapi excluded: requires -vaapi_device and format=nv12,hwupload in the
|
|
28
|
+
// filter graph, which our filter_complex pipeline doesn't set up
|
|
29
|
+
linux: ['h264_nvenc', 'h264_qsv'],
|
|
30
|
+
};
|
|
31
|
+
/** Cache so we only probe once per process */
|
|
32
|
+
let cachedEncoder;
|
|
33
|
+
/**
|
|
34
|
+
* Detect the best available H.264 encoder.
|
|
35
|
+
* Tries platform-specific hardware encoders first, falls back to libx264.
|
|
36
|
+
* Result is cached for the lifetime of the process.
|
|
37
|
+
*/
|
|
38
|
+
export async function detectEncoder() {
|
|
39
|
+
if (cachedEncoder) {
|
|
40
|
+
return cachedEncoder;
|
|
41
|
+
}
|
|
42
|
+
const platform = os.platform();
|
|
43
|
+
const candidates = HW_ENCODER_CANDIDATES[platform] ?? [];
|
|
44
|
+
for (const codec of candidates) {
|
|
45
|
+
const works = await testEncoder(codec);
|
|
46
|
+
if (works) {
|
|
47
|
+
cachedEncoder = { codec, isHardware: true };
|
|
48
|
+
return cachedEncoder;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
cachedEncoder = { codec: 'libx264', isHardware: false };
|
|
52
|
+
return cachedEncoder;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Quick probe: can this encoder produce even a single frame?
|
|
56
|
+
* Runs `ffmpeg -f lavfi -i nullsrc=s=64x64:d=0.01 -c:v <encoder> -f null -`
|
|
57
|
+
* and checks exit code. Timeout 5s to avoid hanging on broken drivers.
|
|
58
|
+
*/
|
|
59
|
+
function testEncoder(codec) {
|
|
60
|
+
return new Promise((resolve) => {
|
|
61
|
+
const child = spawn('ffmpeg', [
|
|
62
|
+
'-hide_banner', '-loglevel', 'error',
|
|
63
|
+
'-f', 'lavfi', '-i', 'nullsrc=s=64x64:d=0.01',
|
|
64
|
+
'-c:v', codec,
|
|
65
|
+
'-f', 'null', '-',
|
|
66
|
+
], { stdio: 'ignore' });
|
|
67
|
+
const timeout = setTimeout(() => {
|
|
68
|
+
child.kill();
|
|
69
|
+
resolve(false);
|
|
70
|
+
}, 5000);
|
|
71
|
+
child.on('close', (code) => {
|
|
72
|
+
clearTimeout(timeout);
|
|
73
|
+
resolve(code === 0);
|
|
74
|
+
});
|
|
75
|
+
child.on('error', () => {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
resolve(false);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Encoding quality parameters
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
/**
|
|
85
|
+
* Build encoding args optimized for screen recordings on social media.
|
|
86
|
+
*
|
|
87
|
+
* Quality rationale (screen recordings = sharp text, flat colors, UI):
|
|
88
|
+
* - libx264 CRF 18 = near visually lossless, prevents text compression artifacts
|
|
89
|
+
* - `-preset fast` = ~4x faster than default `medium`, minimal quality loss on
|
|
90
|
+
* screen content. NOT `ultrafast` which compresses so poorly that platforms
|
|
91
|
+
* (X.com, YouTube) re-encode more aggressively, making it look worse.
|
|
92
|
+
* - `-x264opts deblock=-1,-1` = less deblocking preserves sharp text edges
|
|
93
|
+
* - No `-tune` flag: `animation` blurs text edges, `zerolatency` is for
|
|
94
|
+
* real-time capture only
|
|
95
|
+
* - h264_videotoolbox `-q:v 80` ≈ CRF 18 equivalent for screen content
|
|
96
|
+
* - `-maxrate 25M` = X.com (Twitter) max bitrate cap
|
|
97
|
+
* - `-movflags +faststart` = metadata at front for web streaming
|
|
98
|
+
* - `-pix_fmt yuv420p` = universal compatibility across all platforms
|
|
99
|
+
*/
|
|
100
|
+
function buildEncodingArgs(encoder) {
|
|
101
|
+
const common = [
|
|
102
|
+
'-pix_fmt', 'yuv420p',
|
|
103
|
+
'-maxrate', '25M',
|
|
104
|
+
'-bufsize', '50M',
|
|
105
|
+
'-movflags', '+faststart',
|
|
106
|
+
];
|
|
107
|
+
if (encoder.isHardware) {
|
|
108
|
+
// Hardware encoders: use quality-based mode where supported
|
|
109
|
+
// h264_videotoolbox uses -q:v (1-100, 100=best), others use -b:v
|
|
110
|
+
const qualityArgs = encoder.codec === 'h264_videotoolbox'
|
|
111
|
+
? ['-q:v', '80']
|
|
112
|
+
: ['-b:v', '15M']; // high bitrate for other HW encoders
|
|
113
|
+
return ['-c:v', encoder.codec, ...qualityArgs, ...common];
|
|
114
|
+
}
|
|
115
|
+
// Software: libx264 with screen-recording-optimized settings
|
|
116
|
+
return [
|
|
117
|
+
'-c:v', 'libx264',
|
|
118
|
+
'-crf', '18',
|
|
119
|
+
'-preset', 'fast',
|
|
120
|
+
'-x264opts', 'deblock=-1,-1',
|
|
121
|
+
...common,
|
|
122
|
+
];
|
|
123
|
+
}
|
|
124
|
+
function parseFrameRate(value) {
|
|
125
|
+
if (!value) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const [numRaw, denRaw] = value.split('/').map(Number);
|
|
129
|
+
if (!Number.isFinite(numRaw) || !Number.isFinite(denRaw) || denRaw === 0) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const frameRate = numRaw / denRaw;
|
|
133
|
+
if (!Number.isFinite(frameRate) || frameRate <= 0) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
return frameRate;
|
|
137
|
+
}
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
// Helpers
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
/** Probe input video for dimensions and frame rate via ffprobe. */
|
|
142
|
+
export async function probeVideo(filePath) {
|
|
143
|
+
const stdout = await runCommand({
|
|
144
|
+
bin: 'ffprobe',
|
|
145
|
+
args: [
|
|
146
|
+
'-v', 'error',
|
|
147
|
+
'-select_streams', 'v:0',
|
|
148
|
+
'-show_entries', 'stream=width,height,r_frame_rate,avg_frame_rate',
|
|
149
|
+
'-of', 'json',
|
|
150
|
+
filePath,
|
|
151
|
+
],
|
|
152
|
+
});
|
|
153
|
+
const parsed = JSON.parse(stdout);
|
|
154
|
+
const stream = parsed.streams?.[0];
|
|
155
|
+
if (!stream) {
|
|
156
|
+
throw new Error(`No video stream found in ${filePath}`);
|
|
157
|
+
}
|
|
158
|
+
// Prefer avg_frame_rate for VFR recordings. r_frame_rate can report
|
|
159
|
+
// high timebase-like values (e.g. 30000/1) that are not usable output FPS.
|
|
160
|
+
const avgFrameRate = parseFrameRate(stream.avg_frame_rate);
|
|
161
|
+
const rawFrameRate = parseFrameRate(stream.r_frame_rate);
|
|
162
|
+
const selectedFrameRate = (() => {
|
|
163
|
+
if (avgFrameRate && avgFrameRate <= 120) {
|
|
164
|
+
return avgFrameRate;
|
|
165
|
+
}
|
|
166
|
+
if (rawFrameRate && rawFrameRate <= 120) {
|
|
167
|
+
return rawFrameRate;
|
|
168
|
+
}
|
|
169
|
+
if (avgFrameRate) {
|
|
170
|
+
return avgFrameRate;
|
|
171
|
+
}
|
|
172
|
+
if (rawFrameRate) {
|
|
173
|
+
return rawFrameRate;
|
|
174
|
+
}
|
|
175
|
+
return 30;
|
|
176
|
+
})();
|
|
177
|
+
const normalizedFrameRate = Math.min(120, Math.max(1, Math.round(selectedFrameRate)));
|
|
178
|
+
return {
|
|
179
|
+
width: stream.width,
|
|
180
|
+
height: stream.height,
|
|
181
|
+
frameRate: normalizedFrameRate,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Run a process with argv (no shell). Returns stdout as string.
|
|
186
|
+
* Avoids shell injection by never passing through a shell interpreter.
|
|
187
|
+
*/
|
|
188
|
+
function runCommand({ bin, args, signal, }) {
|
|
189
|
+
return new Promise((resolve, reject) => {
|
|
190
|
+
const child = spawn(bin, args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
191
|
+
let stdout = '';
|
|
192
|
+
let stderr = '';
|
|
193
|
+
child.stdout.on('data', (data) => {
|
|
194
|
+
stdout += data.toString();
|
|
195
|
+
});
|
|
196
|
+
child.stderr.on('data', (data) => {
|
|
197
|
+
stderr += data.toString();
|
|
198
|
+
});
|
|
199
|
+
child.on('close', (code) => {
|
|
200
|
+
if (code === 0) {
|
|
201
|
+
resolve(stdout);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
reject(new Error(`FFmpeg error (exit ${code}): ${stderr}`));
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
child.on('error', (err) => {
|
|
208
|
+
reject(new Error(`Failed to start ${bin}`, { cause: err }));
|
|
209
|
+
});
|
|
210
|
+
if (signal) {
|
|
211
|
+
signal.addEventListener('abort', () => {
|
|
212
|
+
child.kill();
|
|
213
|
+
reject(signal.reason instanceof Error
|
|
214
|
+
? signal.reason
|
|
215
|
+
: new Error('Operation aborted'));
|
|
216
|
+
}, { once: true });
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
/** Build default output path: `/dir/name-fast.ext` */
|
|
221
|
+
function defaultOutputPath(inputFile) {
|
|
222
|
+
const ext = path.extname(inputFile);
|
|
223
|
+
const base = path.basename(inputFile, ext);
|
|
224
|
+
const dir = path.dirname(inputFile);
|
|
225
|
+
return path.join(dir, `${base}-fast${ext}`);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Given sorted, non-overlapping SpeedSections, fill gaps with normal-speed
|
|
229
|
+
* segments so the entire video is covered.
|
|
230
|
+
*/
|
|
231
|
+
function buildSegments(sections) {
|
|
232
|
+
const sorted = [...sections].sort((a, b) => {
|
|
233
|
+
return a.start - b.start;
|
|
234
|
+
});
|
|
235
|
+
// Validate: no overlaps
|
|
236
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
237
|
+
if (sorted[i].start < sorted[i - 1].end) {
|
|
238
|
+
throw new Error(`Sections overlap: [${sorted[i - 1].start}-${sorted[i - 1].end}] and [${sorted[i].start}-${sorted[i].end}]`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const segments = [];
|
|
242
|
+
let cursor = 0;
|
|
243
|
+
for (const section of sorted) {
|
|
244
|
+
// Gap before this section → normal speed
|
|
245
|
+
if (section.start > cursor) {
|
|
246
|
+
segments.push({ start: cursor, end: section.start, speed: 1 });
|
|
247
|
+
}
|
|
248
|
+
// The speed section itself
|
|
249
|
+
segments.push({
|
|
250
|
+
start: section.start,
|
|
251
|
+
end: section.end,
|
|
252
|
+
speed: section.speed,
|
|
253
|
+
});
|
|
254
|
+
cursor = section.end;
|
|
255
|
+
}
|
|
256
|
+
// Trailing normal-speed segment (no end bound → until EOF)
|
|
257
|
+
segments.push({ start: cursor, end: undefined, speed: 1 });
|
|
258
|
+
return segments;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Build the filter string for a single segment.
|
|
262
|
+
*
|
|
263
|
+
* For sped-up segments: `[0:v]trim=...,setpts=...,fps=...,scale=...[vN]`
|
|
264
|
+
* For normal-speed segments where dimensions/fps match input: just
|
|
265
|
+
* `[0:v]trim=...,setpts=PTS-STARTPTS[vN]` — skips fps and scale filters
|
|
266
|
+
* to avoid unnecessary pixel processing and frame-rate checking.
|
|
267
|
+
*/
|
|
268
|
+
function buildSegmentFilter({ segment, index, frameRate, width, height, inputWidth, inputHeight, inputFrameRate, }) {
|
|
269
|
+
const trimParts = [`start=${segment.start}`];
|
|
270
|
+
if (segment.end !== undefined) {
|
|
271
|
+
trimParts.push(`end=${segment.end}`);
|
|
272
|
+
}
|
|
273
|
+
const trim = `trim=${trimParts.join(':')}`;
|
|
274
|
+
// setpts=PTS-STARTPTS resets timestamps after trim.
|
|
275
|
+
// Dividing by speed makes it faster (speed>1) or slower (speed<1).
|
|
276
|
+
const setpts = segment.speed === 1
|
|
277
|
+
? 'setpts=PTS-STARTPTS'
|
|
278
|
+
: `setpts=(PTS-STARTPTS)/${segment.speed}`;
|
|
279
|
+
// For normal-speed segments where output matches input: skip fps/scale
|
|
280
|
+
// to avoid unnecessary pixel processing and frame-rate filtering
|
|
281
|
+
const isPassthrough = segment.speed === 1
|
|
282
|
+
&& inputWidth === width
|
|
283
|
+
&& inputHeight === height
|
|
284
|
+
&& inputFrameRate === frameRate;
|
|
285
|
+
if (isPassthrough) {
|
|
286
|
+
return `[0:v]${trim},${setpts}[v${index}]`;
|
|
287
|
+
}
|
|
288
|
+
// Cap output FPS to the probed source FPS. This prevents sped-up sections
|
|
289
|
+
// from producing excessive frame rates when timestamps are compressed.
|
|
290
|
+
const fps = `fps=fps=${frameRate}:round=down`;
|
|
291
|
+
return `[0:v]${trim},${setpts},${fps},scale=${width}:${height}[v${index}]`;
|
|
292
|
+
}
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
// Public API
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
export async function concatenateVideos(options) {
|
|
297
|
+
const { outputDimensions, frameRate, inputFiles, outputFile, signal } = options;
|
|
298
|
+
if (!outputDimensions || !frameRate || !inputFiles || !outputFile) {
|
|
299
|
+
throw new Error('Missing required parameters');
|
|
300
|
+
}
|
|
301
|
+
const timerId = `concat-${inputFiles.length}-videos-${path.basename(outputFile)}`;
|
|
302
|
+
console.time(timerId);
|
|
303
|
+
const encoder = await detectEncoder();
|
|
304
|
+
const encodingArgs = buildEncodingArgs(encoder);
|
|
305
|
+
// Build argv: -i file1 -i file2 ... -filter_complex "..." -map "[v_out]" output
|
|
306
|
+
const inputArgs = inputFiles.flatMap((file) => {
|
|
307
|
+
return ['-i', file.path];
|
|
308
|
+
});
|
|
309
|
+
const filterComplexParts = [];
|
|
310
|
+
const videoStreamParts = [];
|
|
311
|
+
inputFiles.forEach((file, index) => {
|
|
312
|
+
const videoStream = `[${index}:v:0]`;
|
|
313
|
+
let trimmedVideo = videoStream;
|
|
314
|
+
if (file.start !== undefined || file.end !== undefined) {
|
|
315
|
+
const start = file.start ?? 0;
|
|
316
|
+
const end = file.end ? `end=${file.end}` : '';
|
|
317
|
+
trimmedVideo = `${videoStream}trim=start=${start}:${end},setpts=PTS-STARTPTS`;
|
|
318
|
+
}
|
|
319
|
+
filterComplexParts.push(`${trimmedVideo},fps=${frameRate},scale=${outputDimensions.width}:${outputDimensions.height}[v${index}]`);
|
|
320
|
+
videoStreamParts.push(`[v${index}]`);
|
|
321
|
+
});
|
|
322
|
+
filterComplexParts.push(`${videoStreamParts.join('')}concat=n=${inputFiles.length}:v=1:a=0[v_out]`);
|
|
323
|
+
const filterComplex = filterComplexParts.join('; ');
|
|
324
|
+
const args = [
|
|
325
|
+
...inputArgs,
|
|
326
|
+
'-filter_complex', filterComplex,
|
|
327
|
+
'-map', '[v_out]',
|
|
328
|
+
...encodingArgs,
|
|
329
|
+
outputFile,
|
|
330
|
+
];
|
|
331
|
+
console.log('Running FFmpeg concat:', args.join(' '));
|
|
332
|
+
try {
|
|
333
|
+
await runCommand({ bin: 'ffmpeg', args, signal });
|
|
334
|
+
}
|
|
335
|
+
finally {
|
|
336
|
+
console.timeEnd(timerId);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Speed up (or slow down) sections of a video by timestamp ranges.
|
|
341
|
+
*
|
|
342
|
+
* Sections not covered by any SpeedSection play at normal speed.
|
|
343
|
+
* Uses a single ffmpeg filter_complex: trim each segment, apply setpts
|
|
344
|
+
* speed, normalize fps/scale, then concat — no intermediate files.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```ts
|
|
348
|
+
* await speedUpSections({
|
|
349
|
+
* inputFile: 'recording.mp4',
|
|
350
|
+
* sections: [
|
|
351
|
+
* { start: 10, end: 20, speed: 4 }, // 4x between 10s-20s
|
|
352
|
+
* { start: 30, end: 40, speed: 2 }, // 2x between 30s-40s
|
|
353
|
+
* ],
|
|
354
|
+
* })
|
|
355
|
+
* // → outputs recording-fast.mp4
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
export async function speedUpSections(options) {
|
|
359
|
+
const { inputFile, sections, signal } = options;
|
|
360
|
+
if (sections.length === 0) {
|
|
361
|
+
throw new Error('At least one speed section is required');
|
|
362
|
+
}
|
|
363
|
+
for (const s of sections) {
|
|
364
|
+
if (s.speed <= 0) {
|
|
365
|
+
throw new Error(`Speed must be > 0, got ${s.speed}`);
|
|
366
|
+
}
|
|
367
|
+
if (s.end <= s.start) {
|
|
368
|
+
throw new Error(`Section end (${s.end}) must be greater than start (${s.start})`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const outputFile = options.outputFile ?? defaultOutputPath(inputFile);
|
|
372
|
+
// Probe input when needed for defaults or for passthrough optimization
|
|
373
|
+
const dims = options.outputDimensions;
|
|
374
|
+
const fps = options.frameRate;
|
|
375
|
+
const probed = (!dims || !fps) ? await probeVideo(inputFile) : undefined;
|
|
376
|
+
const width = dims?.width ?? probed.width;
|
|
377
|
+
const height = dims?.height ?? probed.height;
|
|
378
|
+
const frameRate = fps ?? probed.frameRate;
|
|
379
|
+
const encoder = await detectEncoder();
|
|
380
|
+
const encodingArgs = buildEncodingArgs(encoder);
|
|
381
|
+
const timerId = `speedup-${sections.length}-sections-${path.basename(outputFile)}`;
|
|
382
|
+
console.time(timerId);
|
|
383
|
+
const segments = buildSegments(sections);
|
|
384
|
+
const filterParts = segments.map((segment, index) => {
|
|
385
|
+
return buildSegmentFilter({
|
|
386
|
+
segment,
|
|
387
|
+
index,
|
|
388
|
+
frameRate,
|
|
389
|
+
width,
|
|
390
|
+
height,
|
|
391
|
+
inputWidth: probed?.width,
|
|
392
|
+
inputHeight: probed?.height,
|
|
393
|
+
inputFrameRate: probed?.frameRate,
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
const streamLabels = segments.map((_, i) => {
|
|
397
|
+
return `[v${i}]`;
|
|
398
|
+
}).join('');
|
|
399
|
+
filterParts.push(`${streamLabels}concat=n=${segments.length}:v=1:a=0[v_out]`);
|
|
400
|
+
const filterComplex = filterParts.join('; ');
|
|
401
|
+
const args = [
|
|
402
|
+
'-i', inputFile,
|
|
403
|
+
'-filter_complex', filterComplex,
|
|
404
|
+
'-map', '[v_out]',
|
|
405
|
+
'-r', String(frameRate),
|
|
406
|
+
...encodingArgs,
|
|
407
|
+
outputFile,
|
|
408
|
+
];
|
|
409
|
+
console.log('Running FFmpeg speedup:', args.join(' '));
|
|
410
|
+
try {
|
|
411
|
+
await runCommand({ bin: 'ffmpeg', args, signal });
|
|
412
|
+
}
|
|
413
|
+
finally {
|
|
414
|
+
console.timeEnd(timerId);
|
|
415
|
+
}
|
|
416
|
+
return outputFile;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Compute which parts of a recording are "idle" (no execute() calls)
|
|
420
|
+
* and return them as SpeedSections that can be passed to speedUpSections().
|
|
421
|
+
*
|
|
422
|
+
* A buffer of INTERACTION_BUFFER_SECONDS is kept around each execution
|
|
423
|
+
* at normal speed so the viewer sees context before/after each action.
|
|
424
|
+
*
|
|
425
|
+
* @example
|
|
426
|
+
* ```ts
|
|
427
|
+
* const { executionTimestamps, duration } = await stopRecording()
|
|
428
|
+
* const idleSections = computeIdleSections({
|
|
429
|
+
* executionTimestamps,
|
|
430
|
+
* totalDurationMs: duration,
|
|
431
|
+
* })
|
|
432
|
+
* await speedUpSections({
|
|
433
|
+
* inputFile: recordingPath,
|
|
434
|
+
* sections: idleSections,
|
|
435
|
+
* })
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
export function computeIdleSections({ executionTimestamps, totalDurationMs, speed = 6, bufferSeconds = INTERACTION_BUFFER_SECONDS, }) {
|
|
439
|
+
const totalDuration = totalDurationMs / 1000;
|
|
440
|
+
if (executionTimestamps.length === 0) {
|
|
441
|
+
// No execute() boundaries were captured. This commonly happens when
|
|
442
|
+
// recording starts and stops inside a single execute() call.
|
|
443
|
+
// In this case we cannot infer idle gaps safely, so keep original speed.
|
|
444
|
+
return [];
|
|
445
|
+
}
|
|
446
|
+
// Apply buffer: expand each execution range by bufferSeconds on each side,
|
|
447
|
+
// clamp to video bounds, then filter out any ranges that become invalid
|
|
448
|
+
// (e.g. timestamps that exceed the video duration).
|
|
449
|
+
const buffered = executionTimestamps
|
|
450
|
+
.map((t) => ({
|
|
451
|
+
start: Math.max(0, t.start - bufferSeconds),
|
|
452
|
+
end: Math.min(totalDuration, t.end + bufferSeconds),
|
|
453
|
+
}))
|
|
454
|
+
.filter((r) => {
|
|
455
|
+
return Number.isFinite(r.start) && Number.isFinite(r.end) && r.end > r.start;
|
|
456
|
+
})
|
|
457
|
+
.sort((a, b) => {
|
|
458
|
+
return a.start - b.start;
|
|
459
|
+
});
|
|
460
|
+
// Merge overlapping/adjacent buffered ranges
|
|
461
|
+
const merged = [];
|
|
462
|
+
for (const range of buffered) {
|
|
463
|
+
const last = merged[merged.length - 1];
|
|
464
|
+
if (last && range.start <= last.end) {
|
|
465
|
+
last.end = Math.max(last.end, range.end);
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
merged.push({ ...range });
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
// Gaps between merged active ranges are idle sections to speed up
|
|
472
|
+
const idle = [];
|
|
473
|
+
let cursor = 0;
|
|
474
|
+
for (const active of merged) {
|
|
475
|
+
if (active.start > cursor) {
|
|
476
|
+
idle.push({ start: cursor, end: active.start, speed });
|
|
477
|
+
}
|
|
478
|
+
cursor = active.end;
|
|
479
|
+
}
|
|
480
|
+
// Trailing idle after last execution
|
|
481
|
+
if (cursor < totalDuration) {
|
|
482
|
+
idle.push({ start: cursor, end: totalDuration, speed });
|
|
483
|
+
}
|
|
484
|
+
return idle;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Create a demo video from a recording by speeding up idle sections
|
|
488
|
+
* (gaps between execute() calls) while keeping interactions at normal speed.
|
|
489
|
+
*
|
|
490
|
+
* A 0.5-second buffer (INTERACTION_BUFFER_SECONDS) is preserved on each side of
|
|
491
|
+
* an interaction (1 second total) so viewers see context before and after each action.
|
|
492
|
+
*
|
|
493
|
+
* Requires `ffmpeg` and `ffprobe` installed on the system.
|
|
494
|
+
*
|
|
495
|
+
* @returns The output file path
|
|
496
|
+
*/
|
|
497
|
+
export async function createDemoVideo(options) {
|
|
498
|
+
const { recordingPath, durationMs, executionTimestamps, speed = 6, signal, } = options;
|
|
499
|
+
const outputFile = options.outputFile ?? (() => {
|
|
500
|
+
const ext = path.extname(recordingPath);
|
|
501
|
+
const base = path.basename(recordingPath, ext);
|
|
502
|
+
const dir = path.dirname(recordingPath);
|
|
503
|
+
return path.join(dir, `${base}-demo${ext}`);
|
|
504
|
+
})();
|
|
505
|
+
const idleSections = computeIdleSections({
|
|
506
|
+
executionTimestamps,
|
|
507
|
+
totalDurationMs: durationMs,
|
|
508
|
+
speed,
|
|
509
|
+
});
|
|
510
|
+
if (idleSections.length === 0) {
|
|
511
|
+
// No idle sections, nothing to speed up — copy as-is
|
|
512
|
+
const { copyFile } = await import('node:fs/promises');
|
|
513
|
+
await copyFile(recordingPath, outputFile);
|
|
514
|
+
return outputFile;
|
|
515
|
+
}
|
|
516
|
+
return speedUpSections({
|
|
517
|
+
inputFile: recordingPath,
|
|
518
|
+
outputFile,
|
|
519
|
+
sections: idleSections,
|
|
520
|
+
signal,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
//# sourceMappingURL=ffmpeg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ffmpeg.js","sourceRoot":"","sources":["../src/ffmpeg.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ghost-browser.d.ts","sourceRoot":"","sources":["../src/ghost-browser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,eAAO,MAAM,0BAA0B;;;;CAI7B,CAAA;AAEV,eAAO,MAAM,uBAAuB;;;CAG1B,CAAA;AAEV,eAAO,MAAM,wBAAwB;;;;;;CAM3B,CAAA;AAMV,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,GAAG,cAAc,GAAG,UAAU,CAAA;AAElF,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,qBAAqB,CAAA;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,EAAE,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,yBAAyB,
|
|
1
|
+
{"version":3,"file":"ghost-browser.d.ts","sourceRoot":"","sources":["../src/ghost-browser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,eAAO,MAAM,0BAA0B;;;;CAI7B,CAAA;AAEV,eAAO,MAAM,uBAAuB;;;CAG1B,CAAA;AAEV,eAAO,MAAM,wBAAwB;;;;;;CAM3B,CAAA;AAMV,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,GAAG,cAAc,GAAG,UAAU,CAAA;AAElF,MAAM,MAAM,yBAAyB,GAAG;IACtC,SAAS,EAAE,qBAAqB,CAAA;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,EAAE,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9G;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,CACpC,SAAS,EAAE,qBAAqB,EAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EAAE,KACZ,OAAO,CAAC,OAAO,CAAC,CAAA;AA2BrB;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,uBAAuB;;;;EAM5E;AAMD;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,yBAAyB,EACjC,SAAS,EAAE,OAAO,MAAM,GACvB,OAAO,CAAC,yBAAyB,CAAC,CAuCpC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ghost-browser.js","sourceRoot":"","sources":["../src/ghost-browser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gFAAgF;AAChF,8CAA8C;AAC9C,gFAAgF;AAEhF,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,sBAAsB,EAAE,kBAAkB;IAC1C,gBAAgB,EAAE,EAAE;IACpB,wBAAwB,EAAE,EAAE;CACpB,CAAA;AAEV,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,YAAY,EAAE,sCAAsC;IACpD,YAAY,EAAE,sCAAsC;CAC5C,CAAA;AAEV,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,eAAe,EAAE,sCAAsC;IACvD,kBAAkB,EAAE,sCAAsC;IAC1D,YAAY,EAAE,EAAE;IAChB,WAAW,EAAE,kBAAkB;IAC/B,cAAc,EAAE,EAAE;CACV,CAAA;
|
|
1
|
+
{"version":3,"file":"ghost-browser.js","sourceRoot":"","sources":["../src/ghost-browser.ts"],"names":[],"mappings":"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"}
|