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