agentreel 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/bin/agentreel.mjs +55 -46
- package/package.json +1 -1
- package/src/CastVideo.tsx +2 -2
package/README.md
CHANGED
package/bin/agentreel.mjs
CHANGED
|
@@ -280,11 +280,15 @@ async function renderVideo(props, output, musicPath) {
|
|
|
280
280
|
webpackOverride: (config) => config,
|
|
281
281
|
});
|
|
282
282
|
|
|
283
|
-
console.error("
|
|
283
|
+
console.error(" Preparing renderer...");
|
|
284
284
|
const composition = await selectComposition({
|
|
285
285
|
serveUrl,
|
|
286
286
|
id: "CastVideo",
|
|
287
287
|
inputProps: props,
|
|
288
|
+
onBrowserDownload: () => {
|
|
289
|
+
console.error(" Downloading renderer (one-time, ~90MB)...");
|
|
290
|
+
return () => {}; // suppress progress logs
|
|
291
|
+
},
|
|
288
292
|
});
|
|
289
293
|
|
|
290
294
|
console.error(" Rendering...");
|
|
@@ -302,46 +306,40 @@ async function renderVideo(props, output, musicPath) {
|
|
|
302
306
|
|
|
303
307
|
// ── Upload + Share ──────────────────────────────────────────
|
|
304
308
|
|
|
305
|
-
async function
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
].join(CRLF);
|
|
323
|
-
|
|
324
|
-
const footer = `${CRLF}--${boundary}--${CRLF}`;
|
|
325
|
-
|
|
326
|
-
const headerBuf = Buffer.from(header + CRLF);
|
|
327
|
-
const footerBuf = Buffer.from(footer);
|
|
328
|
-
const body = Buffer.concat([headerBuf, fileBuffer, footerBuf]);
|
|
329
|
-
|
|
330
|
-
const resp = await fetch("https://api.streamable.com/upload", {
|
|
331
|
-
method: "POST",
|
|
332
|
-
headers: {
|
|
333
|
-
"Content-Type": `multipart/form-data; boundary=${boundary}`,
|
|
334
|
-
},
|
|
335
|
-
body,
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
if (!resp.ok) {
|
|
339
|
-
const text = await resp.text();
|
|
340
|
-
throw new Error(`Streamable upload failed (${resp.status}): ${text}`);
|
|
309
|
+
async function uploadVideo(filePath) {
|
|
310
|
+
// Try uploading via curl to Streamable (works if user has STREAMABLE_EMAIL/PASSWORD set)
|
|
311
|
+
const email = process.env.STREAMABLE_EMAIL;
|
|
312
|
+
const password = process.env.STREAMABLE_PASSWORD;
|
|
313
|
+
|
|
314
|
+
if (email && password) {
|
|
315
|
+
try {
|
|
316
|
+
const result = execFileSync("curl", [
|
|
317
|
+
"-s", "-u", `${email}:${password}`,
|
|
318
|
+
"-F", `file=@${filePath}`,
|
|
319
|
+
"https://api.streamable.com/upload",
|
|
320
|
+
], { timeout: 60000 });
|
|
321
|
+
const data = JSON.parse(result.toString());
|
|
322
|
+
if (data.shortcode) {
|
|
323
|
+
return `https://streamable.com/${data.shortcode}`;
|
|
324
|
+
}
|
|
325
|
+
} catch { /* fall through */ }
|
|
341
326
|
}
|
|
342
327
|
|
|
343
|
-
|
|
344
|
-
|
|
328
|
+
// Try Imgur as fallback (supports anonymous video upload)
|
|
329
|
+
try {
|
|
330
|
+
const result = execFileSync("curl", [
|
|
331
|
+
"-s",
|
|
332
|
+
"-H", "Authorization: Client-ID 546c25a59c58ad7",
|
|
333
|
+
"-F", `video=@${filePath}`,
|
|
334
|
+
"https://api.imgur.com/3/upload",
|
|
335
|
+
], { timeout: 120000 });
|
|
336
|
+
const data = JSON.parse(result.toString());
|
|
337
|
+
if (data.data?.link) {
|
|
338
|
+
return data.data.link;
|
|
339
|
+
}
|
|
340
|
+
} catch { /* fall through */ }
|
|
341
|
+
|
|
342
|
+
return null;
|
|
345
343
|
}
|
|
346
344
|
|
|
347
345
|
function openShareURL(videoURL, text) {
|
|
@@ -375,14 +373,25 @@ async function shareFlow(outputPath, title) {
|
|
|
375
373
|
const shouldShare = await askYesNo("Share to Twitter? [Y/n] ");
|
|
376
374
|
if (!shouldShare) return;
|
|
377
375
|
|
|
378
|
-
console.error("Uploading
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
376
|
+
console.error("Uploading video...");
|
|
377
|
+
const url = await uploadVideo(outputPath);
|
|
378
|
+
|
|
379
|
+
if (url) {
|
|
380
|
+
const text = `${title}\n\nMade with agentreel`;
|
|
382
381
|
openShareURL(url, text);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
console.error("
|
|
382
|
+
} else {
|
|
383
|
+
// No upload worked — open Twitter with just the text, user attaches video manually
|
|
384
|
+
console.error("Could not auto-upload. Opening Twitter — drag your video into the tweet.");
|
|
385
|
+
const text = `${title}\n\nMade with agentreel`;
|
|
386
|
+
const tweetText = encodeURIComponent(text);
|
|
387
|
+
const intentURL = `https://twitter.com/intent/tweet?text=${tweetText}`;
|
|
388
|
+
const cmd = process.platform === "darwin" ? "open" : "xdg-open";
|
|
389
|
+
try {
|
|
390
|
+
execFileSync(cmd, [intentURL], { stdio: "ignore" });
|
|
391
|
+
} catch {
|
|
392
|
+
console.error(` Tweet link: ${intentURL}`);
|
|
393
|
+
}
|
|
394
|
+
console.error(` Video: ${resolve(outputPath)}`);
|
|
386
395
|
}
|
|
387
396
|
}
|
|
388
397
|
|
package/package.json
CHANGED
package/src/CastVideo.tsx
CHANGED
|
@@ -115,7 +115,7 @@ export const CastVideo: React.FC<CastProps> = ({
|
|
|
115
115
|
letterSpacing: 2,
|
|
116
116
|
}}
|
|
117
117
|
>
|
|
118
|
-
made with
|
|
118
|
+
made with agentreel
|
|
119
119
|
</div>
|
|
120
120
|
|
|
121
121
|
<MusicTrack />
|
|
@@ -1010,7 +1010,7 @@ const EndCard: React.FC<{ text: string; url?: string }> = ({ text, url }) => {
|
|
|
1010
1010
|
letterSpacing: 3,
|
|
1011
1011
|
}}
|
|
1012
1012
|
>
|
|
1013
|
-
made with
|
|
1013
|
+
made with agentreel
|
|
1014
1014
|
</div>
|
|
1015
1015
|
</AbsoluteFill>
|
|
1016
1016
|
);
|