@transcodely/sdk 0.2.0 → 0.3.1

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/CHANGELOG.md CHANGED
@@ -4,6 +4,38 @@ All notable changes to the Transcodely JavaScript / TypeScript SDK will be docum
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Breaking changes are allowed on minor bumps until 1.0.0.
6
6
 
7
+ ## [0.3.1](https://github.com/transcodely/transcodely-js/compare/v0.3.0...v0.3.1) (2026-07-29)
8
+
9
+
10
+ ### Features
11
+
12
+ * expose daily usage buckets and webhook endpoint health + event object-id filtering ([#26](https://github.com/transcodely/transcodely-js/issues/26)) ([28d3c77](https://github.com/transcodely/transcodely-js/commit/28d3c775c04dea4d3f8ff5c35b232072e40144f2))
13
+ * post-launch feature program integration (transcodely-js) ([#38](https://github.com/transcodely/transcodely-js/issues/38)) ([c8705ca](https://github.com/transcodely/transcodely-js/commit/c8705ca411d6ad0a0a221fb4d61461b9f963f49a))
14
+ * sync protos with api 3.10 — billing, captions text tracks, app suspension ([#39](https://github.com/transcodely/transcodely-js/issues/39)) ([a0e158c](https://github.com/transcodely/transcodely-js/commit/a0e158ce19f40c0f983ee9bc018f53073b6bdba4))
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * add working eslint setup, correct create-job example shape ([#24](https://github.com/transcodely/transcodely-js/issues/24)) ([d2e40bd](https://github.com/transcodely/transcodely-js/commit/d2e40bd922cd1b453eba903e63e67cacb512c25b))
20
+ * **webhooks:** restore WebhookEvent narrowing via type guards ([#40](https://github.com/transcodely/transcodely-js/issues/40)) ([c5913a3](https://github.com/transcodely/transcodely-js/commit/c5913a311a6efde2d9a29fb53a9ef0f76d5f904a))
21
+
22
+
23
+ ### Documentation
24
+
25
+ * note content-aware encoding is rejected at create ([#30](https://github.com/transcodely/transcodely-js/issues/30)) ([a7da4ec](https://github.com/transcodely/transcodely-js/commit/a7da4ec9474e9754aa30269e5cdeb1dd40af8815))
26
+ * set managed on the README quick start create-job ([#32](https://github.com/transcodely/transcodely-js/issues/32)) ([5cef326](https://github.com/transcodely/transcodely-js/commit/5cef326f2788262204fb1d986eb284f38870dffc))
27
+
28
+ ## [0.3.0](https://github.com/transcodely/transcodely-js/compare/v0.2.0...v0.3.0) (2026-07-15)
29
+
30
+
31
+ ### ⚠ BREAKING CHANGES
32
+
33
+ * App.webhook, CreateAppRequest.webhook, and UpdateAppRequest.webhook (WebhookConfig / CreateWebhookConfig / UpdateWebhookConfig) are removed. App-level webhook configuration is superseded by the WebhookService endpoints API, already exposed in this SDK as client.webhookEndpoints (create / update / rotateSecret / list / sendTest) and client.webhooks.constructEvent for signature verification.
34
+
35
+ ### Features
36
+
37
+ * sync protos — explicit app scoping; remove legacy app webhook config ([#21](https://github.com/transcodely/transcodely-js/issues/21)) ([10b65fe](https://github.com/transcodely/transcodely-js/commit/10b65fece1c090c0298f24ff9f34554fdfbe9bd5))
38
+
7
39
  ## [0.2.0](https://github.com/transcodely/transcodely-js/compare/v0.1.4...v0.2.0) (2026-07-12)
8
40
 
9
41
 
package/README.md CHANGED
@@ -16,6 +16,9 @@ const client = new Transcodely({ apiKey: process.env.TRANSCODELY_API_KEY! });
16
16
  // Create a job
17
17
  const job = await client.jobs.create({
18
18
  inputUrl: "https://example.com/source.mp4",
19
+ // Write outputs to Transcodely-managed storage. Drop `managed` and set
20
+ // `outputOriginId: "ori_..."` to write to your own configured origin.
21
+ managed: true,
19
22
  outputs: [{
20
23
  type: OutputFormat.HLS,
21
24
  video: [
@@ -23,6 +26,10 @@ const job = await client.jobs.create({
23
26
  { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_720P },
24
27
  ],
25
28
  }],
29
+ // Optional: encode only a sub-range of the input. Applies job-wide and
30
+ // reduces cost (billing keys off the produced output duration). Omit
31
+ // `endSeconds` (or leave 0) to encode through to the end of the input.
32
+ clip: { startSeconds: 2, endSeconds: 7 },
26
33
  });
27
34
 
28
35
  console.log(job.id); // "job_a1b2c3d4e5f6"
@@ -34,6 +41,45 @@ for await (const event of client.jobs.watch(job.id)) {
34
41
  }
35
42
  ```
36
43
 
44
+ ## AI captions
45
+
46
+ Add auto-generated captions to any output with a `generate` subtitle track.
47
+ Leave `language` empty (or set `"auto"`) to auto-detect the spoken language, or
48
+ pass an ISO 639-2 code to force one. A per-job fee is metered by source minute
49
+ and surfaced on `job.fees`; the produced captions show up on `job.subtitleResults`
50
+ with `autoGenerated: true`.
51
+
52
+ ```ts
53
+ import { Transcodely, OutputFormat, VideoCodec, Resolution, SubtitleOperation } from "@transcodely/sdk";
54
+
55
+ const client = new Transcodely({ apiKey: process.env.TRANSCODELY_API_KEY! });
56
+
57
+ // Generate captions while transcoding a new source.
58
+ await client.jobs.create({
59
+ inputUrl: "https://example.com/source.mp4",
60
+ managed: true,
61
+ outputs: [{
62
+ type: OutputFormat.HLS,
63
+ video: [{ codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_1080P }],
64
+ subtitleTracks: [{ operation: SubtitleOperation.GENERATE, language: "auto" }],
65
+ }],
66
+ });
67
+
68
+ // Retro-caption a video you've already hosted: reference it by inputVideoId and
69
+ // request a single captions-only output (no video encode).
70
+ const job = await client.jobs.create({
71
+ inputVideoId: "vid_a1b2c3d4e5f6g7",
72
+ outputs: [{ subtitleTracks: [{ operation: SubtitleOperation.GENERATE }] }],
73
+ });
74
+
75
+ for (const result of job.subtitleResults) {
76
+ console.log(result.language, result.autoGenerated, result.url);
77
+ }
78
+ for (const fee of job.fees) {
79
+ console.log(fee.feeType, fee.amount, fee.currency); // "captions" 0.51 "eur"
80
+ }
81
+ ```
82
+
37
83
  ## Authentication
38
84
 
39
85
  Pass your API key in the constructor:
@@ -46,7 +92,7 @@ const client = new Transcodely({ apiKey: process.env.TRANSCODELY_API_KEY! });
46
92
 
47
93
  ```ts
48
94
  client.jobs // create / get / list / cancel / confirm / watch
49
- client.videos // upload helpers, multipart, get / list / update / delete / watch
95
+ client.videos // upload helpers, multipart, createFromUrl, get / list / update / delete / watch / getStats / listTopVideos
50
96
  client.presets // create / get / getBySlug / list / update / duplicate / archive
51
97
  client.origins // create / get / list / update / validate / archive
52
98
  client.apps // create / get / list / update / archive / enableHosting
@@ -174,17 +220,22 @@ app.post(
174
220
  process.env.WEBHOOK_SECRET!,
175
221
  );
176
222
 
177
- switch (event.type) {
178
- case "job.succeeded":
179
- // event.data is a fully-typed Job
180
- console.log("Job done:", event.data.id);
181
- break;
182
- case "video.uploaded":
183
- console.log("Video uploaded:", event.data.id);
184
- break;
185
- default:
186
- // Forward-compat: unknown types still parse.
187
- console.log("Unhandled:", event.type);
223
+ // `isKnownEvent` narrows `event` to the events this SDK types precisely,
224
+ // so inside the switch `event.data` is the exact resource — no casts.
225
+ if (client.webhooks.isKnownEvent(event)) {
226
+ switch (event.type) {
227
+ case "job.succeeded":
228
+ console.log("Job done:", event.data.id); // event.data is a fully-typed Job
229
+ break;
230
+ case "video.uploaded":
231
+ console.log("Video uploaded:", event.data.id); // event.data is a Video
232
+ break;
233
+ // ...handle the other known types you care about
234
+ }
235
+ } else {
236
+ // Forward-compat: an event type added to the API after this SDK
237
+ // release still verifies and parses; `event.data` is raw `unknown`.
238
+ console.log("Unhandled future type:", event.type);
188
239
  }
189
240
  res.sendStatus(200);
190
241
  } catch (err) {
@@ -200,6 +251,21 @@ app.post(
200
251
 
201
252
  The signed payload is the **raw HTTP body** — use `express.raw()` (or the equivalent in your framework) to receive a `Buffer`, never `express.json()`.
202
253
 
254
+ #### Narrowing the event
255
+
256
+ `constructEvent` (and `client.events.retrieve` / `.list`) return a `WebhookEvent`: the closed, precisely-typed `KnownWebhookEvent` union **plus** an open `UnknownWebhookEvent` arm (`type: string; data: unknown`) so a payload for an event type added after this SDK release still verifies and parses instead of being dropped. That open arm means a bare `switch (event.type)` can't narrow `event.data` on its own — funnel through one of two guards first:
257
+
258
+ - **`isKnownEvent(event)`** narrows to `KnownWebhookEvent`, re-enabling a `switch (event.type)` where every `case` narrows `event.data` to the right resource (and TypeScript flags a `case` you left out if you keep the switch exhaustive). The `else` branch is your forward-compat handler.
259
+ - **`isEventType(event, "job.succeeded")`** narrows to a single event type — ideal for a receiver that only cares about one or two:
260
+
261
+ ```ts
262
+ if (client.webhooks.isEventType(event, "output.ready")) {
263
+ console.log(event.data.outputUrl); // event.data is a fully-typed JobOutput
264
+ }
265
+ ```
266
+
267
+ Both are also exported standalone (`import { isKnownEvent, isEventType } from "@transcodely/sdk"`) for code that doesn't hold a client. `WebhookEvent`, `KnownWebhookEvent`, and `UnknownWebhookEvent` are all exported for annotating your own handler signatures.
268
+
203
269
  Every event carries a `request` object. Events emitted **inside** an API request scope (e.g. `job.created`, from your `jobs.create` call) set `request.id` to the originating `req_*` ID. Events emitted **outside** a request scope — every worker-driven `job.*` / `output.*` event (`job.succeeded`, `job.failed`, `job.canceled`, `job.progress`, `output.ready`, …) — set `request.id` to `null`. `request.idempotencyKey` is `null` whenever the originating request didn't supply one.
204
270
 
205
271
  `constructEvent` accepts `request.id: null` from **v0.1.3** onward. v0.1.2 and earlier rejected such deliveries with a `WebhookPayloadError` — upgrade if you validate worker-driven events.