youtubei 1.3.7 → 1.4.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/dist/cjs/common/shared/HTTP/HTTP.js +18 -7
- package/dist/cjs/youtube/BaseVideo/BaseVideoParser.js +7 -2
- package/dist/cjs/youtube/BaseVideo/VideoCaptions.js +81 -0
- package/dist/cjs/youtube/BaseVideo/index.js +1 -0
- package/dist/cjs/youtube/Caption/Caption.js +17 -0
- package/dist/cjs/youtube/Caption/CaptionLanguage.js +17 -0
- package/dist/cjs/youtube/{Transcript/proto → Caption}/index.js +2 -1
- package/dist/cjs/youtube/Channel/ChannelParser.js +28 -7
- package/dist/cjs/youtube/Client/Client.js +9 -13
- package/dist/cjs/youtube/Comment/CommentParser.js +11 -12
- package/dist/cjs/youtube/LiveVideo/LiveVideo.js +15 -15
- package/dist/cjs/youtube/Video/Video.js +4 -6
- package/dist/cjs/youtube/Video/VideoParser.js +3 -3
- package/dist/cjs/youtube/VideoCompact/VideoCompact.js +2 -2
- package/dist/cjs/youtube/VideoCompact/VideoCompactParser.js +4 -2
- package/dist/cjs/youtube/index.js +1 -1
- package/dist/esm/common/shared/HTTP/HTTP.js +59 -12
- package/dist/esm/youtube/BaseVideo/BaseVideoParser.js +7 -2
- package/dist/esm/youtube/BaseVideo/VideoCaptions.js +133 -0
- package/dist/esm/youtube/BaseVideo/index.js +1 -0
- package/dist/esm/youtube/Caption/Caption.js +19 -0
- package/dist/esm/youtube/Caption/CaptionLanguage.js +15 -0
- package/dist/esm/youtube/Caption/index.js +2 -0
- package/dist/esm/youtube/Channel/ChannelParser.js +28 -7
- package/dist/esm/youtube/Client/Client.js +13 -18
- package/dist/esm/youtube/Comment/CommentParser.js +11 -12
- package/dist/esm/youtube/LiveVideo/LiveVideo.js +15 -15
- package/dist/esm/youtube/Video/Video.js +5 -7
- package/dist/esm/youtube/Video/VideoParser.js +4 -4
- package/dist/esm/youtube/VideoCompact/VideoCompact.js +2 -2
- package/dist/esm/youtube/VideoCompact/VideoCompactParser.js +4 -2
- package/dist/esm/youtube/index.js +1 -1
- package/dist/typings/common/shared/HTTP/HTTP.d.ts +2 -2
- package/dist/typings/youtube/BaseVideo/BaseVideo.d.ts +3 -0
- package/dist/typings/youtube/BaseVideo/VideoCaptions.d.ts +40 -0
- package/dist/typings/youtube/BaseVideo/index.d.ts +1 -0
- package/dist/typings/youtube/Caption/Caption.d.ts +22 -0
- package/dist/typings/youtube/Caption/CaptionLanguage.d.ts +30 -0
- package/dist/typings/youtube/Caption/index.d.ts +2 -0
- package/dist/typings/youtube/Client/Client.d.ts +8 -3
- package/dist/typings/youtube/LiveVideo/LiveVideo.d.ts +5 -5
- package/dist/typings/youtube/Video/Video.d.ts +3 -6
- package/dist/typings/youtube/VideoCompact/VideoCompact.d.ts +2 -2
- package/dist/typings/youtube/index.d.ts +1 -1
- package/package.json +2 -2
- package/dist/cjs/youtube/Transcript/Transcript.js +0 -27
- package/dist/cjs/youtube/Transcript/TranscriptParser.js +0 -13
- package/dist/cjs/youtube/Transcript/index.js +0 -15
- package/dist/cjs/youtube/Transcript/proto/TranscriptParamsProto.js +0 -12
- package/dist/esm/youtube/Transcript/Transcript.js +0 -29
- package/dist/esm/youtube/Transcript/TranscriptParser.js +0 -13
- package/dist/esm/youtube/Transcript/index.js +0 -3
- package/dist/esm/youtube/Transcript/proto/TranscriptParamsProto.js +0 -2
- package/dist/esm/youtube/Transcript/proto/index.js +0 -1
- package/dist/typings/youtube/Transcript/Transcript.d.ts +0 -29
- package/dist/typings/youtube/Transcript/TranscriptParser.d.ts +0 -5
- package/dist/typings/youtube/Transcript/index.d.ts +0 -3
- package/dist/typings/youtube/Transcript/proto/TranscriptParamsProto.d.ts +0 -7
- package/dist/typings/youtube/Transcript/proto/index.d.ts +0 -1
|
@@ -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(video.captions.languages.map((l) => `${l.code} - ${l.name}`)); // printing out available languages for captions
|
|
59
|
+
*
|
|
60
|
+
* console.log(await video.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 };
|
|
@@ -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 };
|
|
@@ -17,16 +17,37 @@ var ChannelParser = /** @class */ (function () {
|
|
|
17
17
|
function ChannelParser() {
|
|
18
18
|
}
|
|
19
19
|
ChannelParser.loadChannel = function (target, data) {
|
|
20
|
-
var _a
|
|
20
|
+
var _a, _b, _c;
|
|
21
|
+
var channelId, title, avatar, subscriberCountText, tvBanner, mobileBanner, banner;
|
|
22
|
+
var _d = data.header, c4TabbedHeaderRenderer = _d.c4TabbedHeaderRenderer, pageHeaderRenderer = _d.pageHeaderRenderer;
|
|
23
|
+
if (c4TabbedHeaderRenderer) {
|
|
24
|
+
channelId = c4TabbedHeaderRenderer.channelId;
|
|
25
|
+
title = c4TabbedHeaderRenderer.title;
|
|
26
|
+
subscriberCountText = (_a = c4TabbedHeaderRenderer.subscriberCountText) === null || _a === void 0 ? void 0 : _a.simpleText;
|
|
27
|
+
avatar = (_b = c4TabbedHeaderRenderer.avatar) === null || _b === void 0 ? void 0 : _b.thumbnails;
|
|
28
|
+
tvBanner = (_c = c4TabbedHeaderRenderer.tvBanner) === null || _c === void 0 ? void 0 : _c.thumbnails;
|
|
29
|
+
mobileBanner = c4TabbedHeaderRenderer.mobileBanner.thumbnails;
|
|
30
|
+
banner = c4TabbedHeaderRenderer.banner.thumbnails;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
channelId =
|
|
34
|
+
data.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.endpoint
|
|
35
|
+
.browseEndpoint.browseId;
|
|
36
|
+
title = pageHeaderRenderer.pageTitle;
|
|
37
|
+
var _e = pageHeaderRenderer.content.pageHeaderViewModel, metadata = _e.metadata, imageModel = _e.image, bannerModel = _e.banner;
|
|
38
|
+
subscriberCountText =
|
|
39
|
+
metadata.contentMetadataViewModel.metadataRows[1].metadataParts[0].text.content;
|
|
40
|
+
avatar = imageModel.decoratedAvatarViewModel.avatar.avatarViewModel.image.sources;
|
|
41
|
+
banner = bannerModel.imageBannerViewModel.image.sources;
|
|
42
|
+
}
|
|
21
43
|
target.id = channelId;
|
|
22
44
|
target.name = title;
|
|
23
|
-
target.thumbnails = new Thumbnails().load(avatar
|
|
45
|
+
target.thumbnails = new Thumbnails().load(avatar);
|
|
24
46
|
target.videoCount = 0; // data not available
|
|
25
|
-
target.subscriberCount = subscriberCountText
|
|
26
|
-
|
|
27
|
-
target.
|
|
28
|
-
target.
|
|
29
|
-
target.mobileBanner = new Thumbnails().load((mobileBanner === null || mobileBanner === void 0 ? void 0 : mobileBanner.thumbnails) || []);
|
|
47
|
+
target.subscriberCount = subscriberCountText;
|
|
48
|
+
target.banner = new Thumbnails().load(banner || []);
|
|
49
|
+
target.tvBanner = new Thumbnails().load(tvBanner || []);
|
|
50
|
+
target.mobileBanner = new Thumbnails().load(mobileBanner || []);
|
|
30
51
|
target.shelves = ChannelParser.parseShelves(target, data);
|
|
31
52
|
return target;
|
|
32
53
|
};
|
|
@@ -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
|
-
|
|
62
|
-
this.http = new HTTP(__assign({ apiKey: INNERTUBE_API_KEY, baseUrl: BASE_URL, clientName: INNERTUBE_CLIENT_NAME, clientVersion: INNERTUBE_CLIENT_VERSION },
|
|
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
|
|
@@ -177,23 +176,19 @@ var Client = /** @class */ (function () {
|
|
|
177
176
|
});
|
|
178
177
|
});
|
|
179
178
|
};
|
|
180
|
-
|
|
179
|
+
/**
|
|
180
|
+
* Get video transcript / caption by video id
|
|
181
|
+
*/
|
|
182
|
+
Client.prototype.getVideoTranscript = function (videoId, languageCode) {
|
|
183
|
+
var _a;
|
|
181
184
|
return __awaiter(this, void 0, void 0, function () {
|
|
182
|
-
var
|
|
183
|
-
return __generator(this, function (
|
|
184
|
-
switch (
|
|
185
|
-
case 0:
|
|
186
|
-
bufferParams = TranscriptParamsProto.encode({ videoId: videoId }).finish();
|
|
187
|
-
return [4 /*yield*/, this.http.post(I_END_POINT + "/get_transcript", {
|
|
188
|
-
data: { params: Buffer.from(bufferParams).toString("base64") },
|
|
189
|
-
})];
|
|
185
|
+
var video;
|
|
186
|
+
return __generator(this, function (_b) {
|
|
187
|
+
switch (_b.label) {
|
|
188
|
+
case 0: return [4 /*yield*/, this.getVideo(videoId)];
|
|
190
189
|
case 1:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return [2 /*return*/, undefined];
|
|
194
|
-
return [2 /*return*/, response.data.actions[0].updateEngagementPanelAction.content.transcriptRenderer.body.transcriptBodyRenderer.cueGroups
|
|
195
|
-
.map(function (t) { return t.transcriptCueGroupRenderer.cues[0].transcriptCueRenderer; })
|
|
196
|
-
.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)];
|
|
197
192
|
}
|
|
198
193
|
});
|
|
199
194
|
});
|
|
@@ -5,25 +5,24 @@ var CommentParser = /** @class */ (function () {
|
|
|
5
5
|
function CommentParser() {
|
|
6
6
|
}
|
|
7
7
|
CommentParser.loadComment = function (target, data) {
|
|
8
|
-
var
|
|
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 =
|
|
12
|
-
target.publishDate =
|
|
13
|
-
target.likeCount = +
|
|
14
|
-
target.isAuthorChannelOwner =
|
|
15
|
-
target.isPinned =
|
|
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:
|
|
25
|
-
name:
|
|
26
|
-
thumbnails: new Thumbnails().load(
|
|
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.
|
|
74
|
-
_this.
|
|
75
|
-
_this.
|
|
76
|
-
_this.
|
|
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.
|
|
97
|
+
if (this.isChatPlaying)
|
|
98
98
|
return;
|
|
99
|
-
this.
|
|
100
|
-
this.
|
|
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.
|
|
105
|
+
if (!this.chatRequestPoolingTimeout)
|
|
106
106
|
return;
|
|
107
|
-
this.
|
|
108
|
-
clearTimeout(this.
|
|
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.
|
|
128
|
+
if (this_1.chatQueue.find(function (c) { return c.id === chat.id; }))
|
|
129
129
|
return "continue";
|
|
130
|
-
this_1.
|
|
131
|
-
var timeout_1 = chat.timestamp / 1000 - (new Date().getTime() - this_1.
|
|
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.
|
|
149
|
+
this.timeoutMs = timeout;
|
|
150
150
|
this.chatContinuation = continuation;
|
|
151
|
-
this.
|
|
151
|
+
this.chatRequestPoolingTimeout = setTimeout(function () { return _this.pollChatContinuation(); }, this.timeoutMs);
|
|
152
152
|
return [2 /*return*/];
|
|
153
153
|
}
|
|
154
154
|
});
|
|
@@ -73,15 +73,13 @@ var Video = /** @class */ (function (_super) {
|
|
|
73
73
|
/**
|
|
74
74
|
* Get Video transcript (if exists)
|
|
75
75
|
*
|
|
76
|
-
*
|
|
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 (
|
|
84
|
-
return [2 /*return*/, this.
|
|
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,
|
|
1
|
+
import { getContinuationFromItems, Thumbnails } from "../../common";
|
|
2
2
|
import { BaseVideoParser } from "../BaseVideo";
|
|
3
3
|
import { Comment } from "../Comment";
|
|
4
4
|
var VideoParser = /** @class */ (function () {
|
|
@@ -25,9 +25,9 @@ var VideoParser = /** @class */ (function () {
|
|
|
25
25
|
return target;
|
|
26
26
|
};
|
|
27
27
|
VideoParser.parseComments = function (data, video) {
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
|
|
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,7 +4,7 @@ var VideoCompactParser = /** @class */ (function () {
|
|
|
4
4
|
function VideoCompactParser() {
|
|
5
5
|
}
|
|
6
6
|
VideoCompactParser.loadVideoCompact = function (target, data) {
|
|
7
|
-
var _a, _b, _c, _d;
|
|
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
10
|
target.title = headline
|
|
@@ -17,7 +17,9 @@ var VideoCompactParser = /** @class */ (function () {
|
|
|
17
17
|
target.duration =
|
|
18
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) ||
|
|
19
19
|
"") || null;
|
|
20
|
-
target.isLive =
|
|
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";
|
|
21
23
|
// Channel
|
|
22
24
|
if (ownerText || shortBylineText) {
|
|
23
25
|
var browseEndpoint = (ownerText || shortBylineText).runs[0].navigationEndpoint
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./Base";
|
|
2
2
|
export * from "./BaseChannel";
|
|
3
3
|
export * from "./BaseVideo";
|
|
4
|
+
export * from "./Caption";
|
|
4
5
|
export * from "./Channel";
|
|
5
6
|
export * from "./Chat";
|
|
6
7
|
export * from "./Client";
|
|
@@ -12,6 +13,5 @@ export * from "./Playlist";
|
|
|
12
13
|
export * from "./PlaylistCompact";
|
|
13
14
|
export * from "./Reply";
|
|
14
15
|
export * from "./SearchResult";
|
|
15
|
-
export * from "./Transcript";
|
|
16
16
|
export * from "./Video";
|
|
17
17
|
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(
|
|
32
|
-
post(
|
|
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(video.captions.languages.map((l) => `${l.code} - ${l.name}`)); // printing out available languages for captions
|
|
18
|
+
*
|
|
19
|
+
* console.log(await video.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 {};
|
|
@@ -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 {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { VideoCaptions } from "../BaseVideo";
|
|
2
|
+
import { Caption } from "./Caption";
|
|
3
|
+
/** @hidden */
|
|
4
|
+
interface CaptionLanguageProperties {
|
|
5
|
+
name?: string;
|
|
6
|
+
code?: string;
|
|
7
|
+
isTranslatable?: boolean;
|
|
8
|
+
url?: string;
|
|
9
|
+
captions?: VideoCaptions;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Represents a caption language option
|
|
13
|
+
*/
|
|
14
|
+
export declare class CaptionLanguage implements CaptionLanguageProperties {
|
|
15
|
+
/** Caption language name */
|
|
16
|
+
name: string;
|
|
17
|
+
/** Caption language code */
|
|
18
|
+
code: string;
|
|
19
|
+
/** Whether this language is translatable */
|
|
20
|
+
isTranslatable: boolean;
|
|
21
|
+
/** Caption language url */
|
|
22
|
+
url: string;
|
|
23
|
+
/** @hidden */
|
|
24
|
+
captions: VideoCaptions;
|
|
25
|
+
/** @hidden */
|
|
26
|
+
constructor(attr?: CaptionLanguageProperties);
|
|
27
|
+
/** Get the captions of this language using the url */
|
|
28
|
+
get(translationLanguageCode?: string): Promise<Caption[] | undefined>;
|
|
29
|
+
}
|
|
30
|
+
export {};
|