youtubei 1.0.0-rc.6 → 1.0.0-rc.8

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 (34) hide show
  1. package/dist/cjs/classes/BaseChannel/BaseChannelParser.js +2 -1
  2. package/dist/cjs/classes/Client/Client.js +14 -0
  3. package/dist/cjs/classes/Transcript/Transcript.js +27 -0
  4. package/dist/cjs/classes/Transcript/TranscriptParser.js +13 -0
  5. package/dist/cjs/classes/Transcript/index.js +15 -0
  6. package/dist/cjs/classes/Transcript/proto/TranscriptParamsProto.js +12 -0
  7. package/dist/cjs/classes/Transcript/proto/index.js +13 -0
  8. package/dist/cjs/classes/Video/Video.js +22 -0
  9. package/dist/cjs/classes/Video/VideoParser.js +9 -1
  10. package/dist/cjs/classes/VideoCompact/VideoCompact.js +13 -0
  11. package/dist/cjs/classes/VideoCompact/VideoCompactParser.js +12 -8
  12. package/dist/cjs/classes/index.js +1 -0
  13. package/dist/esm/classes/BaseChannel/BaseChannelParser.js +2 -1
  14. package/dist/esm/classes/Client/Client.js +22 -0
  15. package/dist/esm/classes/Transcript/Transcript.js +29 -0
  16. package/dist/esm/classes/Transcript/TranscriptParser.js +13 -0
  17. package/dist/esm/classes/Transcript/index.js +3 -0
  18. package/dist/esm/classes/Transcript/proto/TranscriptParamsProto.js +2 -0
  19. package/dist/esm/classes/Transcript/proto/index.js +1 -0
  20. package/dist/esm/classes/Video/Video.js +51 -0
  21. package/dist/esm/classes/Video/VideoParser.js +12 -1
  22. package/dist/esm/classes/VideoCompact/VideoCompact.js +15 -0
  23. package/dist/esm/classes/VideoCompact/VideoCompactParser.js +12 -8
  24. package/dist/esm/classes/index.js +1 -0
  25. package/dist/typings/classes/Client/Client.d.ts +2 -0
  26. package/dist/typings/classes/Transcript/Transcript.d.ts +29 -0
  27. package/dist/typings/classes/Transcript/TranscriptParser.d.ts +5 -0
  28. package/dist/typings/classes/Transcript/index.d.ts +3 -0
  29. package/dist/typings/classes/Transcript/proto/TranscriptParamsProto.d.ts +16 -0
  30. package/dist/typings/classes/Transcript/proto/index.d.ts +1 -0
  31. package/dist/typings/classes/Video/Video.d.ts +19 -0
  32. package/dist/typings/classes/VideoCompact/VideoCompact.d.ts +10 -0
  33. package/dist/typings/classes/index.d.ts +1 -0
  34. package/package.json +2 -2
@@ -5,11 +5,12 @@ const common_1 = require("../../common");
5
5
  const Thumbnails_1 = require("../Thumbnails");
6
6
  class BaseChannelParser {
7
7
  static loadBaseChannel(target, data) {
8
+ var _a;
8
9
  const { channelId, title, thumbnail, videoCountText, subscriberCountText } = data;
9
10
  target.id = channelId;
10
11
  target.name = title.simpleText;
11
12
  target.thumbnails = new Thumbnails_1.Thumbnails().load(thumbnail.thumbnails);
12
- target.videoCount = common_1.stripToInt(videoCountText === null || videoCountText === void 0 ? void 0 : videoCountText.runs[0].text) || 0;
13
+ target.videoCount = common_1.stripToInt((_a = videoCountText === null || videoCountText === void 0 ? void 0 : videoCountText.runs) === null || _a === void 0 ? void 0 : _a[0].text) || 0; // TODO this sometimes contains subscriber count for some reason
13
14
  target.subscriberCount = subscriberCountText === null || subscriberCountText === void 0 ? void 0 : subscriberCountText.simpleText;
14
15
  return target;
15
16
  }
@@ -16,6 +16,7 @@ const LiveVideo_1 = require("../LiveVideo");
16
16
  const MixPlaylist_1 = require("../MixPlaylist");
17
17
  const Playlist_1 = require("../Playlist");
18
18
  const SearchResult_1 = require("../SearchResult");
19
+ const Transcript_1 = require("../Transcript");
19
20
  const Video_1 = require("../Video");
20
21
  const HTTP_1 = require("./HTTP");
21
22
  /** Youtube Client */
@@ -97,5 +98,18 @@ class Client {
97
98
  return new Channel_1.Channel({ client: this }).load(response.data);
98
99
  });
99
100
  }
101
+ getVideoTranscript(videoId) {
102
+ return __awaiter(this, void 0, void 0, function* () {
103
+ const bufferParams = Transcript_1.TranscriptParamsProto.TranscriptParams.encode({ videoId });
104
+ const response = yield this.http.post(`${constants_1.I_END_POINT}/get_transcript`, {
105
+ data: { params: Buffer.from(bufferParams).toString("base64") },
106
+ });
107
+ if (!response.data.actions)
108
+ return undefined;
109
+ return response.data.actions[0].updateEngagementPanelAction.content.transcriptRenderer.body.transcriptBodyRenderer.cueGroups
110
+ .map((t) => t.transcriptCueGroupRenderer.cues[0].transcriptCueRenderer)
111
+ .map((t) => new Transcript_1.Transcript().load(t));
112
+ });
113
+ }
100
114
  }
101
115
  exports.Client = Client;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Transcript = void 0;
4
+ const TranscriptParser_1 = require("./TranscriptParser");
5
+ /**
6
+ * Represent a single video transcript entry
7
+ */
8
+ class Transcript {
9
+ /** @hidden */
10
+ constructor(attr) {
11
+ Object.assign(this, attr);
12
+ }
13
+ /** transcript end time in miliseconds */
14
+ get end() {
15
+ return this.start + this.duration;
16
+ }
17
+ /**
18
+ * Load this instance with raw data from Youtube
19
+ *
20
+ * @hidden
21
+ */
22
+ load(data) {
23
+ TranscriptParser_1.TranscriptParser.loadTranscript(this, data);
24
+ return this;
25
+ }
26
+ }
27
+ exports.Transcript = Transcript;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TranscriptParser = void 0;
4
+ class TranscriptParser {
5
+ static loadTranscript(target, data) {
6
+ const { cue, startOffsetMs, durationMs } = data;
7
+ target.text = cue.simpleText;
8
+ target.duration = +durationMs;
9
+ target.start = +startOffsetMs;
10
+ return target;
11
+ }
12
+ }
13
+ exports.TranscriptParser = TranscriptParser;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./proto"), exports);
14
+ __exportStar(require("./Transcript"), exports);
15
+ __exportStar(require("./TranscriptParser"), exports);
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TranscriptParamsProto = void 0;
7
+ const protocol_buffers_1 = __importDefault(require("protocol-buffers"));
8
+ exports.TranscriptParamsProto = protocol_buffers_1.default(`
9
+ message TranscriptParams {
10
+ optional string videoId = 1;
11
+ }
12
+ `);
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./TranscriptParamsProto"), exports);
@@ -1,4 +1,13 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.Video = void 0;
4
13
  const BaseVideo_1 = require("../BaseVideo");
@@ -22,5 +31,18 @@ class Video extends BaseVideo_1.BaseVideo {
22
31
  VideoParser_1.VideoParser.loadVideo(this, data);
23
32
  return this;
24
33
  }
34
+ /**
35
+ * Get Video transcript (if exists)
36
+ *
37
+ * Equivalent to
38
+ * ```js
39
+ * client.getVideoTranscript(video.id);
40
+ * ```
41
+ */
42
+ getTranscript() {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ return this.client.getVideoTranscript(this.id);
45
+ });
46
+ }
25
47
  }
26
48
  exports.Video = Video;
@@ -4,15 +4,23 @@ exports.VideoParser = void 0;
4
4
  const common_1 = require("../../common");
5
5
  const BaseVideo_1 = require("../BaseVideo");
6
6
  const Comment_1 = require("../Comment");
7
+ const Thumbnails_1 = require("../Thumbnails");
7
8
  class VideoParser {
8
9
  static loadVideo(target, data) {
9
- var _a;
10
+ var _a, _b;
10
11
  const videoInfo = BaseVideo_1.BaseVideoParser.parseRawData(data);
11
12
  target.duration = +videoInfo.videoDetails.lengthSeconds;
12
13
  const itemSectionRenderer = (_a = data[3].response.contents.twoColumnWatchNextResults.results.results.contents
13
14
  .reverse()
14
15
  .find((c) => c.itemSectionRenderer)) === null || _a === void 0 ? void 0 : _a.itemSectionRenderer;
15
16
  target.comments.continuation = common_1.getContinuationFromItems((itemSectionRenderer === null || itemSectionRenderer === void 0 ? void 0 : itemSectionRenderer.contents) || []);
17
+ const chapters = (_b = data[3].response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer) === null || _b === void 0 ? void 0 : _b.decoratedPlayerBarRenderer.playerBar.multiMarkersPlayerBarRenderer.markersMap[0].value.chapters;
18
+ target.chapters =
19
+ (chapters === null || chapters === void 0 ? void 0 : chapters.map(({ chapterRenderer: c }) => ({
20
+ title: c.title.simpleText,
21
+ start: c.timeRangeStartMillis,
22
+ thumbnails: new Thumbnails_1.Thumbnails().load(c.thumbnail.thumbnails),
23
+ }))) || [];
16
24
  return target;
17
25
  }
18
26
  static parseComments(data, video) {
@@ -45,5 +45,18 @@ class VideoCompact extends Base_1.Base {
45
45
  return yield this.client.getVideo(this.id);
46
46
  });
47
47
  }
48
+ /**
49
+ * Get Video transcript (if exists)
50
+ *
51
+ * Equivalent to
52
+ * ```js
53
+ * client.getVideoTranscript(video.id);
54
+ * ```
55
+ */
56
+ getTranscript() {
57
+ return __awaiter(this, void 0, void 0, function* () {
58
+ return this.client.getVideoTranscript(this.id);
59
+ });
60
+ }
48
61
  }
49
62
  exports.VideoCompact = VideoCompact;
@@ -20,14 +20,18 @@ class VideoCompactParser {
20
20
  target.isLive = !!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW");
21
21
  // Channel
22
22
  if (ownerText || shortBylineText) {
23
- const { browseId } = (ownerText || shortBylineText).runs[0].navigationEndpoint.browseEndpoint;
24
- const thumbnails = channelThumbnailSupportedRenderers === null || channelThumbnailSupportedRenderers === void 0 ? void 0 : channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail.thumbnails;
25
- target.channel = new BaseChannel_1.BaseChannel({
26
- id: browseId,
27
- name: (ownerText || shortBylineText).runs[0].text,
28
- thumbnails: thumbnails ? new Thumbnails_1.Thumbnails().load(thumbnails) : undefined,
29
- client: target.client,
30
- });
23
+ const browseEndpoint = (ownerText || shortBylineText).runs[0].navigationEndpoint
24
+ .browseEndpoint;
25
+ if (browseEndpoint) {
26
+ const id = browseEndpoint.browseId;
27
+ const thumbnails = channelThumbnailSupportedRenderers === null || channelThumbnailSupportedRenderers === void 0 ? void 0 : channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail.thumbnails;
28
+ target.channel = new BaseChannel_1.BaseChannel({
29
+ id,
30
+ name: (ownerText || shortBylineText).runs[0].text,
31
+ thumbnails: thumbnails ? new Thumbnails_1.Thumbnails().load(thumbnails) : undefined,
32
+ client: target.client,
33
+ });
34
+ }
31
35
  }
32
36
  target.viewCount = common_1.stripToInt((viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.simpleText) || (viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.runs[0].text));
33
37
  return target;
@@ -25,5 +25,6 @@ __exportStar(require("./PlaylistCompact"), exports);
25
25
  __exportStar(require("./Reply"), exports);
26
26
  __exportStar(require("./SearchResult"), exports);
27
27
  __exportStar(require("./Thumbnails"), exports);
28
+ __exportStar(require("./Transcript"), exports);
28
29
  __exportStar(require("./Video"), exports);
29
30
  __exportStar(require("./VideoCompact"), exports);
@@ -4,11 +4,12 @@ var BaseChannelParser = /** @class */ (function () {
4
4
  function BaseChannelParser() {
5
5
  }
6
6
  BaseChannelParser.loadBaseChannel = function (target, data) {
7
+ var _a;
7
8
  var channelId = data.channelId, title = data.title, thumbnail = data.thumbnail, videoCountText = data.videoCountText, subscriberCountText = data.subscriberCountText;
8
9
  target.id = channelId;
9
10
  target.name = title.simpleText;
10
11
  target.thumbnails = new Thumbnails().load(thumbnail.thumbnails);
11
- target.videoCount = stripToInt(videoCountText === null || videoCountText === void 0 ? void 0 : videoCountText.runs[0].text) || 0;
12
+ target.videoCount = stripToInt((_a = videoCountText === null || videoCountText === void 0 ? void 0 : videoCountText.runs) === null || _a === void 0 ? void 0 : _a[0].text) || 0; // TODO this sometimes contains subscriber count for some reason
12
13
  target.subscriberCount = subscriberCountText === null || subscriberCountText === void 0 ? void 0 : subscriberCountText.simpleText;
13
14
  return target;
14
15
  };
@@ -51,6 +51,7 @@ 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";
54
55
  import { Video } from "../Video";
55
56
  import { HTTP } from "./HTTP";
56
57
  /** Youtube Client */
@@ -171,6 +172,27 @@ var Client = /** @class */ (function () {
171
172
  });
172
173
  });
173
174
  };
175
+ Client.prototype.getVideoTranscript = function (videoId) {
176
+ return __awaiter(this, void 0, void 0, function () {
177
+ var bufferParams, response;
178
+ return __generator(this, function (_a) {
179
+ switch (_a.label) {
180
+ case 0:
181
+ bufferParams = TranscriptParamsProto.TranscriptParams.encode({ videoId: videoId });
182
+ return [4 /*yield*/, this.http.post(I_END_POINT + "/get_transcript", {
183
+ data: { params: Buffer.from(bufferParams).toString("base64") },
184
+ })];
185
+ case 1:
186
+ response = _a.sent();
187
+ if (!response.data.actions)
188
+ return [2 /*return*/, undefined];
189
+ return [2 /*return*/, response.data.actions[0].updateEngagementPanelAction.content.transcriptRenderer.body.transcriptBodyRenderer.cueGroups
190
+ .map(function (t) { return t.transcriptCueGroupRenderer.cues[0].transcriptCueRenderer; })
191
+ .map(function (t) { return new Transcript().load(t); })];
192
+ }
193
+ });
194
+ });
195
+ };
174
196
  return Client;
175
197
  }());
176
198
  export { Client };
@@ -0,0 +1,29 @@
1
+ import { TranscriptParser } from "./TranscriptParser";
2
+ /**
3
+ * Represent a single video transcript entry
4
+ */
5
+ var Transcript = /** @class */ (function () {
6
+ /** @hidden */
7
+ function Transcript(attr) {
8
+ Object.assign(this, attr);
9
+ }
10
+ Object.defineProperty(Transcript.prototype, "end", {
11
+ /** transcript end time in miliseconds */
12
+ get: function () {
13
+ return this.start + this.duration;
14
+ },
15
+ enumerable: false,
16
+ configurable: true
17
+ });
18
+ /**
19
+ * Load this instance with raw data from Youtube
20
+ *
21
+ * @hidden
22
+ */
23
+ Transcript.prototype.load = function (data) {
24
+ TranscriptParser.loadTranscript(this, data);
25
+ return this;
26
+ };
27
+ return Transcript;
28
+ }());
29
+ export { Transcript };
@@ -0,0 +1,13 @@
1
+ var TranscriptParser = /** @class */ (function () {
2
+ function TranscriptParser() {
3
+ }
4
+ TranscriptParser.loadTranscript = function (target, data) {
5
+ var cue = data.cue, startOffsetMs = data.startOffsetMs, durationMs = data.durationMs;
6
+ target.text = cue.simpleText;
7
+ target.duration = +durationMs;
8
+ target.start = +startOffsetMs;
9
+ return target;
10
+ };
11
+ return TranscriptParser;
12
+ }());
13
+ export { TranscriptParser };
@@ -0,0 +1,3 @@
1
+ export * from "./proto";
2
+ export * from "./Transcript";
3
+ export * from "./TranscriptParser";
@@ -0,0 +1,2 @@
1
+ import proto from "protocol-buffers";
2
+ export var TranscriptParamsProto = proto("\n\tmessage TranscriptParams {\n\t\toptional string videoId = 1;\n\t}\n");
@@ -0,0 +1 @@
1
+ export * from "./TranscriptParamsProto";
@@ -11,6 +11,42 @@ var __extends = (this && this.__extends) || (function () {
11
11
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12
12
  };
13
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
+ };
14
50
  import { BaseVideo } from "../BaseVideo";
15
51
  import { VideoComments } from "./VideoComments";
16
52
  import { VideoParser } from "./VideoParser";
@@ -34,6 +70,21 @@ var Video = /** @class */ (function (_super) {
34
70
  VideoParser.loadVideo(this, data);
35
71
  return this;
36
72
  };
73
+ /**
74
+ * Get Video transcript (if exists)
75
+ *
76
+ * Equivalent to
77
+ * ```js
78
+ * client.getVideoTranscript(video.id);
79
+ * ```
80
+ */
81
+ Video.prototype.getTranscript = function () {
82
+ return __awaiter(this, void 0, void 0, function () {
83
+ return __generator(this, function (_a) {
84
+ return [2 /*return*/, this.client.getVideoTranscript(this.id)];
85
+ });
86
+ });
87
+ };
37
88
  return Video;
38
89
  }(BaseVideo));
39
90
  export { Video };
@@ -1,17 +1,28 @@
1
1
  import { getContinuationFromItems, mapFilter } from "../../common";
2
2
  import { BaseVideoParser } from "../BaseVideo";
3
3
  import { Comment } from "../Comment";
4
+ import { Thumbnails } from "../Thumbnails";
4
5
  var VideoParser = /** @class */ (function () {
5
6
  function VideoParser() {
6
7
  }
7
8
  VideoParser.loadVideo = function (target, data) {
8
- var _a;
9
+ var _a, _b;
9
10
  var videoInfo = BaseVideoParser.parseRawData(data);
10
11
  target.duration = +videoInfo.videoDetails.lengthSeconds;
11
12
  var itemSectionRenderer = (_a = data[3].response.contents.twoColumnWatchNextResults.results.results.contents
12
13
  .reverse()
13
14
  .find(function (c) { return c.itemSectionRenderer; })) === null || _a === void 0 ? void 0 : _a.itemSectionRenderer;
14
15
  target.comments.continuation = getContinuationFromItems((itemSectionRenderer === null || itemSectionRenderer === void 0 ? void 0 : itemSectionRenderer.contents) || []);
16
+ var chapters = (_b = data[3].response.playerOverlays.playerOverlayRenderer.decoratedPlayerBarRenderer) === null || _b === void 0 ? void 0 : _b.decoratedPlayerBarRenderer.playerBar.multiMarkersPlayerBarRenderer.markersMap[0].value.chapters;
17
+ target.chapters =
18
+ (chapters === null || chapters === void 0 ? void 0 : chapters.map(function (_a) {
19
+ var c = _a.chapterRenderer;
20
+ return ({
21
+ title: c.title.simpleText,
22
+ start: c.timeRangeStartMillis,
23
+ thumbnails: new Thumbnails().load(c.thumbnail.thumbnails),
24
+ });
25
+ })) || [];
15
26
  return target;
16
27
  };
17
28
  VideoParser.parseComments = function (data, video) {
@@ -93,6 +93,21 @@ var VideoCompact = /** @class */ (function (_super) {
93
93
  });
94
94
  });
95
95
  };
96
+ /**
97
+ * Get Video transcript (if exists)
98
+ *
99
+ * Equivalent to
100
+ * ```js
101
+ * client.getVideoTranscript(video.id);
102
+ * ```
103
+ */
104
+ VideoCompact.prototype.getTranscript = function () {
105
+ return __awaiter(this, void 0, void 0, function () {
106
+ return __generator(this, function (_a) {
107
+ return [2 /*return*/, this.client.getVideoTranscript(this.id)];
108
+ });
109
+ });
110
+ };
96
111
  return VideoCompact;
97
112
  }(Base));
98
113
  export { VideoCompact };
@@ -19,14 +19,18 @@ var VideoCompactParser = /** @class */ (function () {
19
19
  target.isLive = !!((badges === null || badges === void 0 ? void 0 : badges[0].metadataBadgeRenderer.style) === "BADGE_STYLE_TYPE_LIVE_NOW");
20
20
  // Channel
21
21
  if (ownerText || shortBylineText) {
22
- var browseId = (ownerText || shortBylineText).runs[0].navigationEndpoint.browseEndpoint.browseId;
23
- var thumbnails = channelThumbnailSupportedRenderers === null || channelThumbnailSupportedRenderers === void 0 ? void 0 : channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail.thumbnails;
24
- target.channel = new BaseChannel({
25
- id: browseId,
26
- name: (ownerText || shortBylineText).runs[0].text,
27
- thumbnails: thumbnails ? new Thumbnails().load(thumbnails) : undefined,
28
- client: target.client,
29
- });
22
+ var browseEndpoint = (ownerText || shortBylineText).runs[0].navigationEndpoint
23
+ .browseEndpoint;
24
+ if (browseEndpoint) {
25
+ var id = browseEndpoint.browseId;
26
+ var thumbnails = channelThumbnailSupportedRenderers === null || channelThumbnailSupportedRenderers === void 0 ? void 0 : channelThumbnailSupportedRenderers.channelThumbnailWithLinkRenderer.thumbnail.thumbnails;
27
+ target.channel = new BaseChannel({
28
+ id: id,
29
+ name: (ownerText || shortBylineText).runs[0].text,
30
+ thumbnails: thumbnails ? new Thumbnails().load(thumbnails) : undefined,
31
+ client: target.client,
32
+ });
33
+ }
30
34
  }
31
35
  target.viewCount = stripToInt((viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.simpleText) || (viewCountText === null || viewCountText === void 0 ? void 0 : viewCountText.runs[0].text));
32
36
  return target;
@@ -13,5 +13,6 @@ export * from "./PlaylistCompact";
13
13
  export * from "./Reply";
14
14
  export * from "./SearchResult";
15
15
  export * from "./Thumbnails";
16
+ export * from "./Transcript";
16
17
  export * from "./Video";
17
18
  export * from "./VideoCompact";
@@ -4,6 +4,7 @@ import { LiveVideo } from "../LiveVideo";
4
4
  import { MixPlaylist } from "../MixPlaylist";
5
5
  import { Playlist } from "../Playlist";
6
6
  import { SearchOptions, SearchResult, SearchResultItem } from "../SearchResult";
7
+ import { Transcript } from "../Transcript";
7
8
  import { Video } from "../Video";
8
9
  import { HTTP } from "./HTTP";
9
10
  export declare type ClientOptions = {
@@ -38,4 +39,5 @@ export declare class Client {
38
39
  getVideo<T extends Video | LiveVideo | undefined>(videoId: string): Promise<T>;
39
40
  /** Get channel information by channel id+ */
40
41
  getChannel(channelId: string): Promise<Channel | undefined>;
42
+ getVideoTranscript(videoId: string): Promise<Transcript[] | undefined>;
41
43
  }
@@ -0,0 +1,29 @@
1
+ import { YoutubeRawData } from "../../common";
2
+ /** @hidden */
3
+ interface TranscriptProperties {
4
+ text?: string;
5
+ start?: number;
6
+ duration?: number;
7
+ }
8
+ /**
9
+ * Represent a single video transcript entry
10
+ */
11
+ export declare class Transcript implements TranscriptProperties {
12
+ /** transcript content */
13
+ text: string;
14
+ /** transcript start time in miliseconds */
15
+ start: number;
16
+ /** transcript duration in miliseconds */
17
+ duration: number;
18
+ /** @hidden */
19
+ constructor(attr?: TranscriptProperties);
20
+ /** transcript end time in miliseconds */
21
+ get end(): number;
22
+ /**
23
+ * Load this instance with raw data from Youtube
24
+ *
25
+ * @hidden
26
+ */
27
+ load(data: YoutubeRawData): Transcript;
28
+ }
29
+ export {};
@@ -0,0 +1,5 @@
1
+ import { YoutubeRawData } from "../../common";
2
+ import { Transcript } from "./Transcript";
3
+ export declare class TranscriptParser {
4
+ static loadTranscript(target: Transcript, data: YoutubeRawData): Transcript;
5
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./proto";
2
+ export * from "./Transcript";
3
+ export * from "./TranscriptParser";
@@ -0,0 +1,16 @@
1
+ /// <reference types="node" />
2
+ export declare type TranscriptParams = {
3
+ TranscriptParams: {
4
+ videoId: string;
5
+ };
6
+ };
7
+ export declare const TranscriptParamsProto: {
8
+ TranscriptParams: {
9
+ encode: (obj: {
10
+ videoId: string;
11
+ }) => Buffer;
12
+ decode: (buf: Buffer) => {
13
+ videoId: string;
14
+ };
15
+ };
16
+ };
@@ -0,0 +1 @@
1
+ export * from "./TranscriptParamsProto";
@@ -1,15 +1,25 @@
1
1
  import { YoutubeRawData } from "../../common";
2
2
  import { BaseVideo, BaseVideoProperties } from "../BaseVideo";
3
+ import { Thumbnails } from "../Thumbnails";
4
+ import { Transcript } from "../Transcript";
3
5
  import { VideoComments } from "./VideoComments";
6
+ export declare type Chapter = {
7
+ title: string;
8
+ start: number;
9
+ thumbnails: Thumbnails;
10
+ };
4
11
  /** @hidden */
5
12
  interface VideoProperties extends BaseVideoProperties {
6
13
  duration?: number;
7
14
  comments?: VideoComments;
15
+ chapters?: Chapter[];
8
16
  }
9
17
  /** Represents a Video, usually returned from `client.getVideo()` */
10
18
  export declare class Video extends BaseVideo implements VideoProperties {
11
19
  /** The duration of this video in second */
12
20
  duration: number;
21
+ /** Chapters on this video if exists */
22
+ chapters: Chapter[];
13
23
  /** {@link Continuable} of videos inside a {@link Video} */
14
24
  comments: VideoComments;
15
25
  /** @hidden */
@@ -20,5 +30,14 @@ export declare class Video extends BaseVideo implements VideoProperties {
20
30
  * @hidden
21
31
  */
22
32
  load(data: YoutubeRawData): Video;
33
+ /**
34
+ * Get Video transcript (if exists)
35
+ *
36
+ * Equivalent to
37
+ * ```js
38
+ * client.getVideoTranscript(video.id);
39
+ * ```
40
+ */
41
+ getTranscript(): Promise<Transcript[] | undefined>;
23
42
  }
24
43
  export {};
@@ -3,6 +3,7 @@ import { Base, BaseProperties } from "../Base";
3
3
  import { BaseChannel } from "../BaseChannel";
4
4
  import { LiveVideo } from "../LiveVideo";
5
5
  import { Thumbnails } from "../Thumbnails";
6
+ import { Transcript } from "../Transcript";
6
7
  import { Video } from "../Video";
7
8
  /** @hidden */
8
9
  interface VideoCompactProperties extends BaseProperties {
@@ -53,5 +54,14 @@ export declare class VideoCompact extends Base implements VideoCompactProperties
53
54
  * ```
54
55
  */
55
56
  getVideo<T extends Video | LiveVideo>(): Promise<T>;
57
+ /**
58
+ * Get Video transcript (if exists)
59
+ *
60
+ * Equivalent to
61
+ * ```js
62
+ * client.getVideoTranscript(video.id);
63
+ * ```
64
+ */
65
+ getTranscript(): Promise<Transcript[] | undefined>;
56
66
  }
57
67
  export {};
@@ -13,5 +13,6 @@ export * from "./PlaylistCompact";
13
13
  export * from "./Reply";
14
14
  export * from "./SearchResult";
15
15
  export * from "./Thumbnails";
16
+ export * from "./Transcript";
16
17
  export * from "./Video";
17
18
  export * from "./VideoCompact";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "youtubei",
3
- "version": "1.0.0-rc.6",
3
+ "version": "1.0.0-rc.8",
4
4
  "description": "Simple package to get information from youtube such as videos, playlists, channels, video information & comments, related videos, up next video, and more!",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -9,7 +9,7 @@
9
9
  "test": "test"
10
10
  },
11
11
  "devDependencies": {
12
- "@trivago/prettier-plugin-sort-imports": "3.2.0",
12
+ "@trivago/prettier-plugin-sort-imports": "3.4.0",
13
13
  "@types/node": "14.14.12",
14
14
  "@types/node-fetch": "2.6.2",
15
15
  "@typescript-eslint/eslint-plugin": "4.9.1",