@transcodely/sdk 0.3.12 → 0.3.13

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,13 @@ 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.13](https://github.com/transcodely/transcodely-js/compare/v0.3.12...v0.3.13) (2026-10-26)
8
+
9
+
10
+ ### Features
11
+
12
+ * generate_insights from existing captions (api 5.26.0) ([#82](https://github.com/transcodely/transcodely-js/issues/82)) ([a3b4a8d](https://github.com/transcodely/transcodely-js/commit/a3b4a8da9db11748db6f9b9dd34900fb18b5e2be))
13
+
7
14
  ## [0.3.12](https://github.com/transcodely/transcodely-js/compare/v0.3.11...v0.3.12) (2026-10-25)
8
15
 
9
16
 
package/README.md CHANGED
@@ -282,6 +282,20 @@ Jobs carry the same data on `job.subtitleResults[i].transcriptRenditions` and
282
282
  `job.insights`. The `job.insights.ready` and `job.insights.failed` webhook events
283
283
  tell you when an insights pass finishes.
284
284
 
285
+ A hosted video that already has AI captions can get insights without
286
+ transcribing again (EUR 0.02 per video + EUR 0.005 per source minute, charged
287
+ only when ready):
288
+
289
+ ```ts
290
+ // `language` is needed only when the video has several AI caption tracks.
291
+ const ins = await client.videos.generateInsights({ id: "vid_a1b2c3d4e5f6g7" });
292
+ console.log(ins.id, ins.status); // ins_..., InsightsStatus.PENDING
293
+ ```
294
+
295
+ The entry also appears on `video.insights`. The `video.insights.ready` and
296
+ `video.insights.failed` webhook events carry the entry itself as a
297
+ `TranscriptInsights` in `event.data`.
298
+
285
299
  ## Authentication
286
300
 
287
301
  Pass your API key in the constructor:
package/dist/index.cjs CHANGED
@@ -4428,6 +4428,7 @@ var WebhookEndpoint = class _WebhookEndpoint extends protobuf.Message {
4428
4428
  * "job.insights.failed", "output.created", "output.ready",
4429
4429
  * "output.failed", "output.progress", "video.uploaded", "video.ready",
4430
4430
  * "video.failed", "video.deleted", "video.source_scheduled_for_deletion",
4431
+ * "video.insights.ready", "video.insights.failed",
4431
4432
  * "app.created", "app.updated", "app.spend_limit_warning",
4432
4433
  * "app.spend_limit_exceeded", or "*".
4433
4434
  * Keep in sync with domain.WebhookEventTypes() ("job.updated" does not exist).
@@ -7363,6 +7364,17 @@ protobuf.proto3.util.setEnumType(TranscriptFormat, "transcodely.v1.TranscriptFor
7363
7364
  { no: 2, name: "TRANSCRIPT_FORMAT_TXT" },
7364
7365
  { no: 3, name: "TRANSCRIPT_FORMAT_MD" }
7365
7366
  ]);
7367
+ var InsightsSource = /* @__PURE__ */ ((InsightsSource2) => {
7368
+ InsightsSource2[InsightsSource2["UNSPECIFIED"] = 0] = "UNSPECIFIED";
7369
+ InsightsSource2[InsightsSource2["JOB"] = 1] = "JOB";
7370
+ InsightsSource2[InsightsSource2["VIDEO"] = 2] = "VIDEO";
7371
+ return InsightsSource2;
7372
+ })(InsightsSource || {});
7373
+ protobuf.proto3.util.setEnumType(InsightsSource, "transcodely.v1.InsightsSource", [
7374
+ { no: 0, name: "INSIGHTS_SOURCE_UNSPECIFIED" },
7375
+ { no: 1, name: "INSIGHTS_SOURCE_JOB" },
7376
+ { no: 2, name: "INSIGHTS_SOURCE_VIDEO" }
7377
+ ]);
7366
7378
  var InsightsStatus = /* @__PURE__ */ ((InsightsStatus2) => {
7367
7379
  InsightsStatus2[InsightsStatus2["UNSPECIFIED"] = 0] = "UNSPECIFIED";
7368
7380
  InsightsStatus2[InsightsStatus2["PENDING"] = 1] = "PENDING";
@@ -8255,7 +8267,8 @@ var InsightsHighlight = class _InsightsHighlight extends protobuf.Message {
8255
8267
  };
8256
8268
  var TranscriptInsights = class _TranscriptInsights extends protobuf.Message {
8257
8269
  /**
8258
- * The out_… output the generate track was configured on.
8270
+ * The out_… output the generate track was configured on. Empty for source
8271
+ * "video".
8259
8272
  *
8260
8273
  * @generated from field: string output_id = 1;
8261
8274
  */
@@ -8400,6 +8413,38 @@ var TranscriptInsights = class _TranscriptInsights extends protobuf.Message {
8400
8413
  * @generated from field: string hint = 23;
8401
8414
  */
8402
8415
  hint = "";
8416
+ /**
8417
+ * Unique identifier of this insights entry (ins_…).
8418
+ *
8419
+ * @generated from field: string id = 24;
8420
+ */
8421
+ id = "";
8422
+ /**
8423
+ * job | video: requested on a captions job, or on a hosted video's existing
8424
+ * captions with VideoService.GenerateInsights.
8425
+ *
8426
+ * @generated from field: transcodely.v1.InsightsSource source = 25;
8427
+ */
8428
+ source = 0 /* UNSPECIFIED */;
8429
+ /**
8430
+ * The hosted video (vid_…) the insights belong to, for source "video".
8431
+ * Empty for source "job" (see Video.insights for a hosted video's
8432
+ * job-sourced insights).
8433
+ *
8434
+ * @generated from field: string video_id = 26;
8435
+ */
8436
+ videoId = "";
8437
+ /**
8438
+ * Price of this entry in EUR, for source "video": EUR 0.02 per video plus
8439
+ * EUR 0.005 per minute of source, fixed when the entry was created. Charged
8440
+ * only when status becomes "ready"; nothing is charged when it fails. An
8441
+ * entry that becomes "ready" after a newer entry for the same language was
8442
+ * already shown on the video is not charged either, and shows 0.
8443
+ * Absent for source "job", whose insights fees are listed on Job.fees.
8444
+ *
8445
+ * @generated from field: optional double fee_eur = 27;
8446
+ */
8447
+ feeEur;
8403
8448
  constructor(data) {
8404
8449
  super();
8405
8450
  protobuf.proto3.util.initPartial(data, this);
@@ -8495,7 +8540,23 @@ var TranscriptInsights = class _TranscriptInsights extends protobuf.Message {
8495
8540
  kind: "scalar",
8496
8541
  T: 9
8497
8542
  /* ScalarType.STRING */
8498
- }
8543
+ },
8544
+ {
8545
+ no: 24,
8546
+ name: "id",
8547
+ kind: "scalar",
8548
+ T: 9
8549
+ /* ScalarType.STRING */
8550
+ },
8551
+ { no: 25, name: "source", kind: "enum", T: protobuf.proto3.getEnumType(InsightsSource) },
8552
+ {
8553
+ no: 26,
8554
+ name: "video_id",
8555
+ kind: "scalar",
8556
+ T: 9
8557
+ /* ScalarType.STRING */
8558
+ },
8559
+ { no: 27, name: "fee_eur", kind: "scalar", T: 1, opt: true }
8499
8560
  ]);
8500
8561
  static fromBinary(bytes, options) {
8501
8562
  return new _TranscriptInsights().fromBinary(bytes, options);
@@ -14306,7 +14367,8 @@ var CreateJobRequest = class _CreateJobRequest extends protobuf.Message {
14306
14367
  * Optional target app. API-key callers may omit it (their key's app is used)
14307
14368
  * or pass their own app; a different app is rejected with PermissionDenied.
14308
14369
  * Portal/JWT callers pass it to create in a specific app in their org;
14309
- * omitted selects the org's first active app.
14370
+ * omitted selects the org's first active app, or, when input_video_id
14371
+ * names a video in the org, that video's app.
14310
14372
  *
14311
14373
  * @generated from field: optional string app_id = 21;
14312
14374
  */
@@ -14979,9 +15041,14 @@ var Video = class _Video extends protobuf.Message {
14979
15041
  textTracks = [];
14980
15042
  /**
14981
15043
  * AI insights for this video, one per transcript language, from the
14982
- * captions job that requested them (SubtitleTrack.insights). Each moves
14983
- * from "pending" to "ready" or "failed". Signed URLs are computed per
14984
- * request under the same rules as text track URLs and are never stored.
15044
+ * captions job that requested them (SubtitleTrack.insights) or from
15045
+ * GenerateInsights. Each moves from "pending" to "ready" or "failed". A
15046
+ * GenerateInsights entry still pending for a language that already has
15047
+ * ready insights is listed first, ahead of the ready entry it will replace.
15048
+ * If that entry fails, the ready insights stay and the failed entry is no
15049
+ * longer listed; video.insights.failed reports it.
15050
+ * Signed URLs are computed per request under the same rules as text track
15051
+ * URLs and are never stored.
14985
15052
  *
14986
15053
  * @generated from field: repeated transcodely.v1.TranscriptInsights insights = 53;
14987
15054
  */
@@ -15024,12 +15091,13 @@ var Video = class _Video extends protobuf.Message {
15024
15091
  /**
15025
15092
  * Everything this video has cost, in EUR: the sum of the settled totals of
15026
15093
  * every job billed for it — the transcode that produced it plus any later
15027
- * job that took it as input (retro captions, for example).
15094
+ * job that took it as input (retro captions, for example) — plus the fee of
15095
+ * every ready GenerateInsights entry (TranscriptInsights.fee_eur).
15028
15096
  *
15029
15097
  * This is the authoritative per-video figure and the one to display. It is
15030
- * built from the same job totals the billing ledger is written from, so it
15098
+ * built from the same amounts the billing ledger is written from, so it
15031
15099
  * reconciles with the invoice; captions_cost is a breakdown inside it.
15032
- * Absent while no linked job has settled yet.
15100
+ * Absent while nothing linked to the video has been billed yet.
15033
15101
  *
15034
15102
  * @generated from field: optional double total_cost = 52;
15035
15103
  */
@@ -17790,6 +17858,100 @@ var GetSeoMarkupResponse = class _GetSeoMarkupResponse extends protobuf.Message
17790
17858
  return protobuf.proto3.util.equals(_GetSeoMarkupResponse, a, b);
17791
17859
  }
17792
17860
  };
17861
+ var GenerateInsightsRequest = class _GenerateInsightsRequest extends protobuf.Message {
17862
+ /**
17863
+ * Video ID.
17864
+ *
17865
+ * @generated from field: string id = 1;
17866
+ */
17867
+ id = "";
17868
+ /**
17869
+ * ISO 639-2 language of the AI caption track to use (e.g. "eng"). Optional
17870
+ * when the video has exactly one AI caption track; required when it has
17871
+ * several (refused with code parameter_required, listing the available
17872
+ * languages).
17873
+ *
17874
+ * @generated from field: optional string language = 2;
17875
+ */
17876
+ language;
17877
+ /**
17878
+ * Optional free-text guidance about the content, its audience or the tone
17879
+ * you want, at most 300 characters. Same meaning as InsightsOptions.hint.
17880
+ *
17881
+ * @generated from field: optional string hint = 3;
17882
+ */
17883
+ hint;
17884
+ /**
17885
+ * Optional app the video belongs to. API-key callers may omit it (their
17886
+ * key's app is used) or pass their own app; a different app is rejected
17887
+ * with PermissionDenied. Portal/JWT callers may pass it; omitted, the app
17888
+ * is resolved from the video.
17889
+ *
17890
+ * @generated from field: optional string app_id = 4;
17891
+ */
17892
+ appId;
17893
+ constructor(data) {
17894
+ super();
17895
+ protobuf.proto3.util.initPartial(data, this);
17896
+ }
17897
+ static runtime = protobuf.proto3;
17898
+ static typeName = "transcodely.v1.GenerateInsightsRequest";
17899
+ static fields = protobuf.proto3.util.newFieldList(() => [
17900
+ {
17901
+ no: 1,
17902
+ name: "id",
17903
+ kind: "scalar",
17904
+ T: 9
17905
+ /* ScalarType.STRING */
17906
+ },
17907
+ { no: 2, name: "language", kind: "scalar", T: 9, opt: true },
17908
+ { no: 3, name: "hint", kind: "scalar", T: 9, opt: true },
17909
+ { no: 4, name: "app_id", kind: "scalar", T: 9, opt: true }
17910
+ ]);
17911
+ static fromBinary(bytes, options) {
17912
+ return new _GenerateInsightsRequest().fromBinary(bytes, options);
17913
+ }
17914
+ static fromJson(jsonValue, options) {
17915
+ return new _GenerateInsightsRequest().fromJson(jsonValue, options);
17916
+ }
17917
+ static fromJsonString(jsonString, options) {
17918
+ return new _GenerateInsightsRequest().fromJsonString(jsonString, options);
17919
+ }
17920
+ static equals(a, b) {
17921
+ return protobuf.proto3.util.equals(_GenerateInsightsRequest, a, b);
17922
+ }
17923
+ };
17924
+ var GenerateInsightsResponse = class _GenerateInsightsResponse extends protobuf.Message {
17925
+ /**
17926
+ * The insights entry: newly created, or the one already pending for this
17927
+ * video and language. Status is "pending"; poll VideoService.Get (or
17928
+ * Watch) or subscribe to video.insights.ready / video.insights.failed.
17929
+ *
17930
+ * @generated from field: transcodely.v1.TranscriptInsights insights = 1;
17931
+ */
17932
+ insights;
17933
+ constructor(data) {
17934
+ super();
17935
+ protobuf.proto3.util.initPartial(data, this);
17936
+ }
17937
+ static runtime = protobuf.proto3;
17938
+ static typeName = "transcodely.v1.GenerateInsightsResponse";
17939
+ static fields = protobuf.proto3.util.newFieldList(() => [
17940
+ { no: 1, name: "insights", kind: "message", T: TranscriptInsights }
17941
+ ]);
17942
+ static fromBinary(bytes, options) {
17943
+ return new _GenerateInsightsResponse().fromBinary(bytes, options);
17944
+ }
17945
+ static fromJson(jsonValue, options) {
17946
+ return new _GenerateInsightsResponse().fromJson(jsonValue, options);
17947
+ }
17948
+ static fromJsonString(jsonString, options) {
17949
+ return new _GenerateInsightsResponse().fromJsonString(jsonString, options);
17950
+ }
17951
+ static equals(a, b) {
17952
+ return protobuf.proto3.util.equals(_GenerateInsightsResponse, a, b);
17953
+ }
17954
+ };
17793
17955
 
17794
17956
  // src/webhooks/types.ts
17795
17957
  var WEBHOOK_EVENT_TYPES = [
@@ -17809,6 +17971,8 @@ var WEBHOOK_EVENT_TYPES = [
17809
17971
  "video.failed",
17810
17972
  "video.deleted",
17811
17973
  "video.source_scheduled_for_deletion",
17974
+ "video.insights.ready",
17975
+ "video.insights.failed",
17812
17976
  "app.created",
17813
17977
  "app.updated",
17814
17978
  "app.spend_limit_warning",
@@ -17831,8 +17995,14 @@ var NOTIFICATION_EVENT_TYPES = /* @__PURE__ */ new Set([
17831
17995
  "app.spend_limit_warning",
17832
17996
  "app.spend_limit_exceeded"
17833
17997
  ]);
17998
+ var EXACT_TYPE_DECODERS = /* @__PURE__ */ new Map([
17999
+ ["video.insights.ready", (json) => fromJson(json, TranscriptInsights)],
18000
+ ["video.insights.failed", (json) => fromJson(json, TranscriptInsights)]
18001
+ ]);
17834
18002
  function decoderForType(type) {
17835
18003
  if (NOTIFICATION_EVENT_TYPES.has(type)) return void 0;
18004
+ const exact = EXACT_TYPE_DECODERS.get(type);
18005
+ if (exact) return exact;
17836
18006
  for (const entry of RESOURCE_DECODERS) {
17837
18007
  if (type.startsWith(entry.prefix)) return entry.decode;
17838
18008
  }
@@ -19982,7 +20152,7 @@ function backoff(attempt) {
19982
20152
  }
19983
20153
 
19984
20154
  // src/version.ts
19985
- var SDK_VERSION = "0.3.12";
20155
+ var SDK_VERSION = "0.3.13";
19986
20156
  var API_VERSION = "2026-05-03";
19987
20157
  var DEFAULT_BASE_URL = "https://api.transcodely.com";
19988
20158
 
@@ -23791,6 +23961,31 @@ var VideoService = {
23791
23961
  I: GetSeoMarkupRequest,
23792
23962
  O: GetSeoMarkupResponse,
23793
23963
  kind: protobuf.MethodKind.Unary
23964
+ },
23965
+ /**
23966
+ * Generate AI insights (title suggestions, summary, key points, chapters,
23967
+ * questions, key terms, highlights, topics) from a hosted video's existing
23968
+ * AI captions, without transcribing again. Billed EUR 0.02 per video plus
23969
+ * EUR 0.005 per minute of source, charged only when the insights become
23970
+ * ready. Returns the entry in "pending"; it also appears on Video.insights,
23971
+ * and video.insights.ready or video.insights.failed fires when it finishes.
23972
+ *
23973
+ * While an entry for the same video and language is pending, the call
23974
+ * returns that entry and bills nothing new. Once it is ready or failed, a
23975
+ * new call generates (and bills) a new entry; it replaces the ready one
23976
+ * only when it becomes ready itself.
23977
+ *
23978
+ * Refused with failed_precondition and code captions_required when the
23979
+ * video has no AI captions, and insights_transcript_unavailable when the
23980
+ * caption track has no transcript.
23981
+ *
23982
+ * @generated from rpc transcodely.v1.VideoService.GenerateInsights
23983
+ */
23984
+ generateInsights: {
23985
+ name: "GenerateInsights",
23986
+ I: GenerateInsightsRequest,
23987
+ O: GenerateInsightsResponse,
23988
+ kind: protobuf.MethodKind.Unary
23794
23989
  }
23795
23990
  }
23796
23991
  };
@@ -23963,6 +24158,29 @@ var Videos = class {
23963
24158
  opts
23964
24159
  );
23965
24160
  }
24161
+ /**
24162
+ * Generate AI insights (title suggestions, summary, key points, chapters,
24163
+ * questions, key terms, highlights, topics) from a hosted video's existing
24164
+ * AI captions, without transcribing again. Returns the TranscriptInsights
24165
+ * entry in "pending"; it also appears on `video.insights`, and
24166
+ * `video.insights.ready` or `video.insights.failed` fires when it finishes.
24167
+ * Billed EUR 0.02 per video plus EUR 0.005 per minute of source, charged
24168
+ * only when the insights become ready.
24169
+ *
24170
+ * While an entry for the same video and language is pending, the call
24171
+ * returns that entry and bills nothing new. Pass `language` when the video
24172
+ * has several AI caption tracks. A video without AI captions is refused with
24173
+ * failed_precondition (code captions_required).
24174
+ */
24175
+ async generateInsights(req, opts) {
24176
+ const res = await this.transport.unary(
24177
+ VideoService,
24178
+ VideoService.methods.generateInsights,
24179
+ new GenerateInsightsRequest(req),
24180
+ opts
24181
+ );
24182
+ return res.insights;
24183
+ }
23966
24184
  };
23967
24185
 
23968
24186
  // src/resources/uploads.ts
@@ -25347,6 +25565,7 @@ exports.HDRMode = HDRMode;
25347
25565
  exports.HLSPlaylistType = HLSPlaylistType;
25348
25566
  exports.HLSSegmentFormat = HLSSegmentFormat;
25349
25567
  exports.HealthStatus = HealthStatus;
25568
+ exports.InsightsSource = InsightsSource;
25350
25569
  exports.InsightsStatus = InsightsStatus;
25351
25570
  exports.InvalidRequestError = InvalidRequestError;
25352
25571
  exports.InvoiceLineType = InvoiceLineType;