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 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
@@ -9,4 +9,5 @@ export declare class YoutubeTranscript {
9
9
  }
10
10
  export type { CacheStrategy } from './types';
11
11
  export { InMemoryCache, FsCache } from './cache';
12
+ export * from './errors';
12
13
  export declare const fetchTranscript: typeof YoutubeTranscript.fetchTranscript;
package/dist/types.d.ts CHANGED
@@ -7,6 +7,7 @@ export interface TranscriptConfig {
7
7
  userAgent?: string;
8
8
  cache?: CacheStrategy;
9
9
  cacheTTL?: number;
10
+ disableHttps?: boolean;
10
11
  videoFetch?: (params: {
11
12
  url: string;
12
13
  lang?: string;
@@ -85,7 +85,7 @@ function retrieveVideoId(videoId) {
85
85
  throw new YoutubeTranscriptInvalidVideoIdError();
86
86
  }
87
87
  function defaultFetch(_a) {
88
- return __awaiter(this, arguments, undefined, function* ({ url, lang, userAgent, }) {
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, undefined, undefined, function* () {
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, undefined, undefined, function* () {
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 !== undefined ? ttl : this.defaultTTL);
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, undefined, undefined, function* () {
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, undefined, undefined, function* () {
143
- const expires = Date.now() + (ttl !== null && ttl !== undefined ? ttl : this.defaultTTL);
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, undefined, undefined, function* () {
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 === undefined ? undefined : _a.userAgent) || DEFAULT_USER_AGENT;
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 === undefined ? undefined : _b.videoFetch) || defaultFetch;
160
- const transcriptFetch = ((_c = this.config) === null || _c === undefined ? undefined : _c.transcriptFetch) || defaultFetch;
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 === undefined ? undefined : _d.lang) || 'default'}`;
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 === undefined ? undefined : _e.cache) {
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: `https://www.youtube.com/watch?v=${identifier}`,
173
- lang: (_f = this.config) === null || _f === undefined ? undefined : _f.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 = (_g = (() => {
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 || _g === undefined ? undefined : _g['playerCaptionsTracklistRenderer'];
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 (((_h = this.config) === null || _h === undefined ? undefined : _h.lang) &&
206
- !captions.captionTracks.some((track) => { var _a; return track.languageCode === ((_a = this.config) === null || _a === undefined ? undefined : _a.lang); })) {
207
- throw new YoutubeTranscriptNotAvailableLanguageError((_j = this.config) === null || _j === undefined ? undefined : _j.lang, captions.captionTracks.map((track) => track.languageCode), identifier);
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 transcriptURL = (((_k = this.config) === null || _k === undefined ? undefined : _k.lang)
210
- ? captions.captionTracks.find((track) => { var _a; return track.languageCode === ((_a = this.config) === null || _a === undefined ? undefined : _a.lang); })
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: (_l = this.config) === null || _l === undefined ? undefined : _l.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 === undefined ? undefined : _a.lang) !== null && _b !== undefined ? _b : captions.captionTracks[0].languageCode,
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 ((_m = this.config) === null || _m === undefined ? undefined : _m.cache) {
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, undefined, undefined, function* () {
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.2",
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 install"
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.3.0",
37
- "prettier": "^3.4.2",
38
- "rollup": "^4.30.1",
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.2.5",
41
+ "ts-jest": "^29.3.0",
42
42
  "tslib": "^2.8.1",
43
- "typescript": "^5.7.3"
43
+ "typescript": "^5.8.2"
44
44
  },
45
45
  "files": [
46
46
  "dist/*"