@agent-foundry/replay-server 1.0.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/.cursor/project.mdc +694 -0
- package/.dockerignore +11 -0
- package/Dockerfile +156 -0
- package/README.md +628 -0
- package/bundles/.gitkeep +2 -0
- package/dist/cli/render.d.ts +10 -0
- package/dist/cli/render.d.ts.map +1 -0
- package/dist/cli/render.js +206 -0
- package/dist/cli/render.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/renderer/PuppeteerRenderer.d.ts +72 -0
- package/dist/renderer/PuppeteerRenderer.d.ts.map +1 -0
- package/dist/renderer/PuppeteerRenderer.js +392 -0
- package/dist/renderer/PuppeteerRenderer.js.map +1 -0
- package/dist/renderer/index.d.ts +2 -0
- package/dist/renderer/index.d.ts.map +1 -0
- package/dist/renderer/index.js +2 -0
- package/dist/renderer/index.js.map +1 -0
- package/dist/server/index.d.ts +14 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +348 -0
- package/dist/server/index.js.map +1 -0
- package/docker-compose.local.yml +29 -0
- package/package.json +35 -0
- package/samples/life-replay-lr-mkcdfzc2-u8cqbs.json +1770 -0
- package/scripts/build-bundle.sh +52 -0
- package/scripts/deploy-aliyun.sh +81 -0
- package/src/cli/render.ts +243 -0
- package/src/index.ts +2 -0
- package/src/renderer/PuppeteerRenderer.ts +512 -0
- package/src/renderer/index.ts +1 -0
- package/src/server/index.ts +407 -0
- package/tsconfig.json +35 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI tool for offline video rendering
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx tsx src/cli/render.ts --manifest ./replay.json --output ./output.mp4
|
|
7
|
+
* npx tsx src/cli/render.ts --manifest-url https://... --game-url http://localhost:5173
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { PuppeteerRenderer } from '../renderer/PuppeteerRenderer.js';
|
|
12
|
+
function parseArgs() {
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const result = {
|
|
15
|
+
output: './output.mp4',
|
|
16
|
+
gameUrl: 'http://localhost:5173',
|
|
17
|
+
width: 720,
|
|
18
|
+
height: 1280,
|
|
19
|
+
fps: 16,
|
|
20
|
+
secondsPerAge: 1.0,
|
|
21
|
+
keepTemp: false,
|
|
22
|
+
useHardwareAcceleration: false,
|
|
23
|
+
help: false,
|
|
24
|
+
};
|
|
25
|
+
for (let i = 0; i < args.length; i++) {
|
|
26
|
+
const arg = args[i];
|
|
27
|
+
const next = args[i + 1];
|
|
28
|
+
switch (arg) {
|
|
29
|
+
case '--manifest':
|
|
30
|
+
case '-m':
|
|
31
|
+
result.manifest = next;
|
|
32
|
+
i++;
|
|
33
|
+
break;
|
|
34
|
+
case '--manifest-url':
|
|
35
|
+
result.manifestUrl = next;
|
|
36
|
+
i++;
|
|
37
|
+
break;
|
|
38
|
+
case '--output':
|
|
39
|
+
case '-o':
|
|
40
|
+
result.output = next;
|
|
41
|
+
i++;
|
|
42
|
+
break;
|
|
43
|
+
case '--game-url':
|
|
44
|
+
case '-g':
|
|
45
|
+
result.gameUrl = next;
|
|
46
|
+
i++;
|
|
47
|
+
break;
|
|
48
|
+
case '--width':
|
|
49
|
+
result.width = parseInt(next, 10);
|
|
50
|
+
i++;
|
|
51
|
+
break;
|
|
52
|
+
case '--height':
|
|
53
|
+
result.height = parseInt(next, 10);
|
|
54
|
+
i++;
|
|
55
|
+
break;
|
|
56
|
+
case '--fps':
|
|
57
|
+
result.fps = parseInt(next, 10);
|
|
58
|
+
i++;
|
|
59
|
+
break;
|
|
60
|
+
case '--seconds-per-age':
|
|
61
|
+
result.secondsPerAge = parseFloat(next);
|
|
62
|
+
i++;
|
|
63
|
+
break;
|
|
64
|
+
case '--keep-temp':
|
|
65
|
+
result.keepTemp = true;
|
|
66
|
+
break;
|
|
67
|
+
case '--use-hardware-acceleration':
|
|
68
|
+
case '--nvenc':
|
|
69
|
+
result.useHardwareAcceleration = true;
|
|
70
|
+
break;
|
|
71
|
+
case '--help':
|
|
72
|
+
case '-h':
|
|
73
|
+
result.help = true;
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
function printHelp() {
|
|
80
|
+
console.log(`
|
|
81
|
+
🎬 LifeRestart Replay Renderer CLI
|
|
82
|
+
|
|
83
|
+
Usage:
|
|
84
|
+
npx tsx src/cli/render.ts [options]
|
|
85
|
+
|
|
86
|
+
Options:
|
|
87
|
+
-m, --manifest <path> Path to replay manifest JSON file
|
|
88
|
+
--manifest-url <url> URL to fetch replay manifest from
|
|
89
|
+
-o, --output <path> Output video path (default: ./output.mp4)
|
|
90
|
+
-g, --game-url <url> Game URL (default: http://localhost:5173)
|
|
91
|
+
--width <px> Video width (default: 720)
|
|
92
|
+
--height <px> Video height (default: 1280)
|
|
93
|
+
--fps <n> Frames per second (default: 16)
|
|
94
|
+
--seconds-per-age <n> Seconds to display each age (default: 1.0)
|
|
95
|
+
--use-hardware-acceleration Enable NVENC hardware acceleration (default: CPU encoding)
|
|
96
|
+
--nvenc Alias for --use-hardware-acceleration
|
|
97
|
+
--keep-temp Keep temporary screenshot files (deprecated)
|
|
98
|
+
-h, --help Show this help message
|
|
99
|
+
|
|
100
|
+
Examples:
|
|
101
|
+
# Render from local manifest file
|
|
102
|
+
npx tsx src/cli/render.ts -m ./replay.json -o ./video.mp4
|
|
103
|
+
|
|
104
|
+
# Render from URL
|
|
105
|
+
npx tsx src/cli/render.ts --manifest-url https://example.com/replay.json
|
|
106
|
+
|
|
107
|
+
# Custom video settings
|
|
108
|
+
npx tsx src/cli/render.ts -m ./replay.json --width 720 --height 1280 --fps 60
|
|
109
|
+
`);
|
|
110
|
+
}
|
|
111
|
+
async function loadManifest(args) {
|
|
112
|
+
if (args.manifest) {
|
|
113
|
+
const manifestPath = path.resolve(args.manifest);
|
|
114
|
+
if (!fs.existsSync(manifestPath)) {
|
|
115
|
+
throw new Error(`Manifest file not found: ${manifestPath}`);
|
|
116
|
+
}
|
|
117
|
+
const content = await fs.promises.readFile(manifestPath, 'utf-8');
|
|
118
|
+
return JSON.parse(content);
|
|
119
|
+
}
|
|
120
|
+
if (args.manifestUrl) {
|
|
121
|
+
const response = await fetch(args.manifestUrl);
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw new Error(`Failed to fetch manifest: ${response.statusText}`);
|
|
124
|
+
}
|
|
125
|
+
return await response.json();
|
|
126
|
+
}
|
|
127
|
+
throw new Error('Either --manifest or --manifest-url is required');
|
|
128
|
+
}
|
|
129
|
+
function formatProgress(progress) {
|
|
130
|
+
const percent = progress.total > 0
|
|
131
|
+
? Math.round((progress.current / progress.total) * 100)
|
|
132
|
+
: 0;
|
|
133
|
+
const bar = '█'.repeat(Math.floor(percent / 5)) + '░'.repeat(20 - Math.floor(percent / 5));
|
|
134
|
+
return `[${bar}] ${percent}% - ${progress.message}`;
|
|
135
|
+
}
|
|
136
|
+
async function main() {
|
|
137
|
+
const args = parseArgs();
|
|
138
|
+
if (args.help) {
|
|
139
|
+
printHelp();
|
|
140
|
+
process.exit(0);
|
|
141
|
+
}
|
|
142
|
+
if (!args.manifest && !args.manifestUrl) {
|
|
143
|
+
console.error('Error: Either --manifest or --manifest-url is required');
|
|
144
|
+
console.error('Run with --help for usage information');
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
console.log('🎬 LifeRestart Replay Renderer');
|
|
148
|
+
console.log('━'.repeat(50));
|
|
149
|
+
try {
|
|
150
|
+
// Load manifest
|
|
151
|
+
console.log('📄 Loading manifest...');
|
|
152
|
+
const manifest = await loadManifest(args);
|
|
153
|
+
console.log(` Game ID: ${manifest.gameId}`);
|
|
154
|
+
console.log(` Timeline: ${manifest.timeline.length} ages`);
|
|
155
|
+
console.log(` Highlights: ${manifest.highlights.length}`);
|
|
156
|
+
// Estimate duration
|
|
157
|
+
const estimatedDuration = manifest.timeline.length * args.secondsPerAge;
|
|
158
|
+
console.log(` Estimated video duration: ${estimatedDuration}s`);
|
|
159
|
+
console.log('');
|
|
160
|
+
// Create output directory
|
|
161
|
+
const outputDir = path.dirname(path.resolve(args.output));
|
|
162
|
+
await fs.promises.mkdir(outputDir, { recursive: true });
|
|
163
|
+
// Start rendering
|
|
164
|
+
console.log('🚀 Starting render...');
|
|
165
|
+
console.log(` Game URL: ${args.gameUrl}`);
|
|
166
|
+
console.log(` Output: ${args.output}`);
|
|
167
|
+
console.log(` Resolution: ${args.width}x${args.height} @ ${args.fps}fps`);
|
|
168
|
+
console.log(` Encoder: ${args.useHardwareAcceleration ? 'h264_nvenc (Hardware)' : 'libx264 (CPU)'}`);
|
|
169
|
+
console.log('');
|
|
170
|
+
const renderer = new PuppeteerRenderer();
|
|
171
|
+
let lastLine = '';
|
|
172
|
+
const result = await renderer.render(manifest, {
|
|
173
|
+
gameUrl: args.gameUrl,
|
|
174
|
+
outputPath: path.resolve(args.output),
|
|
175
|
+
width: args.width,
|
|
176
|
+
height: args.height,
|
|
177
|
+
fps: args.fps,
|
|
178
|
+
secondsPerAge: args.secondsPerAge,
|
|
179
|
+
useHardwareAcceleration: args.useHardwareAcceleration,
|
|
180
|
+
keepTempFiles: args.keepTemp,
|
|
181
|
+
onProgress: (progress) => {
|
|
182
|
+
const line = formatProgress(progress);
|
|
183
|
+
if (line !== lastLine) {
|
|
184
|
+
process.stdout.write(`\r${line}`);
|
|
185
|
+
lastLine = line;
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
console.log('\n');
|
|
190
|
+
if (result.success) {
|
|
191
|
+
console.log('✅ Render completed successfully!');
|
|
192
|
+
console.log(` Output: ${result.outputPath}`);
|
|
193
|
+
console.log(` Duration: ${result.duration?.toFixed(1)}s`);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
console.error('❌ Render failed:', result.error);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
console.error('❌ Error:', error instanceof Error ? error.message : error);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
main();
|
|
206
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/cli/render.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAkB,MAAM,kCAAkC,CAAC;AAiBrF,SAAS,SAAS;IACd,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAY;QACpB,MAAM,EAAE,cAAc;QACtB,OAAO,EAAE,uBAAuB;QAChC,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,IAAI;QACZ,GAAG,EAAE,EAAE;QACP,aAAa,EAAE,GAAG;QAClB,QAAQ,EAAE,KAAK;QACf,uBAAuB,EAAE,KAAK;QAC9B,IAAI,EAAE,KAAK;KACd,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAEzB,QAAQ,GAAG,EAAE,CAAC;YACV,KAAK,YAAY,CAAC;YAClB,KAAK,IAAI;gBACL,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACvB,CAAC,EAAE,CAAC;gBACJ,MAAM;YACV,KAAK,gBAAgB;gBACjB,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC;gBAC1B,CAAC,EAAE,CAAC;gBACJ,MAAM;YACV,KAAK,UAAU,CAAC;YAChB,KAAK,IAAI;gBACL,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;gBACrB,CAAC,EAAE,CAAC;gBACJ,MAAM;YACV,KAAK,YAAY,CAAC;YAClB,KAAK,IAAI;gBACL,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;gBACtB,CAAC,EAAE,CAAC;gBACJ,MAAM;YACV,KAAK,SAAS;gBACV,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAClC,CAAC,EAAE,CAAC;gBACJ,MAAM;YACV,KAAK,UAAU;gBACX,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACnC,CAAC,EAAE,CAAC;gBACJ,MAAM;YACV,KAAK,OAAO;gBACR,MAAM,CAAC,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAChC,CAAC,EAAE,CAAC;gBACJ,MAAM;YACV,KAAK,mBAAmB;gBACpB,MAAM,CAAC,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;gBACxC,CAAC,EAAE,CAAC;gBACJ,MAAM;YACV,KAAK,aAAa;gBACd,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACvB,MAAM;YACV,KAAK,6BAA6B,CAAC;YACnC,KAAK,SAAS;gBACV,MAAM,CAAC,uBAAuB,GAAG,IAAI,CAAC;gBACtC,MAAM;YACV,KAAK,QAAQ,CAAC;YACd,KAAK,IAAI;gBACL,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;gBACnB,MAAM;QACd,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,SAAS;IACd,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Bf,CAAC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAa;IACrC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,4BAA4B,YAAY,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAClE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,cAAc,CAAC,QAAwB;IAC5C,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,GAAG,CAAC;QAC9B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;QACvD,CAAC,CAAC,CAAC,CAAC;IAER,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAE3F,OAAO,IAAI,GAAG,KAAK,OAAO,OAAO,QAAQ,CAAC,OAAO,EAAE,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,IAAI;IACf,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IAEzB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,SAAS,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5B,IAAI,CAAC;QACD,gBAAgB;QAChB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,eAAe,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,gBAAgB,QAAQ,CAAC,QAAQ,CAAC,MAAM,OAAO,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,kBAAkB,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QAE5D,oBAAoB;QACpB,MAAM,iBAAiB,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,gCAAgC,iBAAiB,GAAG,CAAC,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,0BAA0B;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1D,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAExD,kBAAkB;QAClB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,MAAM,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;QACvG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,MAAM,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAC;QAEzC,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE;YAC3C,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,uBAAuB,EAAE,IAAI,CAAC,uBAAuB;YACrD,aAAa,EAAE,IAAI,CAAC,QAAQ;YAC5B,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE;gBACrB,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;gBACtC,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACpB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;oBAClC,QAAQ,GAAG,IAAI,CAAC;gBACpB,CAAC;YACL,CAAC;SACJ,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAElB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChE,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Puppeteer-based Video Renderer
|
|
3
|
+
*
|
|
4
|
+
* This renderer:
|
|
5
|
+
* 1. Launches a headless browser
|
|
6
|
+
* 2. Opens the game at a special replay URL
|
|
7
|
+
* 3. Injects the replay manifest
|
|
8
|
+
* 4. Captures screenshots as JPEG buffers and streams directly to FFmpeg via stdin
|
|
9
|
+
* 5. Encodes video using libx264 (CPU) by default, or h264_nvenc if explicitly enabled
|
|
10
|
+
*/
|
|
11
|
+
import type { ReplayManifestV1 } from '@agent-foundry/replay';
|
|
12
|
+
export interface RenderConfig {
|
|
13
|
+
/** URL of the game (can be local file:// or http://) */
|
|
14
|
+
gameUrl: string;
|
|
15
|
+
/** Output video path */
|
|
16
|
+
outputPath: string;
|
|
17
|
+
/** Video dimensions */
|
|
18
|
+
width?: number;
|
|
19
|
+
height?: number;
|
|
20
|
+
/** Frames per second */
|
|
21
|
+
fps?: number;
|
|
22
|
+
/** Seconds to display each age */
|
|
23
|
+
secondsPerAge?: number;
|
|
24
|
+
/** Enable hardware acceleration (NVENC). Default: false (uses CPU libx264) */
|
|
25
|
+
useHardwareAcceleration?: boolean;
|
|
26
|
+
/** Temporary directory for screenshots (deprecated, no longer used) */
|
|
27
|
+
tempDir?: string;
|
|
28
|
+
/** Whether to keep temp files after rendering (deprecated, no longer used) */
|
|
29
|
+
keepTempFiles?: boolean;
|
|
30
|
+
/** Callback for progress updates */
|
|
31
|
+
onProgress?: (progress: RenderProgress) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface RenderProgress {
|
|
34
|
+
stage: 'init' | 'capture' | 'encode' | 'complete' | 'error';
|
|
35
|
+
current: number;
|
|
36
|
+
total: number;
|
|
37
|
+
message: string;
|
|
38
|
+
}
|
|
39
|
+
export interface RenderResult {
|
|
40
|
+
success: boolean;
|
|
41
|
+
outputPath?: string;
|
|
42
|
+
duration?: number;
|
|
43
|
+
error?: string;
|
|
44
|
+
}
|
|
45
|
+
export declare class PuppeteerRenderer {
|
|
46
|
+
private browser;
|
|
47
|
+
private page;
|
|
48
|
+
private pageErrors;
|
|
49
|
+
private failedRequests;
|
|
50
|
+
/**
|
|
51
|
+
* Render a replay manifest to video
|
|
52
|
+
*/
|
|
53
|
+
render(manifest: ReplayManifestV1, config: RenderConfig): Promise<RenderResult>;
|
|
54
|
+
private initBrowser;
|
|
55
|
+
private loadGame;
|
|
56
|
+
/**
|
|
57
|
+
* Capture frames and encode video in streaming mode using FFmpeg stdin
|
|
58
|
+
* Frames are captured as JPEG buffers and streamed directly to FFmpeg
|
|
59
|
+
*/
|
|
60
|
+
private captureAndEncodeFrames;
|
|
61
|
+
/**
|
|
62
|
+
* Internal method to capture and encode with a specific encoder
|
|
63
|
+
*/
|
|
64
|
+
private captureAndEncodeFramesWithEncoder;
|
|
65
|
+
/**
|
|
66
|
+
* Launch FFmpeg process with appropriate parameters
|
|
67
|
+
*/
|
|
68
|
+
private launchFFmpeg;
|
|
69
|
+
private closeBrowser;
|
|
70
|
+
private reportProgress;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=PuppeteerRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PuppeteerRenderer.d.ts","sourceRoot":"","sources":["../../src/renderer/PuppeteerRenderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,MAAM,WAAW,YAAY;IACzB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAEhB,wBAAwB;IACxB,UAAU,EAAE,MAAM,CAAC;IAEnB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,8EAA8E;IAC9E,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,oCAAoC;IACpC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAWD,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,cAAc,CAAkD;IAExE;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;YAiDvE,WAAW;YAqDX,QAAQ;IA4FtB;;;OAGG;YACW,sBAAsB;IAYpC;;OAEG;YACW,iCAAiC;IA0K/C;;OAEG;IACH,OAAO,CAAC,YAAY;YA4BN,YAAY;IAQ1B,OAAO,CAAC,cAAc;CAWzB"}
|