youtubei 1.3.6 → 1.4.0

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.
Files changed (59) hide show
  1. package/dist/cjs/common/shared/HTTP/HTTP.js +18 -7
  2. package/dist/cjs/youtube/BaseVideo/BaseVideoParser.js +9 -4
  3. package/dist/cjs/youtube/BaseVideo/VideoCaptions.js +81 -0
  4. package/dist/cjs/youtube/BaseVideo/index.js +1 -0
  5. package/dist/cjs/youtube/Caption/Caption.js +17 -0
  6. package/dist/cjs/youtube/Caption/CaptionLanguage.js +17 -0
  7. package/dist/cjs/youtube/{Transcript/proto → Caption}/index.js +2 -1
  8. package/dist/cjs/youtube/Client/Client.js +16 -18
  9. package/dist/cjs/youtube/Comment/CommentParser.js +11 -12
  10. package/dist/cjs/youtube/LiveVideo/LiveVideo.js +15 -15
  11. package/dist/cjs/youtube/LiveVideo/LiveVideoParser.js +1 -1
  12. package/dist/cjs/youtube/Video/Video.js +4 -6
  13. package/dist/cjs/youtube/Video/VideoParser.js +5 -5
  14. package/dist/cjs/youtube/VideoCompact/VideoCompact.js +2 -2
  15. package/dist/cjs/youtube/VideoCompact/VideoCompactParser.js +9 -5
  16. package/dist/cjs/youtube/index.js +0 -1
  17. package/dist/esm/common/shared/HTTP/HTTP.js +59 -12
  18. package/dist/esm/youtube/BaseVideo/BaseVideoParser.js +9 -4
  19. package/dist/esm/youtube/BaseVideo/VideoCaptions.js +133 -0
  20. package/dist/esm/youtube/BaseVideo/index.js +1 -0
  21. package/dist/esm/youtube/Caption/Caption.js +19 -0
  22. package/dist/esm/youtube/Caption/CaptionLanguage.js +15 -0
  23. package/dist/esm/youtube/Caption/index.js +2 -0
  24. package/dist/esm/youtube/Client/Client.js +21 -24
  25. package/dist/esm/youtube/Comment/CommentParser.js +11 -12
  26. package/dist/esm/youtube/LiveVideo/LiveVideo.js +15 -15
  27. package/dist/esm/youtube/LiveVideo/LiveVideoParser.js +1 -1
  28. package/dist/esm/youtube/Video/Video.js +5 -7
  29. package/dist/esm/youtube/Video/VideoParser.js +6 -6
  30. package/dist/esm/youtube/VideoCompact/VideoCompact.js +2 -2
  31. package/dist/esm/youtube/VideoCompact/VideoCompactParser.js +9 -5
  32. package/dist/esm/youtube/index.js +0 -1
  33. package/dist/typings/common/shared/HTTP/HTTP.d.ts +2 -2
  34. package/dist/typings/youtube/BaseVideo/BaseVideo.d.ts +3 -0
  35. package/dist/typings/youtube/BaseVideo/VideoCaptions.d.ts +40 -0
  36. package/dist/typings/youtube/BaseVideo/index.d.ts +1 -0
  37. package/dist/typings/youtube/Caption/Caption.d.ts +22 -0
  38. package/dist/typings/youtube/Caption/CaptionLanguage.d.ts +30 -0
  39. package/dist/typings/youtube/Caption/index.d.ts +2 -0
  40. package/dist/typings/youtube/Client/Client.d.ts +8 -3
  41. package/dist/typings/youtube/LiveVideo/LiveVideo.d.ts +5 -5
  42. package/dist/typings/youtube/Video/Video.d.ts +3 -6
  43. package/dist/typings/youtube/VideoCompact/VideoCompact.d.ts +2 -2
  44. package/dist/typings/youtube/index.d.ts +0 -1
  45. package/package.json +1 -1
  46. package/dist/cjs/youtube/Transcript/Transcript.js +0 -27
  47. package/dist/cjs/youtube/Transcript/TranscriptParser.js +0 -13
  48. package/dist/cjs/youtube/Transcript/index.js +0 -15
  49. package/dist/cjs/youtube/Transcript/proto/TranscriptParamsProto.js +0 -12
  50. package/dist/esm/youtube/Transcript/Transcript.js +0 -29
  51. package/dist/esm/youtube/Transcript/TranscriptParser.js +0 -13
  52. package/dist/esm/youtube/Transcript/index.js +0 -3
  53. package/dist/esm/youtube/Transcript/proto/TranscriptParamsProto.js +0 -2
  54. package/dist/esm/youtube/Transcript/proto/index.js +0 -1
  55. package/dist/typings/youtube/Transcript/Transcript.d.ts +0 -29
  56. package/dist/typings/youtube/Transcript/TranscriptParser.d.ts +0 -5
  57. package/dist/typings/youtube/Transcript/index.d.ts +0 -3
  58. package/dist/typings/youtube/Transcript/proto/TranscriptParamsProto.d.ts +0 -7
  59. package/dist/typings/youtube/Transcript/proto/index.d.ts +0 -1
@@ -13,6 +13,7 @@ import { getContinuationFromItems, stripToInt, Thumbnails } from "../../common";
13
13
  import { BaseChannel } from "../BaseChannel";
14
14
  import { PlaylistCompact } from "../PlaylistCompact";
15
15
  import { VideoCompact } from "../VideoCompact";
16
+ import { VideoCaptions } from "./VideoCaptions";
16
17
  var BaseVideoParser = /** @class */ (function () {
17
18
  function BaseVideoParser() {
18
19
  }
@@ -43,11 +44,15 @@ var BaseVideoParser = /** @class */ (function () {
43
44
  ((_b = (_a = videoInfo.superTitleLink) === null || _a === void 0 ? void 0 : _a.runs) === null || _b === void 0 ? void 0 : _b.map(function (r) { return r.text.trim(); }).filter(function (t) { return t; })) || [];
44
45
  target.description = videoInfo.videoDetails.shortDescription || "";
45
46
  // related videos
46
- var secondaryContents = (_c = data[3].response.contents.twoColumnWatchNextResults.secondaryResults) === null || _c === void 0 ? void 0 : _c.secondaryResults.results;
47
+ var secondaryContents = (_c = data.response.contents.twoColumnWatchNextResults.secondaryResults) === null || _c === void 0 ? void 0 : _c.secondaryResults.results;
47
48
  if (secondaryContents) {
48
49
  target.related.items = BaseVideoParser.parseRelatedFromSecondaryContent(secondaryContents, target.client);
49
50
  target.related.continuation = getContinuationFromItems(secondaryContents);
50
51
  }
52
+ // captions
53
+ if (videoInfo.captions) {
54
+ target.captions = new VideoCaptions({ client: target.client, video: target }).load(videoInfo.captions.playerCaptionsTracklistRenderer);
55
+ }
51
56
  return target;
52
57
  };
53
58
  BaseVideoParser.parseRelated = function (data, client) {
@@ -59,12 +64,12 @@ var BaseVideoParser = /** @class */ (function () {
59
64
  return getContinuationFromItems(secondaryContents);
60
65
  };
61
66
  BaseVideoParser.parseRawData = function (data) {
62
- var contents = data[3].response.contents.twoColumnWatchNextResults.results.results.contents;
67
+ var contents = data.response.contents.twoColumnWatchNextResults.results.results.contents;
63
68
  var primaryInfo = contents.find(function (c) { return "videoPrimaryInfoRenderer" in c; })
64
69
  .videoPrimaryInfoRenderer;
65
70
  var secondaryInfo = contents.find(function (c) { return "videoSecondaryInfoRenderer" in c; }).videoSecondaryInfoRenderer;
66
- var videoDetails = data[2].playerResponse.videoDetails;
67
- return __assign(__assign(__assign({}, secondaryInfo), primaryInfo), { videoDetails: videoDetails });
71
+ var _a = data.playerResponse, videoDetails = _a.videoDetails, captions = _a.captions;
72
+ return __assign(__assign(__assign({}, secondaryInfo), primaryInfo), { videoDetails: videoDetails, captions: captions });
68
73
  };
69
74
  BaseVideoParser.parseCompactRenderer = function (data, client) {
70
75
  if ("compactVideoRenderer" in data) {
@@ -0,0 +1,133 @@
1
+ var __extends = (this && this.__extends) || (function () {
2
+ var extendStatics = function (d, b) {
3
+ extendStatics = Object.setPrototypeOf ||
4
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6
+ return extendStatics(d, b);
7
+ };
8
+ return function (d, b) {
9
+ extendStatics(d, b);
10
+ function __() { this.constructor = d; }
11
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12
+ };
13
+ })();
14
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
+ return new (P || (P = Promise))(function (resolve, reject) {
17
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
21
+ });
22
+ };
23
+ var __generator = (this && this.__generator) || function (thisArg, body) {
24
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
25
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
26
+ function verb(n) { return function (v) { return step([n, v]); }; }
27
+ function step(op) {
28
+ if (f) throw new TypeError("Generator is already executing.");
29
+ while (_) try {
30
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
31
+ if (y = 0, t) op = [op[0] & 2, t.value];
32
+ switch (op[0]) {
33
+ case 0: case 1: t = op; break;
34
+ case 4: _.label++; return { value: op[1], done: false };
35
+ case 5: _.label++; y = op[1]; op = [0]; continue;
36
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
37
+ default:
38
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
39
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
40
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
41
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
42
+ if (t[2]) _.ops.pop();
43
+ _.trys.pop(); continue;
44
+ }
45
+ op = body.call(thisArg, _);
46
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
47
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
48
+ }
49
+ };
50
+ import { Base } from "../Base";
51
+ import { Caption, CaptionLanguage } from "../Caption";
52
+ /**
53
+ * Captions of a video
54
+ *
55
+ * @example
56
+ * ```js
57
+ *
58
+ * console.log(result.captions.languages.map((l) => `${l.code} - ${l.name}`)); // printing out available languages for captions
59
+ *
60
+ * console.log(await result.captions.get("en")); // printing out captions of a specific language using language code
61
+ * ```
62
+ */
63
+ var VideoCaptions = /** @class */ (function (_super) {
64
+ __extends(VideoCaptions, _super);
65
+ /** @hidden */
66
+ function VideoCaptions(_a) {
67
+ var video = _a.video, client = _a.client;
68
+ var _this = _super.call(this, client) || this;
69
+ _this.video = video;
70
+ _this.languages = [];
71
+ return _this;
72
+ }
73
+ /**
74
+ * Load this instance with raw data from Youtube
75
+ *
76
+ * @hidden
77
+ */
78
+ VideoCaptions.prototype.load = function (data) {
79
+ var _this = this;
80
+ var captionTracks = data.captionTracks;
81
+ if (captionTracks) {
82
+ this.languages = captionTracks.map(function (track) {
83
+ return new CaptionLanguage({
84
+ captions: _this,
85
+ name: track.name.simpleText,
86
+ code: track.languageCode,
87
+ isTranslatable: !!track.isTranslatable,
88
+ url: track.baseUrl,
89
+ });
90
+ });
91
+ }
92
+ return this;
93
+ };
94
+ /**
95
+ * Get captions of a specific language or a translation of a specific language
96
+ */
97
+ VideoCaptions.prototype.get = function (languageCode, translationLanguageCode) {
98
+ var _a, _b;
99
+ return __awaiter(this, void 0, void 0, function () {
100
+ var url, params, response, captions;
101
+ return __generator(this, function (_c) {
102
+ switch (_c.label) {
103
+ case 0:
104
+ if (!languageCode)
105
+ languageCode = this.client.options.youtubeClientOptions.hl;
106
+ url = (_a = this.languages.find(function (l) { return l.code.toUpperCase() === (languageCode === null || languageCode === void 0 ? void 0 : languageCode.toUpperCase()); })) === null || _a === void 0 ? void 0 : _a.url;
107
+ if (!url)
108
+ return [2 /*return*/, undefined];
109
+ params = { fmt: "json3" };
110
+ if (translationLanguageCode)
111
+ params["tlang"] = translationLanguageCode;
112
+ return [4 /*yield*/, this.client.http.get(url, { params: params })];
113
+ case 1:
114
+ response = _c.sent();
115
+ captions = (_b = response.data.events) === null || _b === void 0 ? void 0 : _b.reduce(function (curr, e) {
116
+ var _a;
117
+ if (e.segs === undefined)
118
+ return curr;
119
+ curr.push(new Caption({
120
+ duration: e.dDurationMs,
121
+ start: e.tStartMs,
122
+ text: (_a = e.segs) === null || _a === void 0 ? void 0 : _a.map(function (s) { return Object.values(s).join(""); }).join(" "),
123
+ }));
124
+ return curr;
125
+ }, []);
126
+ return [2 /*return*/, captions];
127
+ }
128
+ });
129
+ });
130
+ };
131
+ return VideoCaptions;
132
+ }(Base));
133
+ export { VideoCaptions };
@@ -1,3 +1,4 @@
1
1
  export * from "./BaseVideo";
2
2
  export * from "./BaseVideoParser";
3
+ export * from "./VideoCaptions";
3
4
  export * from "./VideoRelated";
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Represent a single video caption entry
3
+ */
4
+ var Caption = /** @class */ (function () {
5
+ /** @hidden */
6
+ function Caption(attr) {
7
+ Object.assign(this, attr);
8
+ }
9
+ Object.defineProperty(Caption.prototype, "end", {
10
+ /** transcript end time in milliseconds */
11
+ get: function () {
12
+ return this.start + this.duration;
13
+ },
14
+ enumerable: false,
15
+ configurable: true
16
+ });
17
+ return Caption;
18
+ }());
19
+ export { Caption };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Represents a caption language option
3
+ */
4
+ var CaptionLanguage = /** @class */ (function () {
5
+ /** @hidden */
6
+ function CaptionLanguage(attr) {
7
+ Object.assign(this, attr);
8
+ }
9
+ /** Get the captions of this language using the url */
10
+ CaptionLanguage.prototype.get = function (translationLanguageCode) {
11
+ return this.captions.get(this.code, translationLanguageCode);
12
+ };
13
+ return CaptionLanguage;
14
+ }());
15
+ export { CaptionLanguage };
@@ -0,0 +1,2 @@
1
+ export * from "./Caption";
2
+ export * from "./CaptionLanguage";
@@ -51,15 +51,14 @@ import { LiveVideo } from "../LiveVideo";
51
51
  import { MixPlaylist } from "../MixPlaylist";
52
52
  import { Playlist } from "../Playlist";
53
53
  import { SearchResult } from "../SearchResult";
54
- import { Transcript, TranscriptParamsProto } from "../Transcript";
55
54
  import { Video } from "../Video";
56
55
  import { BASE_URL, INNERTUBE_API_KEY, INNERTUBE_CLIENT_NAME, INNERTUBE_CLIENT_VERSION, I_END_POINT, WATCH_END_POINT, } from "../constants";
57
56
  /** Youtube Client */
58
57
  var Client = /** @class */ (function () {
59
58
  function Client(options) {
60
59
  if (options === void 0) { options = {}; }
61
- var fullOptions = __assign(__assign({ initialCookie: "", fetchOptions: {} }, options), { youtubeClientOptions: __assign({ hl: "en", gl: "US" }, options.youtubeClientOptions) });
62
- this.http = new HTTP(__assign({ apiKey: INNERTUBE_API_KEY, baseUrl: BASE_URL, clientName: INNERTUBE_CLIENT_NAME, clientVersion: INNERTUBE_CLIENT_VERSION }, fullOptions));
60
+ this.options = __assign(__assign({ initialCookie: "", fetchOptions: {} }, options), { youtubeClientOptions: __assign({ hl: "en", gl: "US" }, options.youtubeClientOptions) });
61
+ this.http = new HTTP(__assign({ apiKey: INNERTUBE_API_KEY, baseUrl: BASE_URL, clientName: INNERTUBE_CLIENT_NAME, clientVersion: INNERTUBE_CLIENT_VERSION }, this.options));
63
62
  }
64
63
  /**
65
64
  * Searches for videos / playlists / channels
@@ -136,7 +135,7 @@ var Client = /** @class */ (function () {
136
135
  Client.prototype.getVideo = function (videoId) {
137
136
  var _a;
138
137
  return __awaiter(this, void 0, void 0, function () {
139
- var response;
138
+ var response, data;
140
139
  return __generator(this, function (_b) {
141
140
  switch (_b.label) {
142
141
  case 0: return [4 /*yield*/, this.http.get("" + WATCH_END_POINT, {
@@ -144,13 +143,15 @@ var Client = /** @class */ (function () {
144
143
  })];
145
144
  case 1:
146
145
  response = _b.sent();
147
- if (!((_a = response.data[3]) === null || _a === void 0 ? void 0 : _a.response.contents) ||
148
- response.data[2].playerResponse.playabilityStatus.status === "ERROR") {
146
+ data = Array.isArray(response.data)
147
+ ? response.data.reduce(function (prev, curr) { return (__assign(__assign({}, prev), curr)); }, {})
148
+ : response.data;
149
+ if (!((_a = data.response) === null || _a === void 0 ? void 0 : _a.contents) || data.playerResponse.playabilityStatus.status === "ERROR") {
149
150
  return [2 /*return*/, undefined];
150
151
  }
151
- return [2 /*return*/, (!response.data[2].playerResponse.playabilityStatus.liveStreamability
152
- ? new Video({ client: this }).load(response.data)
153
- : new LiveVideo({ client: this }).load(response.data))];
152
+ return [2 /*return*/, (!data.playerResponse.playabilityStatus.liveStreamability
153
+ ? new Video({ client: this }).load(data)
154
+ : new LiveVideo({ client: this }).load(data))];
154
155
  }
155
156
  });
156
157
  });
@@ -175,23 +176,19 @@ var Client = /** @class */ (function () {
175
176
  });
176
177
  });
177
178
  };
178
- Client.prototype.getVideoTranscript = function (videoId) {
179
+ /**
180
+ * Get video transcript / caption by video id
181
+ */
182
+ Client.prototype.getVideoTranscript = function (videoId, languageCode) {
183
+ var _a;
179
184
  return __awaiter(this, void 0, void 0, function () {
180
- var bufferParams, response;
181
- return __generator(this, function (_a) {
182
- switch (_a.label) {
183
- case 0:
184
- bufferParams = TranscriptParamsProto.encode({ videoId: videoId }).finish();
185
- return [4 /*yield*/, this.http.post(I_END_POINT + "/get_transcript", {
186
- data: { params: Buffer.from(bufferParams).toString("base64") },
187
- })];
185
+ var video;
186
+ return __generator(this, function (_b) {
187
+ switch (_b.label) {
188
+ case 0: return [4 /*yield*/, this.getVideo(videoId)];
188
189
  case 1:
189
- response = _a.sent();
190
- if (!response.data.actions)
191
- return [2 /*return*/, undefined];
192
- return [2 /*return*/, response.data.actions[0].updateEngagementPanelAction.content.transcriptRenderer.body.transcriptBodyRenderer.cueGroups
193
- .map(function (t) { return t.transcriptCueGroupRenderer.cues[0].transcriptCueRenderer; })
194
- .map(function (t) { return new Transcript().load(t); })];
190
+ video = _b.sent();
191
+ return [2 /*return*/, (_a = video === null || video === void 0 ? void 0 : video.captions) === null || _a === void 0 ? void 0 : _a.get(languageCode)];
195
192
  }
196
193
  });
197
194
  });
@@ -5,25 +5,24 @@ var CommentParser = /** @class */ (function () {
5
5
  function CommentParser() {
6
6
  }
7
7
  CommentParser.loadComment = function (target, data) {
8
- var _a = data.comment.commentRenderer, authorText = _a.authorText, authorThumbnail = _a.authorThumbnail, authorEndpoint = _a.authorEndpoint, contentText = _a.contentText, publishedTimeText = _a.publishedTimeText, commentId = _a.commentId, voteCount = _a.voteCount, authorIsChannelOwner = _a.authorIsChannelOwner, pinnedCommentBadge = _a.pinnedCommentBadge, replyCount = _a.replyCount;
8
+ var properties = data.properties, toolbar = data.toolbar, author = data.author, avatar = data.avatar;
9
9
  // Basic information
10
- target.id = commentId;
11
- target.content = contentText.runs.map(function (r) { return r.text; }).join("");
12
- target.publishDate = publishedTimeText.runs.shift().text;
13
- target.likeCount = +((voteCount === null || voteCount === void 0 ? void 0 : voteCount.simpleText) || 0);
14
- target.isAuthorChannelOwner = authorIsChannelOwner;
15
- target.isPinned = !!pinnedCommentBadge;
16
- target.replyCount = replyCount;
10
+ target.id = properties.commentId;
11
+ target.content = properties.content.content;
12
+ target.publishDate = properties.publishedTime;
13
+ target.likeCount = +toolbar.likeCountLiked; // probably broken
14
+ target.isAuthorChannelOwner = !!author.isCreator;
15
+ target.isPinned = false; // TODO fix this
16
+ target.replyCount = +toolbar.replyCount;
17
17
  // Reply Continuation
18
18
  target.replies.continuation = data.replies
19
19
  ? getContinuationFromItems(data.replies.commentRepliesRenderer.contents)
20
20
  : undefined;
21
21
  // Author
22
- var browseId = authorEndpoint.browseEndpoint.browseId;
23
22
  target.author = new BaseChannel({
24
- id: browseId,
25
- name: authorText.simpleText,
26
- thumbnails: new Thumbnails().load(authorThumbnail.thumbnails),
23
+ id: author.id,
24
+ name: author.displayName,
25
+ thumbnails: new Thumbnails().load(avatar.image.sources),
27
26
  client: target.client,
28
27
  });
29
28
  return target;
@@ -70,10 +70,10 @@ var LiveVideo = /** @class */ (function (_super) {
70
70
  /** @hidden */
71
71
  function LiveVideo(attr) {
72
72
  var _this = _super.call(this, attr) || this;
73
- _this._delay = 0;
74
- _this._timeoutMs = 0;
75
- _this._isChatPlaying = false;
76
- _this._chatQueue = [];
73
+ _this.delay = 0;
74
+ _this.timeoutMs = 0;
75
+ _this.isChatPlaying = false;
76
+ _this.chatQueue = [];
77
77
  Object.assign(_this, attr);
78
78
  return _this;
79
79
  }
@@ -94,18 +94,18 @@ var LiveVideo = /** @class */ (function (_super) {
94
94
  */
95
95
  LiveVideo.prototype.playChat = function (delay) {
96
96
  if (delay === void 0) { delay = 0; }
97
- if (this._isChatPlaying)
97
+ if (this.isChatPlaying)
98
98
  return;
99
- this._delay = delay;
100
- this._isChatPlaying = true;
99
+ this.delay = delay;
100
+ this.isChatPlaying = true;
101
101
  this.pollChatContinuation();
102
102
  };
103
103
  /** Stop request polling for live chat */
104
104
  LiveVideo.prototype.stopChat = function () {
105
- if (!this._chatRequestPoolingTimeout)
105
+ if (!this.chatRequestPoolingTimeout)
106
106
  return;
107
- this._isChatPlaying = false;
108
- clearTimeout(this._chatRequestPoolingTimeout);
107
+ this.isChatPlaying = false;
108
+ clearTimeout(this.chatRequestPoolingTimeout);
109
109
  };
110
110
  /** Start request polling */
111
111
  LiveVideo.prototype.pollChatContinuation = function () {
@@ -125,10 +125,10 @@ var LiveVideo = /** @class */ (function (_super) {
125
125
  chats = LiveVideoParser.parseChats(response.data);
126
126
  _loop_1 = function (c) {
127
127
  var chat = new Chat({ client: this_1.client }).load(c);
128
- if (this_1._chatQueue.find(function (c) { return c.id === chat.id; }))
128
+ if (this_1.chatQueue.find(function (c) { return c.id === chat.id; }))
129
129
  return "continue";
130
- this_1._chatQueue.push(chat);
131
- var timeout_1 = chat.timestamp / 1000 - (new Date().getTime() - this_1._delay);
130
+ this_1.chatQueue.push(chat);
131
+ var timeout_1 = chat.timestamp / 1000 - (new Date().getTime() - this_1.delay);
132
132
  setTimeout(function () { return _this.emit("chat", chat); }, timeout_1);
133
133
  };
134
134
  this_1 = this;
@@ -146,9 +146,9 @@ var LiveVideo = /** @class */ (function (_super) {
146
146
  finally { if (e_1) throw e_1.error; }
147
147
  }
148
148
  _a = LiveVideoParser.parseContinuation(response.data), timeout = _a.timeout, continuation = _a.continuation;
149
- this._timeoutMs = timeout;
149
+ this.timeoutMs = timeout;
150
150
  this.chatContinuation = continuation;
151
- this._chatRequestPoolingTimeout = setTimeout(function () { return _this.pollChatContinuation(); }, this._timeoutMs);
151
+ this.chatRequestPoolingTimeout = setTimeout(function () { return _this.pollChatContinuation(); }, this.timeoutMs);
152
152
  return [2 /*return*/];
153
153
  }
154
154
  });
@@ -9,7 +9,7 @@ var LiveVideoParser = /** @class */ (function () {
9
9
  .map(function (r) { return r.text; })
10
10
  .join(" ")
11
11
  .replace(/[^0-9]/g, "");
12
- target.chatContinuation = (_a = data[3].response.contents.twoColumnWatchNextResults.conversationBar.liveChatRenderer) === null || _a === void 0 ? void 0 : _a.continuations[0].reloadContinuationData.continuation;
12
+ target.chatContinuation = (_a = data.response.contents.twoColumnWatchNextResults.conversationBar.liveChatRenderer) === null || _a === void 0 ? void 0 : _a.continuations[0].reloadContinuationData.continuation;
13
13
  return target;
14
14
  };
15
15
  LiveVideoParser.parseChats = function (data) {
@@ -73,15 +73,13 @@ var Video = /** @class */ (function (_super) {
73
73
  /**
74
74
  * Get Video transcript (if exists)
75
75
  *
76
- * Equivalent to
77
- * ```js
78
- * client.getVideoTranscript(video.id);
79
- * ```
76
+ * @deprecated use `video.captions.get()` instead
80
77
  */
81
- Video.prototype.getTranscript = function () {
78
+ Video.prototype.getTranscript = function (languageCode) {
79
+ var _a;
82
80
  return __awaiter(this, void 0, void 0, function () {
83
- return __generator(this, function (_a) {
84
- return [2 /*return*/, this.client.getVideoTranscript(this.id)];
81
+ return __generator(this, function (_b) {
82
+ return [2 /*return*/, (_a = this.captions) === null || _a === void 0 ? void 0 : _a.get(languageCode)];
85
83
  });
86
84
  });
87
85
  };
@@ -1,4 +1,4 @@
1
- import { getContinuationFromItems, mapFilter, Thumbnails } from "../../common";
1
+ import { getContinuationFromItems, Thumbnails } from "../../common";
2
2
  import { BaseVideoParser } from "../BaseVideo";
3
3
  import { Comment } from "../Comment";
4
4
  var VideoParser = /** @class */ (function () {
@@ -8,11 +8,11 @@ var VideoParser = /** @class */ (function () {
8
8
  var _a, _b, _c;
9
9
  var videoInfo = BaseVideoParser.parseRawData(data);
10
10
  target.duration = +videoInfo.videoDetails.lengthSeconds;
11
- var itemSectionRenderer = (_a = data[3].response.contents.twoColumnWatchNextResults.results.results.contents
11
+ var itemSectionRenderer = (_a = data.response.contents.twoColumnWatchNextResults.results.results.contents
12
12
  .reverse()
13
13
  .find(function (c) { return c.itemSectionRenderer; })) === null || _a === void 0 ? void 0 : _a.itemSectionRenderer;
14
14
  target.comments.continuation = getContinuationFromItems((itemSectionRenderer === null || itemSectionRenderer === void 0 ? void 0 : itemSectionRenderer.contents) || []);
15
- var chapters = (_c = (_b = data[3].response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer) === null || _b === void 0 ? void 0 : _b.decoratedPlayerBarRenderer.playerBar.multiMarkersPlayerBarRenderer.markersMap) === null || _c === void 0 ? void 0 : _c[0].value.chapters;
15
+ var chapters = (_c = (_b = data.response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer) === null || _b === void 0 ? void 0 : _b.decoratedPlayerBarRenderer.playerBar.multiMarkersPlayerBarRenderer.markersMap) === null || _c === void 0 ? void 0 : _c[0].value.chapters;
16
16
  target.chapters =
17
17
  (chapters === null || chapters === void 0 ? void 0 : chapters.map(function (_a) {
18
18
  var c = _a.chapterRenderer;
@@ -25,9 +25,9 @@ var VideoParser = /** @class */ (function () {
25
25
  return target;
26
26
  };
27
27
  VideoParser.parseComments = function (data, video) {
28
- var endpoints = data.onResponseReceivedEndpoints.at(-1);
29
- var continuationItems = (endpoints.reloadContinuationItemsCommand || endpoints.appendContinuationItemsAction).continuationItems;
30
- var comments = mapFilter(continuationItems, "commentThreadRenderer");
28
+ var comments = data.frameworkUpdates.entityBatchUpdate.mutations
29
+ .filter(function (m) { return m.payload.commentEntityPayload; })
30
+ .map(function (m) { return m.payload.commentEntityPayload; });
31
31
  return comments.map(function (c) {
32
32
  return new Comment({ video: video, client: video.client }).load(c);
33
33
  });
@@ -101,10 +101,10 @@ var VideoCompact = /** @class */ (function (_super) {
101
101
  * client.getVideoTranscript(video.id);
102
102
  * ```
103
103
  */
104
- VideoCompact.prototype.getTranscript = function () {
104
+ VideoCompact.prototype.getTranscript = function (languageCode) {
105
105
  return __awaiter(this, void 0, void 0, function () {
106
106
  return __generator(this, function (_a) {
107
- return [2 /*return*/, this.client.getVideoTranscript(this.id)];
107
+ return [2 /*return*/, this.client.getVideoTranscript(this.id, languageCode)];
108
108
  });
109
109
  });
110
110
  };
@@ -4,18 +4,22 @@ var VideoCompactParser = /** @class */ (function () {
4
4
  function VideoCompactParser() {
5
5
  }
6
6
  VideoCompactParser.loadVideoCompact = function (target, data) {
7
- var _a, _b, _c;
7
+ var _a, _b, _c, _d, _e;
8
8
  var videoId = data.videoId, title = data.title, headline = data.headline, lengthText = data.lengthText, thumbnail = data.thumbnail, ownerText = data.ownerText, shortBylineText = data.shortBylineText, publishedTimeText = data.publishedTimeText, viewCountText = data.viewCountText, badges = data.badges, thumbnailOverlays = data.thumbnailOverlays, channelThumbnailSupportedRenderers = data.channelThumbnailSupportedRenderers, detailedMetadataSnippets = data.detailedMetadataSnippets;
9
9
  target.id = videoId;
10
- target.title = headline ? headline.simpleText : title.simpleText || ((_a = title.runs[0]) === null || _a === void 0 ? void 0 : _a.text);
10
+ target.title = headline
11
+ ? headline.simpleText
12
+ : title.simpleText || ((_b = (_a = title.runs) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.text) || "";
11
13
  target.thumbnails = new Thumbnails().load(thumbnail.thumbnails);
12
14
  target.uploadDate = publishedTimeText === null || publishedTimeText === void 0 ? void 0 : publishedTimeText.simpleText;
13
15
  target.description =
14
- ((_b = detailedMetadataSnippets === null || detailedMetadataSnippets === void 0 ? void 0 : detailedMetadataSnippets[0].snippetText.runs) === null || _b === void 0 ? void 0 : _b.map(function (r) { return r.text; }).join("")) || "";
16
+ ((_c = detailedMetadataSnippets === null || detailedMetadataSnippets === void 0 ? void 0 : detailedMetadataSnippets[0].snippetText.runs) === null || _c === void 0 ? void 0 : _c.map(function (r) { return r.text; }).join("")) || "";
15
17
  target.duration =
16
- getDuration((lengthText === null || lengthText === void 0 ? void 0 : lengthText.simpleText) || ((_c = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _c === void 0 ? void 0 : _c.text.simpleText) ||
18
+ getDuration((lengthText === null || lengthText === void 0 ? void 0 : lengthText.simpleText) || ((_d = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _d === void 0 ? void 0 : _d.text.simpleText) ||
17
19
  "") || null;
18
- target.isLive = !!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW");
20
+ target.isLive =
21
+ !!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW") ||
22
+ ((_e = thumbnailOverlays === null || thumbnailOverlays === void 0 ? void 0 : thumbnailOverlays[0].thumbnailOverlayTimeStatusRenderer) === null || _e === void 0 ? void 0 : _e.style) === "LIVE";
19
23
  // Channel
20
24
  if (ownerText || shortBylineText) {
21
25
  var browseEndpoint = (ownerText || shortBylineText).runs[0].navigationEndpoint
@@ -12,6 +12,5 @@ export * from "./Playlist";
12
12
  export * from "./PlaylistCompact";
13
13
  export * from "./Reply";
14
14
  export * from "./SearchResult";
15
- export * from "./Transcript";
16
15
  export * from "./Video";
17
16
  export * from "./VideoCompact";
@@ -28,8 +28,8 @@ export declare class HTTP {
28
28
  private defaultFetchOptions;
29
29
  private defaultClientOptions;
30
30
  constructor(options: HTTPOptions);
31
- get(url: string, options?: Partial<Options>): Promise<Response>;
32
- post(url: string, options?: Partial<Options>): Promise<Response>;
31
+ get(path: string, options?: Partial<Options>): Promise<Response>;
32
+ post(path: string, options?: Partial<Options>): Promise<Response>;
33
33
  private request;
34
34
  private parseCookie;
35
35
  }
@@ -3,6 +3,7 @@ import { Base, BaseProperties } from "../Base";
3
3
  import { BaseChannel } from "../BaseChannel";
4
4
  import { PlaylistCompact } from "../PlaylistCompact";
5
5
  import { VideoCompact } from "../VideoCompact";
6
+ import { VideoCaptions } from "./VideoCaptions";
6
7
  import { VideoRelated } from "./VideoRelated";
7
8
  /** @hidden */
8
9
  export interface BaseVideoProperties extends BaseProperties {
@@ -40,6 +41,8 @@ export declare class BaseVideo extends Base implements BaseVideoProperties {
40
41
  tags: string[];
41
42
  /** Continuable of videos / playlists related to this video */
42
43
  related: VideoRelated;
44
+ /** Captions helper class of this video (if caption exists in this video) */
45
+ captions: VideoCaptions | null;
43
46
  /** @hidden */
44
47
  constructor(attr: BaseVideoProperties);
45
48
  /**
@@ -0,0 +1,40 @@
1
+ import { YoutubeRawData } from "../../common";
2
+ import { Base } from "../Base";
3
+ import { BaseVideo } from "../BaseVideo";
4
+ import { Caption, CaptionLanguage } from "../Caption";
5
+ import { Client } from "../Client";
6
+ /** @hidden */
7
+ interface ConstructorParams {
8
+ client: Client;
9
+ video?: BaseVideo;
10
+ }
11
+ /**
12
+ * Captions of a video
13
+ *
14
+ * @example
15
+ * ```js
16
+ *
17
+ * console.log(result.captions.languages.map((l) => `${l.code} - ${l.name}`)); // printing out available languages for captions
18
+ *
19
+ * console.log(await result.captions.get("en")); // printing out captions of a specific language using language code
20
+ * ```
21
+ */
22
+ export declare class VideoCaptions extends Base {
23
+ /** The video this captions belongs to */
24
+ video?: BaseVideo;
25
+ /** List of available languages for this video */
26
+ languages: Array<CaptionLanguage>;
27
+ /** @hidden */
28
+ constructor({ video, client }: ConstructorParams);
29
+ /**
30
+ * Load this instance with raw data from Youtube
31
+ *
32
+ * @hidden
33
+ */
34
+ load(data: YoutubeRawData): VideoCaptions;
35
+ /**
36
+ * Get captions of a specific language or a translation of a specific language
37
+ */
38
+ get(languageCode?: string, translationLanguageCode?: string): Promise<Caption[] | undefined>;
39
+ }
40
+ export {};
@@ -1,3 +1,4 @@
1
1
  export * from "./BaseVideo";
2
2
  export * from "./BaseVideoParser";
3
+ export * from "./VideoCaptions";
3
4
  export * from "./VideoRelated";
@@ -0,0 +1,22 @@
1
+ /** @hidden */
2
+ interface CaptionProperties {
3
+ text?: string;
4
+ start?: number;
5
+ duration?: number;
6
+ }
7
+ /**
8
+ * Represent a single video caption entry
9
+ */
10
+ export declare class Caption implements CaptionProperties {
11
+ /** caption content */
12
+ text: string;
13
+ /** caption start time in milliseconds */
14
+ start: number;
15
+ /** caption duration in milliseconds */
16
+ duration: number;
17
+ /** @hidden */
18
+ constructor(attr?: CaptionProperties);
19
+ /** transcript end time in milliseconds */
20
+ get end(): number;
21
+ }
22
+ export {};