youtube-transcript-plus 1.0.2 → 1.0.4
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/README.md +15 -0
- package/dist/index.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/youtube-transcript-plus.js +32 -28
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -42,6 +42,20 @@ fetchTranscript('videoId_or_URL', {
|
|
|
42
42
|
.catch(console.error);
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
### HTTP Support
|
|
46
|
+
|
|
47
|
+
You can disable HTTPS and use HTTP instead for YouTube requests by setting the `disableHttps` option to `true`. This might be necessary in certain environments where HTTPS connections are restricted.
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
fetchTranscript('videoId_or_URL', {
|
|
51
|
+
disableHttps: true, // Use HTTP instead of HTTPS
|
|
52
|
+
})
|
|
53
|
+
.then(console.log)
|
|
54
|
+
.catch(console.error);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Security Warning:** Using HTTP instead of HTTPS removes transport layer security and is not recommended for production environments. Only use this option when absolutely necessary.
|
|
58
|
+
|
|
45
59
|
### Custom Fetch Functions
|
|
46
60
|
|
|
47
61
|
You can inject custom `videoFetch` and `transcriptFetch` functions to modify the fetch behavior, such as using a proxy or custom headers.
|
|
@@ -188,6 +202,7 @@ Fetches the transcript for a YouTube video.
|
|
|
188
202
|
- **`userAgent`**: Custom User-Agent string.
|
|
189
203
|
- **`cache`**: Custom caching strategy.
|
|
190
204
|
- **`cacheTTL`**: Time-to-live for cache entries in milliseconds.
|
|
205
|
+
- **`disableHttps`**: Set to `true` to use HTTP instead of HTTPS for YouTube requests.
|
|
191
206
|
- **`videoFetch`**: Custom fetch function for the video page request.
|
|
192
207
|
- **`transcriptFetch`**: Custom fetch function for the transcript request.
|
|
193
208
|
|
package/dist/index.d.ts
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -85,7 +85,7 @@ function retrieveVideoId(videoId) {
|
|
|
85
85
|
throw new YoutubeTranscriptInvalidVideoIdError();
|
|
86
86
|
}
|
|
87
87
|
function defaultFetch(_a) {
|
|
88
|
-
return __awaiter(this, arguments,
|
|
88
|
+
return __awaiter(this, arguments, void 0, function* ({ url, lang, userAgent, }) {
|
|
89
89
|
return fetch(url, {
|
|
90
90
|
headers: Object.assign(Object.assign({}, (lang && { 'Accept-Language': lang })), { 'User-Agent': userAgent || DEFAULT_USER_AGENT }),
|
|
91
91
|
});
|
|
@@ -99,7 +99,7 @@ class FsCache {
|
|
|
99
99
|
fs.mkdir(cacheDir, { recursive: true }).catch(() => { });
|
|
100
100
|
}
|
|
101
101
|
get(key) {
|
|
102
|
-
return __awaiter(this,
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
103
|
const filePath = path.join(this.cacheDir, key);
|
|
104
104
|
try {
|
|
105
105
|
const data = yield fs.readFile(filePath, 'utf-8');
|
|
@@ -114,9 +114,9 @@ class FsCache {
|
|
|
114
114
|
});
|
|
115
115
|
}
|
|
116
116
|
set(key, value, ttl) {
|
|
117
|
-
return __awaiter(this,
|
|
117
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
118
118
|
const filePath = path.join(this.cacheDir, key);
|
|
119
|
-
const expires = Date.now() + (ttl !== null && ttl !==
|
|
119
|
+
const expires = Date.now() + (ttl !== null && ttl !== void 0 ? ttl : this.defaultTTL);
|
|
120
120
|
yield fs.writeFile(filePath, JSON.stringify({ value, expires }), 'utf-8');
|
|
121
121
|
});
|
|
122
122
|
}
|
|
@@ -129,7 +129,7 @@ class InMemoryCache {
|
|
|
129
129
|
this.defaultTTL = defaultTTL;
|
|
130
130
|
}
|
|
131
131
|
get(key) {
|
|
132
|
-
return __awaiter(this,
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
133
|
const entry = this.cache.get(key);
|
|
134
134
|
if (entry && entry.expires > Date.now()) {
|
|
135
135
|
return entry.value;
|
|
@@ -139,8 +139,8 @@ class InMemoryCache {
|
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
set(key, value, ttl) {
|
|
142
|
-
return __awaiter(this,
|
|
143
|
-
const expires = Date.now() + (ttl !== null && ttl !==
|
|
142
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
143
|
+
const expires = Date.now() + (ttl !== null && ttl !== void 0 ? ttl : this.defaultTTL);
|
|
144
144
|
this.cache.set(key, { value, expires });
|
|
145
145
|
});
|
|
146
146
|
}
|
|
@@ -151,26 +151,27 @@ class YoutubeTranscript {
|
|
|
151
151
|
this.config = config;
|
|
152
152
|
}
|
|
153
153
|
fetchTranscript(videoId) {
|
|
154
|
-
return __awaiter(this,
|
|
155
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
154
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
155
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
156
156
|
const identifier = retrieveVideoId(videoId);
|
|
157
|
-
const userAgent = ((_a = this.config) === null || _a ===
|
|
157
|
+
const userAgent = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.userAgent) || DEFAULT_USER_AGENT;
|
|
158
158
|
// Use custom fetch functions if provided, otherwise use defaultFetch
|
|
159
|
-
const videoFetch = ((_b = this.config) === null || _b ===
|
|
160
|
-
const transcriptFetch = ((_c = this.config) === null || _c ===
|
|
159
|
+
const videoFetch = ((_b = this.config) === null || _b === void 0 ? void 0 : _b.videoFetch) || defaultFetch;
|
|
160
|
+
const transcriptFetch = ((_c = this.config) === null || _c === void 0 ? void 0 : _c.transcriptFetch) || defaultFetch;
|
|
161
161
|
// Cache key based on video ID and language
|
|
162
|
-
const cacheKey = `transcript:${identifier}:${((_d = this.config) === null || _d ===
|
|
162
|
+
const cacheKey = `transcript:${identifier}:${((_d = this.config) === null || _d === void 0 ? void 0 : _d.lang) || 'default'}`;
|
|
163
163
|
// Check cache first
|
|
164
|
-
if ((_e = this.config) === null || _e ===
|
|
164
|
+
if ((_e = this.config) === null || _e === void 0 ? void 0 : _e.cache) {
|
|
165
165
|
const cachedTranscript = yield this.config.cache.get(cacheKey);
|
|
166
166
|
if (cachedTranscript) {
|
|
167
167
|
return JSON.parse(cachedTranscript);
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
+
const protocol = ((_f = this.config) === null || _f === void 0 ? void 0 : _f.disableHttps) ? 'http' : 'https';
|
|
170
171
|
// Fetch the video page
|
|
171
172
|
const videoPageResponse = yield videoFetch({
|
|
172
|
-
url:
|
|
173
|
-
lang: (
|
|
173
|
+
url: `${protocol}://www.youtube.com/watch?v=${identifier}`,
|
|
174
|
+
lang: (_g = this.config) === null || _g === void 0 ? void 0 : _g.lang,
|
|
174
175
|
userAgent,
|
|
175
176
|
});
|
|
176
177
|
if (!videoPageResponse.ok) {
|
|
@@ -188,31 +189,34 @@ class YoutubeTranscript {
|
|
|
188
189
|
}
|
|
189
190
|
throw new YoutubeTranscriptDisabledError(identifier);
|
|
190
191
|
}
|
|
191
|
-
const captions = (
|
|
192
|
+
const captions = (_h = (() => {
|
|
192
193
|
try {
|
|
193
194
|
return JSON.parse(splittedHTML[1].split(',"videoDetails')[0].replace('\n', ''));
|
|
194
195
|
}
|
|
195
196
|
catch (e) {
|
|
196
197
|
return undefined;
|
|
197
198
|
}
|
|
198
|
-
})()) === null ||
|
|
199
|
+
})()) === null || _h === void 0 ? void 0 : _h['playerCaptionsTracklistRenderer'];
|
|
199
200
|
if (!captions) {
|
|
200
201
|
throw new YoutubeTranscriptDisabledError(identifier);
|
|
201
202
|
}
|
|
202
203
|
if (!('captionTracks' in captions)) {
|
|
203
204
|
throw new YoutubeTranscriptNotAvailableError(identifier);
|
|
204
205
|
}
|
|
205
|
-
if (((
|
|
206
|
-
!captions.captionTracks.some((track) => { var _a; return track.languageCode === ((_a = this.config) === null || _a ===
|
|
207
|
-
throw new YoutubeTranscriptNotAvailableLanguageError((
|
|
206
|
+
if (((_j = this.config) === null || _j === void 0 ? void 0 : _j.lang) &&
|
|
207
|
+
!captions.captionTracks.some((track) => { var _a; return track.languageCode === ((_a = this.config) === null || _a === void 0 ? void 0 : _a.lang); })) {
|
|
208
|
+
throw new YoutubeTranscriptNotAvailableLanguageError((_k = this.config) === null || _k === void 0 ? void 0 : _k.lang, captions.captionTracks.map((track) => track.languageCode), identifier);
|
|
208
209
|
}
|
|
209
|
-
const
|
|
210
|
-
? captions.captionTracks.find((track) => { var _a; return track.languageCode === ((_a = this.config) === null || _a ===
|
|
210
|
+
const captionURL = (((_l = this.config) === null || _l === void 0 ? void 0 : _l.lang)
|
|
211
|
+
? captions.captionTracks.find((track) => { var _a; return track.languageCode === ((_a = this.config) === null || _a === void 0 ? void 0 : _a.lang); })
|
|
211
212
|
: captions.captionTracks[0]).baseUrl;
|
|
213
|
+
const transcriptURL = ((_m = this.config) === null || _m === void 0 ? void 0 : _m.disableHttps)
|
|
214
|
+
? captionURL.replace('https://', 'http://')
|
|
215
|
+
: captionURL;
|
|
212
216
|
// Fetch the transcript
|
|
213
217
|
const transcriptResponse = yield transcriptFetch({
|
|
214
218
|
url: transcriptURL,
|
|
215
|
-
lang: (
|
|
219
|
+
lang: (_o = this.config) === null || _o === void 0 ? void 0 : _o.lang,
|
|
216
220
|
userAgent,
|
|
217
221
|
});
|
|
218
222
|
if (!transcriptResponse.ok) {
|
|
@@ -226,11 +230,11 @@ class YoutubeTranscript {
|
|
|
226
230
|
text: result[3],
|
|
227
231
|
duration: parseFloat(result[2]),
|
|
228
232
|
offset: parseFloat(result[1]),
|
|
229
|
-
lang: (_b = (_a = this.config) === null || _a ===
|
|
233
|
+
lang: (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.lang) !== null && _b !== void 0 ? _b : captions.captionTracks[0].languageCode,
|
|
230
234
|
});
|
|
231
235
|
});
|
|
232
236
|
// Store in cache if a strategy is provided
|
|
233
|
-
if ((
|
|
237
|
+
if ((_p = this.config) === null || _p === void 0 ? void 0 : _p.cache) {
|
|
234
238
|
yield this.config.cache.set(cacheKey, JSON.stringify(transcript), this.config.cacheTTL);
|
|
235
239
|
}
|
|
236
240
|
return transcript;
|
|
@@ -238,7 +242,7 @@ class YoutubeTranscript {
|
|
|
238
242
|
}
|
|
239
243
|
// Add static method for new usage pattern
|
|
240
244
|
static fetchTranscript(videoId, config) {
|
|
241
|
-
return __awaiter(this,
|
|
245
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
242
246
|
const instance = new YoutubeTranscript(config);
|
|
243
247
|
return instance.fetchTranscript(videoId);
|
|
244
248
|
});
|
|
@@ -247,4 +251,4 @@ class YoutubeTranscript {
|
|
|
247
251
|
// Export the static method directly for convenience
|
|
248
252
|
const fetchTranscript = YoutubeTranscript.fetchTranscript;
|
|
249
253
|
|
|
250
|
-
export { FsCache, InMemoryCache, YoutubeTranscript, fetchTranscript };
|
|
254
|
+
export { FsCache, InMemoryCache, YoutubeTranscript, YoutubeTranscriptDisabledError, YoutubeTranscriptInvalidVideoIdError, YoutubeTranscriptNotAvailableError, YoutubeTranscriptNotAvailableLanguageError, YoutubeTranscriptTooManyRequestError, YoutubeTranscriptVideoUnavailableError, fetchTranscript };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "youtube-transcript-plus",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Fetch transcript from a YouTube video",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/youtube-transcript-plus.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"format": "prettier --write 'src/**/*.ts'",
|
|
12
12
|
"test": "jest",
|
|
13
13
|
"test:watch": "jest --watch",
|
|
14
|
-
"prepare": "husky
|
|
14
|
+
"prepare": "husky"
|
|
15
15
|
},
|
|
16
16
|
"author": "ericmmartin",
|
|
17
17
|
"keywords": [
|
|
@@ -33,14 +33,14 @@
|
|
|
33
33
|
"https-proxy-agent": "^7.0.6",
|
|
34
34
|
"husky": "^9.1.7",
|
|
35
35
|
"jest": "^29.7.0",
|
|
36
|
-
"lint-staged": "^15.
|
|
37
|
-
"prettier": "^3.
|
|
38
|
-
"rollup": "^4.
|
|
36
|
+
"lint-staged": "^15.5.0",
|
|
37
|
+
"prettier": "^3.5.3",
|
|
38
|
+
"rollup": "^4.37.0",
|
|
39
39
|
"rollup-plugin-typescript": "^1.0.1",
|
|
40
40
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
41
|
-
"ts-jest": "^29.
|
|
41
|
+
"ts-jest": "^29.3.0",
|
|
42
42
|
"tslib": "^2.8.1",
|
|
43
|
-
"typescript": "^5.
|
|
43
|
+
"typescript": "^5.8.2"
|
|
44
44
|
},
|
|
45
45
|
"files": [
|
|
46
46
|
"dist/*"
|