@stack0/sdk 0.5.16 → 0.5.17
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 +27 -2
- package/dist/cdn/index.d.mts +130 -9
- package/dist/cdn/index.d.ts +130 -9
- package/dist/cdn/index.js +71 -5
- package/dist/cdn/index.js.map +1 -1
- package/dist/cdn/index.mjs +71 -5
- package/dist/cdn/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +71 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +71 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1430,7 +1430,12 @@ var CDN = class {
|
|
|
1430
1430
|
return this.http.get(`/cdn/video/${assetId}/stream`);
|
|
1431
1431
|
}
|
|
1432
1432
|
/**
|
|
1433
|
-
*
|
|
1433
|
+
* Get the thumbnail at a specific timestamp, generating it on miss
|
|
1434
|
+
*
|
|
1435
|
+
* If no thumbnail exists at that timestamp yet, generation is queued
|
|
1436
|
+
* automatically and a response with `status: "pending"` (null url) is
|
|
1437
|
+
* returned. Poll until `status` is "ready", or use
|
|
1438
|
+
* {@link getThumbnailAndWait} to do that for you.
|
|
1434
1439
|
*
|
|
1435
1440
|
* @example
|
|
1436
1441
|
* ```typescript
|
|
@@ -1440,7 +1445,9 @@ var CDN = class {
|
|
|
1440
1445
|
* width: 320,
|
|
1441
1446
|
* format: 'webp',
|
|
1442
1447
|
* });
|
|
1443
|
-
*
|
|
1448
|
+
* if (thumbnail.status === 'ready') {
|
|
1449
|
+
* console.log(`Thumbnail URL: ${thumbnail.url}`);
|
|
1450
|
+
* }
|
|
1444
1451
|
* ```
|
|
1445
1452
|
*/
|
|
1446
1453
|
async getThumbnail(request) {
|
|
@@ -1450,20 +1457,52 @@ var CDN = class {
|
|
|
1450
1457
|
if (request.format) params.set("format", request.format);
|
|
1451
1458
|
return this.http.get(`/cdn/video/thumbnail/${request.assetId}?${params.toString()}`);
|
|
1452
1459
|
}
|
|
1460
|
+
/**
|
|
1461
|
+
* Get the thumbnail at a specific timestamp, waiting for generation to complete
|
|
1462
|
+
*
|
|
1463
|
+
* Calls {@link getThumbnail} and polls until the thumbnail is ready.
|
|
1464
|
+
*
|
|
1465
|
+
* @example
|
|
1466
|
+
* ```typescript
|
|
1467
|
+
* const thumbnail = await cdn.getThumbnailAndWait({
|
|
1468
|
+
* assetId: 'video-asset-id',
|
|
1469
|
+
* timestamp: 3.5,
|
|
1470
|
+
* });
|
|
1471
|
+
* console.log(`Thumbnail URL: ${thumbnail.url}`);
|
|
1472
|
+
* ```
|
|
1473
|
+
*/
|
|
1474
|
+
async getThumbnailAndWait(request, options = {}) {
|
|
1475
|
+
const { pollInterval = 1e3, timeout = 6e4 } = options;
|
|
1476
|
+
const startTime = Date.now();
|
|
1477
|
+
while (true) {
|
|
1478
|
+
const thumbnail = await this.getThumbnail(request);
|
|
1479
|
+
if (thumbnail.status === "ready") {
|
|
1480
|
+
return thumbnail;
|
|
1481
|
+
}
|
|
1482
|
+
if (Date.now() - startTime >= timeout) {
|
|
1483
|
+
throw new Error("Thumbnail generation timed out");
|
|
1484
|
+
}
|
|
1485
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1453
1488
|
/**
|
|
1454
1489
|
* Regenerate a thumbnail for a video (force regeneration even if one exists)
|
|
1455
1490
|
*
|
|
1456
|
-
* Useful for retrying failed thumbnail generation or regenerating with
|
|
1491
|
+
* Useful for retrying failed thumbnail generation or regenerating with
|
|
1492
|
+
* different settings. Regeneration is async: poll {@link getThumbnail} (or
|
|
1493
|
+
* use {@link getThumbnailAndWait}) at the same timestamp until the new
|
|
1494
|
+
* frame is ready.
|
|
1457
1495
|
*
|
|
1458
1496
|
* @example
|
|
1459
1497
|
* ```typescript
|
|
1460
|
-
*
|
|
1498
|
+
* await cdn.regenerateThumbnail({
|
|
1461
1499
|
* assetId: 'video-asset-id',
|
|
1462
1500
|
* timestamp: 5, // 5 seconds into the video
|
|
1463
1501
|
* width: 1280,
|
|
1464
1502
|
* format: 'jpg',
|
|
1465
1503
|
* });
|
|
1466
|
-
*
|
|
1504
|
+
* const thumbnail = await cdn.getThumbnailAndWait({ assetId: 'video-asset-id', timestamp: 5 });
|
|
1505
|
+
* console.log(`Thumbnail URL: ${thumbnail.url}`);
|
|
1467
1506
|
* ```
|
|
1468
1507
|
*/
|
|
1469
1508
|
async regenerateThumbnail(request) {
|
|
@@ -2088,6 +2127,33 @@ var CDN = class {
|
|
|
2088
2127
|
* });
|
|
2089
2128
|
* console.log(`Merge job started: ${job.id}`);
|
|
2090
2129
|
* ```
|
|
2130
|
+
*
|
|
2131
|
+
* @example Composite a screen recording onto a held phone ("POV holding my phone"):
|
|
2132
|
+
* ```typescript
|
|
2133
|
+
* const job = await cdn.createMergeJob({
|
|
2134
|
+
* projectSlug: 'my-project',
|
|
2135
|
+
* inputs: [
|
|
2136
|
+
* { assetId: 'reaction-clip-id' },
|
|
2137
|
+
* {
|
|
2138
|
+
* assetId: 'app-recording-id', // the overlay clip
|
|
2139
|
+
* composite: {
|
|
2140
|
+
* backgroundAssetId: 'holding-phone-shot-id', // image or video
|
|
2141
|
+
* // Corner-pin onto the angled screen (background pixel coords, TL/TR/BL/BR)
|
|
2142
|
+
* quad: {
|
|
2143
|
+
* topLeft: { x: 320, y: 480 },
|
|
2144
|
+
* topRight: { x: 760, y: 500 },
|
|
2145
|
+
* bottomLeft: { x: 300, y: 1400 },
|
|
2146
|
+
* bottomRight: { x: 740, y: 1440 },
|
|
2147
|
+
* },
|
|
2148
|
+
* fit: 'cover',
|
|
2149
|
+
* // Screen area painted #F500FA in the background is keyed out, so the
|
|
2150
|
+
* // recording shows through and fingers over the screen occlude it
|
|
2151
|
+
* chromaKey: { color: '#F500FA', similarity: 0.34, blend: 0.06 },
|
|
2152
|
+
* },
|
|
2153
|
+
* },
|
|
2154
|
+
* ],
|
|
2155
|
+
* });
|
|
2156
|
+
* ```
|
|
2091
2157
|
*/
|
|
2092
2158
|
async createMergeJob(request) {
|
|
2093
2159
|
const response = await this.http.post("/cdn/video/merge", request);
|