extract-youtube 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 +61 -20
- package/dist/archiver-web.es-3EQgnnex.js +2 -0
- package/dist/archiver-web.es-3EQgnnex.js.map +1 -0
- package/dist/archiver-web.es-CO0IfW41.mjs +2 -0
- package/dist/archiver-web.es-CO0IfW41.mjs.map +1 -0
- package/dist/archiver-web.es-eh2cNrlm.js +3140 -0
- package/dist/archiver-web.es-eh2cNrlm.js.map +1 -0
- package/dist/cli.js +455 -56
- package/dist/cli.js.map +1 -1
- package/dist/index-CLlAnStL-BKslXZFs.mjs +2 -0
- package/dist/index-CLlAnStL-BKslXZFs.mjs.map +1 -0
- package/dist/index-CLlAnStL-BNm8mEFS.js +6524 -0
- package/dist/index-CLlAnStL-BNm8mEFS.js.map +1 -0
- package/dist/index-CLlAnStL-DDV_Pgc5.js +2 -0
- package/dist/index-CLlAnStL-DDV_Pgc5.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/rolldown-runtime-Bd6kNlEP.js +71 -0
- package/jest.config.js +0 -0
- package/package.json +12 -9
- package/src/cli.ts +11 -2
- package/src/{errors.ts → errors/index.ts} +1 -1
- package/src/fetchers/transcript-list-fetcher.ts +0 -0
- package/src/fetchers/youtube-data-extractor.ts +0 -0
- package/src/{formatters.ts → formatters/index.ts} +82 -3
- package/src/http/fetch-http-client.ts +9 -9
- package/src/index.ts +4 -0
- package/src/models/fetched-transcript.ts +0 -0
- package/src/models/index.ts +0 -0
- package/src/models/transcript-list.ts +0 -0
- package/src/models/transcript.ts +0 -0
- package/src/parsers/transcript-parser.ts +4 -0
- package/src/{proxies.ts → proxies/index.ts} +1 -1
- package/src/{types.ts → types/index.ts} +0 -2
- package/src/utils/http-error-handler.ts +0 -1
- package/src/utils/transcript-utils.ts +107 -0
- package/src/youtube-transcript-api.ts +0 -0
- package/{__tests__ → test}/api.test.ts +0 -0
- package/{__tests__/basic-usage.ts → test/basic.test.ts} +0 -0
- package/{__tests__ → test}/formatters.test.ts +0 -0
- package/{__tests__ → test}/integration.test.ts +0 -0
- package/tsconfig.json +5 -5
- package/tsconfig.test.json +10 -0
- package/vite.config.ts +8 -3
- package/CHANGELOG.md +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,45 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
|
|
4
|
-
var __create = Object.create;
|
|
5
|
-
var __defProp = Object.defineProperty;
|
|
6
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
-
var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
11
|
-
var __exportAll = (all, no_symbols) => {
|
|
12
|
-
let target = {};
|
|
13
|
-
for (var name in all) __defProp(target, name, {
|
|
14
|
-
get: all[name],
|
|
15
|
-
enumerable: true
|
|
16
|
-
});
|
|
17
|
-
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
18
|
-
return target;
|
|
19
|
-
};
|
|
20
|
-
var __copyProps = (to, from, except, desc) => {
|
|
21
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
22
|
-
key = keys[i];
|
|
23
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
24
|
-
get: ((k) => from[k]).bind(null, key),
|
|
25
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
return to;
|
|
29
|
-
};
|
|
30
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
31
|
-
value: mod,
|
|
32
|
-
enumerable: true
|
|
33
|
-
}) : target, mod));
|
|
34
|
-
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
35
|
-
//#endregion
|
|
3
|
+
const require_rolldown_runtime = require("./rolldown-runtime-Bd6kNlEP.js");
|
|
36
4
|
let html_entities = require("html-entities");
|
|
37
5
|
let fast_xml_parser = require("fast-xml-parser");
|
|
38
|
-
let node_fetch = require("node-fetch");
|
|
39
|
-
node_fetch = __toESM(node_fetch);
|
|
40
6
|
let https_proxy_agent = require("https-proxy-agent");
|
|
41
|
-
//#region src/errors.ts
|
|
42
|
-
var _CouldNotRetrieveTranscript
|
|
7
|
+
//#region src/errors/index.ts
|
|
8
|
+
var _CouldNotRetrieveTranscript;
|
|
9
|
+
var _RequestBlocked;
|
|
43
10
|
var YOUTUBE_WATCH_URL$1 = "https://www.youtube.com/watch?v={video_id}";
|
|
44
11
|
/**
|
|
45
12
|
* Base exception class for all YouTube Transcript API errors.
|
|
@@ -411,6 +378,7 @@ var TranscriptParser = class TranscriptParser {
|
|
|
411
378
|
* @returns {string} The cleaned text
|
|
412
379
|
*/
|
|
413
380
|
cleanTranscriptText(text) {
|
|
381
|
+
if (typeof text !== "string") text = String(text || "");
|
|
414
382
|
return (0, html_entities.decode)(text).replace(this.htmlRemovalRegex, "");
|
|
415
383
|
}
|
|
416
384
|
};
|
|
@@ -430,6 +398,9 @@ _TranscriptParser.FORMATTING_TAGS = [
|
|
|
430
398
|
//#endregion
|
|
431
399
|
//#region src/utils/http-error-handler.ts
|
|
432
400
|
/**
|
|
401
|
+
* @fileoverview HTTP error handling utilities for YouTube API requests
|
|
402
|
+
*/
|
|
403
|
+
/**
|
|
433
404
|
* Checks an HTTP response and throws appropriate errors if the request failed.
|
|
434
405
|
*
|
|
435
406
|
* @param {Response} response - The HTTP response to check
|
|
@@ -740,7 +711,7 @@ var TranscriptList = class TranscriptList {
|
|
|
740
711
|
}
|
|
741
712
|
};
|
|
742
713
|
//#endregion
|
|
743
|
-
//#region src/types.ts
|
|
714
|
+
//#region src/types/index.ts
|
|
744
715
|
/**
|
|
745
716
|
* Playability status enum values
|
|
746
717
|
*/
|
|
@@ -1040,12 +1011,375 @@ var TranscriptListFetcher = class {
|
|
|
1040
1011
|
}
|
|
1041
1012
|
};
|
|
1042
1013
|
//#endregion
|
|
1014
|
+
//#region ../../node_modules/.bun/grab-url@1.6.22/node_modules/grab-url/dist/log.es.js
|
|
1015
|
+
var t = {
|
|
1016
|
+
reset: [0, "000000"],
|
|
1017
|
+
black: [30, "1f2937"],
|
|
1018
|
+
red: [31, "dc2626"],
|
|
1019
|
+
green: [32, "2d6a4f"],
|
|
1020
|
+
yellow: [33, "92400e"],
|
|
1021
|
+
blue: [34, "1a56db"],
|
|
1022
|
+
magenta: [35, "6d28d9"],
|
|
1023
|
+
cyan: [36, "0e7490"],
|
|
1024
|
+
white: [37, "374151"],
|
|
1025
|
+
gray: [90, "6b7280"],
|
|
1026
|
+
brightRed: [91, "ef4444"],
|
|
1027
|
+
brightGreen: [92, "059669"],
|
|
1028
|
+
brightYellow: [93, "d97706"],
|
|
1029
|
+
brightBlue: [94, "3b82f6"],
|
|
1030
|
+
brightMagenta: [95, "8b5cf6"],
|
|
1031
|
+
brightCyan: [96, "06b6d4"],
|
|
1032
|
+
brightWhite: [97, "f9fafb"],
|
|
1033
|
+
bgBlack: [40, "111827"],
|
|
1034
|
+
bgRed: [41, "fca5a5"],
|
|
1035
|
+
bgGreen: [42, "a7f3d0"],
|
|
1036
|
+
bgYellow: [43, "fde68a"],
|
|
1037
|
+
bgBlue: [44, "bfdbfe"],
|
|
1038
|
+
bgMagenta: [45, "ddd6fe"],
|
|
1039
|
+
bgCyan: [46, "a5f3fc"],
|
|
1040
|
+
bgWhite: [47, "f9fafb"],
|
|
1041
|
+
bgGray: [100, "d1d5db"],
|
|
1042
|
+
bgBrightRed: [101, "fee2e2"],
|
|
1043
|
+
bgBrightGreen: [102, "d1fae5"],
|
|
1044
|
+
bgBrightYellow: [103, "fef3c7"],
|
|
1045
|
+
bgBrightBlue: [104, "dbeafe"],
|
|
1046
|
+
bgBrightMagenta: [105, "ede9fe"],
|
|
1047
|
+
bgBrightCyan: [106, "cffafe"],
|
|
1048
|
+
bgBrightWhite: [107, "ffffff"]
|
|
1049
|
+
};
|
|
1050
|
+
function r$1(e = "ansi") {
|
|
1051
|
+
const r = {};
|
|
1052
|
+
for (const [n, [o, i]] of Object.entries(t)) r[n] = "html" === e ? "reset" === n ? "</span>" : `<span style="color:#${i}">` : "\x1B[" + o + "m";
|
|
1053
|
+
return r;
|
|
1054
|
+
}
|
|
1055
|
+
function n$1(e, t = "ansi") {
|
|
1056
|
+
const n = r$1(t);
|
|
1057
|
+
return "string" == typeof e ? n.yellow : "number" == typeof e ? n.cyan : "boolean" == typeof e ? n.magenta : "function" == typeof e ? n.red : null === e ? n.gray : Array.isArray(e) ? n.blue : "object" == typeof e ? n.green : n.white;
|
|
1058
|
+
}
|
|
1059
|
+
function o$1(e) {
|
|
1060
|
+
return "string" == typeof e ? "\"\"" : "number" == typeof e ? "number" : "boolean" == typeof e ? "bool" : "function" == typeof e ? "function" : null === e ? "null" : Array.isArray(e) ? e.length ? "[" + o$1(e[0]) + "]" : "[]" : "object" == typeof e ? "{...}" : typeof e;
|
|
1061
|
+
}
|
|
1062
|
+
function i$2(e, t = 0, l = "ansi") {
|
|
1063
|
+
const g = r$1(l), a = "html" === l, s = " ".repeat(t);
|
|
1064
|
+
if ("object" != typeof e || null === e) return n$1(e, l) + o$1(e) + g.reset;
|
|
1065
|
+
if (Array.isArray(e)) {
|
|
1066
|
+
if (a) {
|
|
1067
|
+
let r = [];
|
|
1068
|
+
e.length && (r = e.every((t) => typeof t == typeof e[0]) ? [i$2(e[0], t + 1, l)] : e.map((e) => i$2(e, t + 1, l)));
|
|
1069
|
+
return `<details open><summary style="cursor:pointer;display:inline">${`${g.blue}[${g.reset} ${e.length} × ${o$1(e[0] ?? void 0)} ${g.blue}]${g.reset}`}</summary>${r.map((e) => `<div style="margin-left:1.5em">${e}</div>`).join("")}</details>`;
|
|
1070
|
+
}
|
|
1071
|
+
let r = g.blue + "[" + g.reset;
|
|
1072
|
+
return e.length && (r += "\n"), e.every((t) => typeof t == typeof e[0]) ? r += s + " " + i$2(e[0], t + 1, l) + ",\n" : e.forEach((n, o) => {
|
|
1073
|
+
r += s + " " + i$2(n, t + 1, l), o < e.length - 1 && (r += ","), r += "\n";
|
|
1074
|
+
}), r += s + g.blue + "]" + g.reset, r;
|
|
1075
|
+
}
|
|
1076
|
+
const b = Object.keys(e);
|
|
1077
|
+
if (a) {
|
|
1078
|
+
const r = b.slice(0, 4).join(", ") + (b.length > 4 ? "…" : "");
|
|
1079
|
+
return `<details open><summary style="cursor:pointer">${`${g.green}{${g.reset} ${r} ${g.green}}${g.reset}`}</summary>${b.map((r) => {
|
|
1080
|
+
const a = e[r], s = n$1(a, l);
|
|
1081
|
+
return "object" == typeof a && null !== a ? `<div style="margin-left:1.5em">${s}${r}${g.reset}: ${i$2(a, t + 1, l)}</div>` : `<div style="margin-left:1.5em">${s}${r}: ${o$1(a)}${g.reset}</div>`;
|
|
1082
|
+
}).join("")}</details>`;
|
|
1083
|
+
}
|
|
1084
|
+
let f = g.green + "{" + g.reset;
|
|
1085
|
+
return b.length && (f += "\n"), b.forEach((r, a) => {
|
|
1086
|
+
const y = e[r], c = n$1(y, l);
|
|
1087
|
+
f += s + " ", f += "object" == typeof y && null !== y ? c + r + g.reset + ": " + i$2(y, t + 1, l) : c + r + ": " + o$1(y) + g.reset, a < b.length - 1 && (f += ","), f += "\n";
|
|
1088
|
+
}), f += s + g.green + "}" + g.reset, f;
|
|
1089
|
+
}
|
|
1090
|
+
function l$2(e = "", t = {}) {
|
|
1091
|
+
let { color: n, style: o = "color:rgb(54, 165, 220); font-size: 10pt;", hideInProduction: l, startSpinner: g = !1, stopSpinner: a = !1 } = t;
|
|
1092
|
+
const s = r$1();
|
|
1093
|
+
void 0 === l && (l = "undefined" != typeof window && window?.location.hostname.includes("localhost")), "object" == typeof e && (e = i$2(e) + "\n\n" + JSON.stringify(e, null, 2)), Array.isArray(n) && 1 == n.length && (n = n[0]), n && "undefined" != typeof process && ("string" == typeof e && e.includes("%c") && Array.isArray(n) ? e = e.replace(/%c/g, (e, t) => s[n[t]] || "") : n && "string" == typeof n && (e = (s[n] || "") + e + s.reset));
|
|
1094
|
+
var b = 0;
|
|
1095
|
+
return g ? globalThis.interval = setInterval(() => {
|
|
1096
|
+
process.stdout.write((Array.isArray(n) ? s[n[0]] : s[n] || "") + "\r" + "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏".split("")[b = ++b % 10] + " " + e + s.reset);
|
|
1097
|
+
}, 50) : a ? (clearInterval(globalThis.interval), process.stdout.write("\r" + (e || " ") + " ".repeat("string" == typeof e ? e.length + 20 : 40) + "\n")) : "string" == typeof o ? (1 == o.split(" ").length || n ? o = `color: ${n || o}; font-size: 11pt;` : o.match(/^#[0-9a-fA-F]{6}$/) && (o = `color: ${o}; font-size: 11pt;`), l ? console.debug((o ? "%c" : "") + (e || ""), o) : console.log((o ? "%c" : "") + (e || ""), o)) : "object" == typeof o && console.log(e, ...o), !0;
|
|
1098
|
+
}
|
|
1099
|
+
//#endregion
|
|
1100
|
+
//#region ../../node_modules/.bun/grab-url@1.6.22/node_modules/grab-url/dist/core-BX1uvK6L.js
|
|
1101
|
+
var n = async (e, t) => {
|
|
1102
|
+
let n;
|
|
1103
|
+
return async function(...o) {
|
|
1104
|
+
clearTimeout(n), n = setTimeout(async () => {
|
|
1105
|
+
clearTimeout(n), await e(...o);
|
|
1106
|
+
}, t);
|
|
1107
|
+
};
|
|
1108
|
+
};
|
|
1109
|
+
var o = (e) => new Promise((t) => setTimeout(t, 1e3 * e || 0));
|
|
1110
|
+
var r = (e, t) => {
|
|
1111
|
+
let n = (e) => t?.startsWith(e) || !1, o = e, r = t;
|
|
1112
|
+
return t?.startsWith("http:") || t?.startsWith("https:") ? o = "" : n("/") || o.endsWith("/") ? n("/") && o.endsWith("/") && (r = t.slice(1)) : r = "/" + t, {
|
|
1113
|
+
baseURL: o,
|
|
1114
|
+
path: r
|
|
1115
|
+
};
|
|
1116
|
+
};
|
|
1117
|
+
function s(e) {
|
|
1118
|
+
if ("undefined" == typeof document) return;
|
|
1119
|
+
let t, n = document.getElementById("alert-overlay");
|
|
1120
|
+
if (!n) {
|
|
1121
|
+
n = document.body.appendChild(document.createElement("div")), n.id = "alert-overlay", n.setAttribute("style", "position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center"), n.innerHTML = "<div id=\"alert-box\" style=\"background:#fff;padding:1.5em 2em;border-radius:8px;box-shadow:0 2px 16px #0003;min-width:320px;max-width:90vw;max-height:80vh;position:relative;display:flex;flex-direction:column;\">\n <button id=\"close-alert\" style=\"position:absolute;top:12px;right:20px;font-size:1.5em;background:none;border:none;cursor:pointer;color:black;\">×</button>\n <div id=\"alert-list\" style=\"overflow:auto;flex:1;font-family:monospace;font-size:13px;\"></div>\n </div>", n.addEventListener("click", (e) => e.target == n && n.remove());
|
|
1122
|
+
const e = document.getElementById("close-alert");
|
|
1123
|
+
e && (e.onclick = () => n.remove());
|
|
1124
|
+
}
|
|
1125
|
+
t = document.getElementById("alert-list"), t.innerHTML += `<div style="border-bottom:1px solid #e5e7eb;margin:0.5em 0;padding-bottom:0.5em">${e}</div>`;
|
|
1126
|
+
}
|
|
1127
|
+
function i$1(e) {
|
|
1128
|
+
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1129
|
+
}
|
|
1130
|
+
function a() {
|
|
1131
|
+
"undefined" != typeof document && document.addEventListener("keydown", (t) => {
|
|
1132
|
+
const n = window.grab;
|
|
1133
|
+
if (n && n.log && "i" === t.key && t.ctrlKey && t.altKey) {
|
|
1134
|
+
let t = "";
|
|
1135
|
+
for (const o of n.log) {
|
|
1136
|
+
const n = new Date(o.lastFetchTime).toLocaleString(), r = i$2(o.request, 0, "html"), s = i$2(o.response, 0, "html"), a = i$1(JSON.stringify(o.response, null, 2));
|
|
1137
|
+
t += `\n <details open style="margin-bottom:0.75em">\n <summary style="cursor:pointer;font-weight:bold;padding:4px 0;list-style:none;display:flex;justify-content:space-between">\n <span style="color:#1a56db">${i$1(o.path)}</span>\n <span style="color:#6b7280;font-weight:normal;margin-left:1em">${n}</span>\n </summary>\n <div style="padding-left:1em;margin-top:0.5em">\n <details style="margin-bottom:0.4em">\n <summary style="cursor:pointer;color:#6b7280;font-size:0.9em">Request</summary>\n <div style="padding:0.4em 0 0 1em">${r}</div>\n </details>\n <details open style="margin-bottom:0.4em">\n <summary style="cursor:pointer;color:#6b7280;font-size:0.9em">Response (structure)</summary>\n <div style="padding:0.4em 0 0 1em">${s}</div>\n </details>\n <details style="margin-bottom:0.4em">\n <summary style="cursor:pointer;color:#6b7280;font-size:0.9em">Response (data)</summary>\n <pre style="margin:0.4em 0 0 1em;padding:0.5em;background:#f9fafb;border:1px solid #e5e7eb;border-radius:4px;overflow:auto;max-height:300px;font-size:12px">${a}</pre>\n </details>\n </div>\n </details>`;
|
|
1138
|
+
}
|
|
1139
|
+
s(t || "<em>No requests logged yet.</em>");
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
function l$1(o) {
|
|
1144
|
+
return async function i(a, l) {
|
|
1145
|
+
const c = function(e) {
|
|
1146
|
+
return {
|
|
1147
|
+
..."undefined" != typeof window ? window?.grab?.defaults : globalThis?.grab?.defaults || {},
|
|
1148
|
+
...e
|
|
1149
|
+
};
|
|
1150
|
+
}(l);
|
|
1151
|
+
let { headers: d, response: u, method: f = c.post ? "POST" : c.put ? "PUT" : c.patch ? "PATCH" : "GET", cache: p, timeout: m = 30, baseURL: y = "undefined" != typeof process && process.env.SERVER_API_URL || "/api/", cancelOngoingIfNew: g, cancelNewIfOngoing: b, rateLimit: w, debug: h, infiniteScroll: v, logger: T = l$2, onRequest: x, onResponse: L, onError: E, onStream: A, unzip: S, dom: O, body: R, post: P, put: k, patch: $, ...j } = c;
|
|
1152
|
+
const q = r(y, a);
|
|
1153
|
+
y = q.baseURL, a = q.path;
|
|
1154
|
+
const F = function(e) {
|
|
1155
|
+
const t = "function" == typeof e ? e : null;
|
|
1156
|
+
return {
|
|
1157
|
+
response: !e || t ? {} : e,
|
|
1158
|
+
resFunction: t
|
|
1159
|
+
};
|
|
1160
|
+
}(u);
|
|
1161
|
+
let N = F.response, D = F.resFunction;
|
|
1162
|
+
const I = ("undefined" != typeof window ? window.grab : globalThis.grab)?.log || [];
|
|
1163
|
+
D ? N = D({
|
|
1164
|
+
...N,
|
|
1165
|
+
isLoading: !0
|
|
1166
|
+
}) : "object" == typeof N && (N.isLoading = !0);
|
|
1167
|
+
try {
|
|
1168
|
+
const r = await async function(e, t, o, r) {
|
|
1169
|
+
const { debounce: s = 0, repeat: i = 0, repeatEvery: a = null, setDefaults: l = !1 } = o;
|
|
1170
|
+
if (s > 0) return await (await n(async () => {
|
|
1171
|
+
await r(e, {
|
|
1172
|
+
...t,
|
|
1173
|
+
debounce: 0
|
|
1174
|
+
});
|
|
1175
|
+
}, 1e3 * s))(), o.response || {};
|
|
1176
|
+
if (i > 1) {
|
|
1177
|
+
for (let n = 0; n < i; n++) await r(e, {
|
|
1178
|
+
...t,
|
|
1179
|
+
repeat: 0
|
|
1180
|
+
});
|
|
1181
|
+
return o.response || {};
|
|
1182
|
+
}
|
|
1183
|
+
if (a) return setInterval(async () => {
|
|
1184
|
+
await r(e, {
|
|
1185
|
+
...t,
|
|
1186
|
+
repeat: 0,
|
|
1187
|
+
repeatEvery: null
|
|
1188
|
+
});
|
|
1189
|
+
}, 1e3 * a), o.response || {};
|
|
1190
|
+
if (l) {
|
|
1191
|
+
const e = "undefined" != typeof window ? window.grab : globalThis.grab;
|
|
1192
|
+
return e && (e.defaults = {
|
|
1193
|
+
...t,
|
|
1194
|
+
setDefaults: void 0
|
|
1195
|
+
}), o.response || {};
|
|
1196
|
+
}
|
|
1197
|
+
return null;
|
|
1198
|
+
}(a, l || {}, c, i);
|
|
1199
|
+
if (r) return r;
|
|
1200
|
+
(function(e, t, n, o) {
|
|
1201
|
+
if ("undefined" == typeof window) return;
|
|
1202
|
+
const { regrabOnStale: r, regrabOnFocus: s, regrabOnNetwork: i, cache: a, cacheForTime: l = 60 } = n, c = async () => await o(e, {
|
|
1203
|
+
...t,
|
|
1204
|
+
cache: !1
|
|
1205
|
+
});
|
|
1206
|
+
r && a && setTimeout(c, 1e3 * l), i && window.addEventListener("online", c), s && (window.addEventListener("focus", c), document.addEventListener("visibilitychange", async () => {
|
|
1207
|
+
"visible" === document.visibilityState && await c();
|
|
1208
|
+
}));
|
|
1209
|
+
})(a, l || {}, c, i);
|
|
1210
|
+
let { params: s, priorRequest: u, response: E, paramsAsText: P } = function(e, t, n, o, r, s) {
|
|
1211
|
+
const { cache: i, cacheForTime: a, infiniteScroll: l } = n, [c, d] = l || [], u = JSON.stringify(c ? {
|
|
1212
|
+
...t,
|
|
1213
|
+
[c]: void 0
|
|
1214
|
+
} : t);
|
|
1215
|
+
let f = s.find((t) => t.request === u && t.path === e);
|
|
1216
|
+
if (c) {
|
|
1217
|
+
let e = (f?.currentPage || 0) + 1 || t?.[c] || 1;
|
|
1218
|
+
f ? f.currentPage = e : (o[d] = [], e = 1), t = {
|
|
1219
|
+
...t,
|
|
1220
|
+
[c]: e
|
|
1221
|
+
};
|
|
1222
|
+
} else {
|
|
1223
|
+
for (let e of Object.keys(o)) o[e] = void 0;
|
|
1224
|
+
if (i && f?.response && (!a || f.lastFetchTime > Date.now() - 1e3 * a)) {
|
|
1225
|
+
for (let e of Object.keys(f.response)) o[e] = f.response[e];
|
|
1226
|
+
r && (o = r(o));
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
return {
|
|
1230
|
+
params: t,
|
|
1231
|
+
priorRequest: f,
|
|
1232
|
+
response: o,
|
|
1233
|
+
paramsAsText: u
|
|
1234
|
+
};
|
|
1235
|
+
}(a, j, c, N, D, I);
|
|
1236
|
+
if (j = s, N = E, function(e, n, o, r, s) {
|
|
1237
|
+
if ("undefined" == typeof window || !o?.length) return;
|
|
1238
|
+
const [i, , a] = o;
|
|
1239
|
+
if (void 0 === a) return;
|
|
1240
|
+
let l = "string" == typeof a ? document.querySelector(a) : a;
|
|
1241
|
+
l ? (window.scrollListener && "function" == typeof l.removeEventListener && l.removeEventListener("scroll", window.scrollListener), window.scrollListener = (t) => {
|
|
1242
|
+
const o = t.target;
|
|
1243
|
+
localStorage.setItem("scroll", JSON.stringify([
|
|
1244
|
+
o.scrollTop,
|
|
1245
|
+
o.scrollLeft,
|
|
1246
|
+
a
|
|
1247
|
+
])), o.scrollHeight - o.scrollTop <= o.clientHeight + 200 && s(e, {
|
|
1248
|
+
...n,
|
|
1249
|
+
cache: !1,
|
|
1250
|
+
[i]: (r?.currentPage || 0) + 1
|
|
1251
|
+
});
|
|
1252
|
+
}, l.addEventListener("scroll", window.scrollListener)) : l$2("paginateDOM not found", { color: "red" });
|
|
1253
|
+
}(a, l, v, u, i), w > 0 && u?.lastFetchTime > Date.now() - 1e3 * w) throw new Error(`Fetch rate limit exceeded for ${a}. Wait ${w}s between requests.`);
|
|
1254
|
+
if (u?.controller) {
|
|
1255
|
+
if (g) u.controller.abort();
|
|
1256
|
+
else if (b) return { isLoading: !0 };
|
|
1257
|
+
}
|
|
1258
|
+
const k = new AbortController();
|
|
1259
|
+
let $ = k.signal;
|
|
1260
|
+
g || "function" != typeof AbortSignal.timeout || ($ = AbortSignal.timeout(1e3 * m)), I.unshift({
|
|
1261
|
+
path: a,
|
|
1262
|
+
request: P,
|
|
1263
|
+
lastFetchTime: Date.now(),
|
|
1264
|
+
controller: k
|
|
1265
|
+
});
|
|
1266
|
+
let { fetchParams: q, paramsGETRequest: F } = function(e, t, n, o, r, s) {
|
|
1267
|
+
const i = [
|
|
1268
|
+
"POST",
|
|
1269
|
+
"PUT",
|
|
1270
|
+
"PATCH"
|
|
1271
|
+
].includes(e), a = {
|
|
1272
|
+
method: e,
|
|
1273
|
+
headers: {
|
|
1274
|
+
"Content-Type": "application/json",
|
|
1275
|
+
Accept: "application/json",
|
|
1276
|
+
...t
|
|
1277
|
+
},
|
|
1278
|
+
body: n || (i ? JSON.stringify(o) : null),
|
|
1279
|
+
redirect: "follow",
|
|
1280
|
+
cache: r ? "force-cache" : "no-store",
|
|
1281
|
+
signal: s
|
|
1282
|
+
};
|
|
1283
|
+
let l = "";
|
|
1284
|
+
return i || (l = (Object.keys(o).length ? "?" : "") + new URLSearchParams(o).toString()), {
|
|
1285
|
+
fetchParams: a,
|
|
1286
|
+
paramsGETRequest: l
|
|
1287
|
+
};
|
|
1288
|
+
}(f, d, R, j, !!p, $);
|
|
1289
|
+
if ("function" == typeof x) {
|
|
1290
|
+
const e = x(a, N, j, q);
|
|
1291
|
+
Array.isArray(e) && ([a, N, j, q] = e);
|
|
1292
|
+
}
|
|
1293
|
+
const z = /* @__PURE__ */ new Date(), U = await o(y, a, F, q, j, A, S, O);
|
|
1294
|
+
if (D ? N = D({
|
|
1295
|
+
...N,
|
|
1296
|
+
isLoading: void 0
|
|
1297
|
+
}) : "object" == typeof N && delete N.isLoading, "function" == typeof L) {
|
|
1298
|
+
const e = L(a, N, j, q);
|
|
1299
|
+
Array.isArray(e) && ([a, N, j, q] = e);
|
|
1300
|
+
}
|
|
1301
|
+
const H = ((Number(/* @__PURE__ */ new Date()) - Number(z)) / 1e3).toFixed(1);
|
|
1302
|
+
h && T(`Path:${y + a + F}\n${JSON.stringify(l, null, 2)}\nTime: ${H}s\nResponse: ${i$2(U)}`);
|
|
1303
|
+
const [, W] = v || [];
|
|
1304
|
+
return N = function(e, t, n, o) {
|
|
1305
|
+
if ("object" == typeof e && null !== e) {
|
|
1306
|
+
for (let n of Object.keys(e)) t[n] = o === n && Array.isArray(t[n]) ? [...t[n], ...e[n]] : e[n];
|
|
1307
|
+
t.data = e;
|
|
1308
|
+
} else n ? t = n({
|
|
1309
|
+
data: e,
|
|
1310
|
+
...e
|
|
1311
|
+
}) : "object" == typeof t && (t.data = e);
|
|
1312
|
+
return t;
|
|
1313
|
+
}(U, N, D, W), I[0] && (I[0].response = N), D && (N = D(N)), N;
|
|
1314
|
+
} catch (U) {
|
|
1315
|
+
if ("function" == typeof E && E(U.message, y + a, j), c.retryAttempts && c.retryAttempts > 0) return await i(a, {
|
|
1316
|
+
...l,
|
|
1317
|
+
retryAttempts: --c.retryAttempts
|
|
1318
|
+
});
|
|
1319
|
+
!U.message.includes("signal") && h && (T(`Error: ${U.message}\nPath:${y + a}\n`, { color: "red" }), "undefined" != typeof document && s(U.message)), N = N || {}, N.error = U.message;
|
|
1320
|
+
const e = "function" == typeof u ? u : null;
|
|
1321
|
+
return e ? (N.data = e({
|
|
1322
|
+
isLoading: void 0,
|
|
1323
|
+
error: U.message
|
|
1324
|
+
}), N = N.data) : delete N.isLoading, N;
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
//#endregion
|
|
1329
|
+
//#region ../../node_modules/.bun/grab-url@1.6.22/node_modules/grab-url/dist/grab-api.es.js
|
|
1330
|
+
async function i(t) {
|
|
1331
|
+
const { extract: r } = await Promise.resolve().then(() => require("./archiver-web.es-eh2cNrlm.js")), o = await r({ archiveBuffer: t }), e = {};
|
|
1332
|
+
for (const n of o) e[n.path] = n.content;
|
|
1333
|
+
return e;
|
|
1334
|
+
}
|
|
1335
|
+
async function c(t, r) {
|
|
1336
|
+
const { parseHTML: o } = await Promise.resolve().then(() => require("./index-CLlAnStL-BNm8mEFS.js")), { document: e } = o(t);
|
|
1337
|
+
if (!r || !0 === r) return e;
|
|
1338
|
+
const n = e.querySelector(r);
|
|
1339
|
+
return n ? n.innerHTML ?? n.textContent : null;
|
|
1340
|
+
}
|
|
1341
|
+
var l = l$1(async function(r, o$2, e, n, a, s, l, d) {
|
|
1342
|
+
const u = ("undefined" != typeof window ? window.grab : globalThis.grab)?.mock?.[o$2], f = JSON.stringify(a);
|
|
1343
|
+
if (u && (!u.method || u.method === n.method) && (!u.params || f === JSON.stringify(u.params))) return await o(u.delay || 0), "function" == typeof u.response ? u.response(a) : u.response;
|
|
1344
|
+
const w = await fetch(r + o$2 + e, n).catch((t) => {
|
|
1345
|
+
throw new Error(t.message);
|
|
1346
|
+
});
|
|
1347
|
+
if (!w.ok) throw new Error(`HTTP error: ${w.status} ${w.statusText}`);
|
|
1348
|
+
if (s) return await s(w.body), null;
|
|
1349
|
+
const h = w.headers.get("content-type") ?? "", g = !1 !== l && (h.includes("application/zip") || h.includes("application/x-zip")), m = !1 !== d && ("string" == typeof d || h.includes("text/html"));
|
|
1350
|
+
if (g) return { data: await i(await w.arrayBuffer().catch((t) => {
|
|
1351
|
+
throw new Error("Error reading zip: " + t);
|
|
1352
|
+
})) };
|
|
1353
|
+
if (m) return { data: await c(await w.text().catch((t) => {
|
|
1354
|
+
throw new Error("Error reading html: " + t);
|
|
1355
|
+
}), "string" != typeof d || d) };
|
|
1356
|
+
return await (h.includes("application/json") ? w.json() : h.includes("application/pdf") || h.includes("application/octet-stream") ? w.blob() : h ? w.text() : w.json()).catch((t) => {
|
|
1357
|
+
throw new Error("Error parsing response: " + t);
|
|
1358
|
+
});
|
|
1359
|
+
});
|
|
1360
|
+
var d = l;
|
|
1361
|
+
d.instance = (t = {}) => (r, o = {}) => l(r, {
|
|
1362
|
+
...t,
|
|
1363
|
+
...o
|
|
1364
|
+
}), d.log = [], d.mock = {}, d.defaults = {}, "undefined" != typeof window ? (window.log = l$2, window.grab = d, a(), document.addEventListener("DOMContentLoaded", () => {
|
|
1365
|
+
try {
|
|
1366
|
+
const t = localStorage.getItem("scroll");
|
|
1367
|
+
if (!t) return;
|
|
1368
|
+
const [r, o, e] = JSON.parse(t);
|
|
1369
|
+
if (!r || !e) return;
|
|
1370
|
+
const n = document.querySelector(e);
|
|
1371
|
+
n && (n.scrollTop = r, n.scrollLeft = o);
|
|
1372
|
+
} catch (t) {
|
|
1373
|
+
console.warn("Failed to restore scroll position", t);
|
|
1374
|
+
}
|
|
1375
|
+
})) : "undefined" != typeof globalThis && (globalThis.log = l$2, globalThis.grab = d);
|
|
1376
|
+
//#endregion
|
|
1043
1377
|
//#region src/http/fetch-http-client.ts
|
|
1044
1378
|
/**
|
|
1045
|
-
* @fileoverview HTTP client implementation using
|
|
1379
|
+
* @fileoverview HTTP client implementation using grab-url
|
|
1046
1380
|
*/
|
|
1047
1381
|
/**
|
|
1048
|
-
* Simple HTTP client implementation using
|
|
1382
|
+
* Simple HTTP client implementation using grab-url with proxy support.
|
|
1049
1383
|
* This client handles HTTP/HTTPS requests with configurable headers and proxy settings.
|
|
1050
1384
|
*
|
|
1051
1385
|
* @internal
|
|
@@ -1086,7 +1420,7 @@ var FetchHttpClient = class {
|
|
|
1086
1420
|
*/
|
|
1087
1421
|
async get(url, options) {
|
|
1088
1422
|
const proxyAgent = this.getProxyAgentForUrl(url);
|
|
1089
|
-
return (
|
|
1423
|
+
return d(url, {
|
|
1090
1424
|
...options,
|
|
1091
1425
|
method: "GET",
|
|
1092
1426
|
headers: {
|
|
@@ -1105,7 +1439,7 @@ var FetchHttpClient = class {
|
|
|
1105
1439
|
*/
|
|
1106
1440
|
async post(url, options) {
|
|
1107
1441
|
const proxyAgent = this.getProxyAgentForUrl(url);
|
|
1108
|
-
return (
|
|
1442
|
+
return d(url, {
|
|
1109
1443
|
...options,
|
|
1110
1444
|
method: "POST",
|
|
1111
1445
|
headers: {
|
|
@@ -1344,7 +1678,53 @@ var YouTubeTranscriptApi = class {
|
|
|
1344
1678
|
}
|
|
1345
1679
|
};
|
|
1346
1680
|
//#endregion
|
|
1347
|
-
//#region src/
|
|
1681
|
+
//#region src/utils/transcript-utils.ts
|
|
1682
|
+
/**
|
|
1683
|
+
* Encodes speech speed from a fetched transcript into a compact run-length string.
|
|
1684
|
+
* Optionally prepends a YouTube embed iframe with data-timestamps for player sync.
|
|
1685
|
+
* @param transcript - A FetchedTranscript returned by fetchTranscript()
|
|
1686
|
+
* @param addPlayer - If true, prepends an iframe embed with data-timestamps attribute
|
|
1687
|
+
* @returns html content, word count, run-length encoded speed string, and raw timestamps
|
|
1688
|
+
*/
|
|
1689
|
+
function encodeTranscriptSpeeds(transcript, addPlayer = false) {
|
|
1690
|
+
let charCount = 0;
|
|
1691
|
+
const timestamps = [];
|
|
1692
|
+
const textParts = [];
|
|
1693
|
+
for (const snippet of transcript.snippets) {
|
|
1694
|
+
textParts.push(snippet.text);
|
|
1695
|
+
charCount += snippet.text.length;
|
|
1696
|
+
if (snippet.start > 0) timestamps.push([charCount, snippet.start]);
|
|
1697
|
+
}
|
|
1698
|
+
const content = textParts.join(" ").replace(/\s+/g, " ");
|
|
1699
|
+
const word_count = content.split(/\s+/).filter(Boolean).length;
|
|
1700
|
+
const speedValues = timestamps.map(([char, time]) => Math.floor(char / time) - 10);
|
|
1701
|
+
if (speedValues.length === 0) return {
|
|
1702
|
+
html: content,
|
|
1703
|
+
word_count,
|
|
1704
|
+
speeds: ""
|
|
1705
|
+
};
|
|
1706
|
+
const compressed = [];
|
|
1707
|
+
const compressedCount = [];
|
|
1708
|
+
let currentNum = speedValues[0];
|
|
1709
|
+
let count = 1;
|
|
1710
|
+
for (let i = 1; i < speedValues.length; i++) if (speedValues[i] === currentNum) count++;
|
|
1711
|
+
else {
|
|
1712
|
+
compressed.push(currentNum);
|
|
1713
|
+
compressedCount.push(count);
|
|
1714
|
+
currentNum = speedValues[i];
|
|
1715
|
+
count = 1;
|
|
1716
|
+
}
|
|
1717
|
+
compressed.push(currentNum);
|
|
1718
|
+
compressedCount.push(count);
|
|
1719
|
+
const speeds = compressed.map((val, i) => `${val}x${compressedCount[i]}`).join(",");
|
|
1720
|
+
return {
|
|
1721
|
+
html: addPlayer ? `<iframe width="100%" height="315px" data-timestamps="${speeds}" src="https://www.youtube.com/embed/${transcript.videoId}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>${content}` : content,
|
|
1722
|
+
word_count,
|
|
1723
|
+
speeds
|
|
1724
|
+
};
|
|
1725
|
+
}
|
|
1726
|
+
//#endregion
|
|
1727
|
+
//#region src/proxies/index.ts
|
|
1348
1728
|
var _WebshareProxyConfig;
|
|
1349
1729
|
/**
|
|
1350
1730
|
* Exception for invalid proxy configurations
|
|
@@ -1510,7 +1890,7 @@ _WebshareProxyConfig = WebshareProxyConfig;
|
|
|
1510
1890
|
_WebshareProxyConfig.DEFAULT_DOMAIN_NAME = "p.webshare.io";
|
|
1511
1891
|
_WebshareProxyConfig.DEFAULT_PORT = 80;
|
|
1512
1892
|
//#endregion
|
|
1513
|
-
//#region src/formatters.ts
|
|
1893
|
+
//#region src/formatters/index.ts
|
|
1514
1894
|
/**
|
|
1515
1895
|
* Base abstract class for all transcript formatters.
|
|
1516
1896
|
*/
|
|
@@ -1604,7 +1984,7 @@ var WebVTTFormatter = class extends SubtitleFormatterBase {
|
|
|
1604
1984
|
};
|
|
1605
1985
|
//#endregion
|
|
1606
1986
|
//#region package.json
|
|
1607
|
-
var package_exports = /* @__PURE__ */ __exportAll({
|
|
1987
|
+
var package_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
|
|
1608
1988
|
author: () => "",
|
|
1609
1989
|
bin: () => bin,
|
|
1610
1990
|
default: () => package_default,
|
|
@@ -1618,14 +1998,15 @@ var package_exports = /* @__PURE__ */ __exportAll({
|
|
|
1618
1998
|
main: () => main$1,
|
|
1619
1999
|
module: () => module$1,
|
|
1620
2000
|
name: () => name,
|
|
2001
|
+
repository: () => repository,
|
|
1621
2002
|
scripts: () => scripts,
|
|
1622
2003
|
types: () => types,
|
|
1623
2004
|
version: () => version
|
|
1624
|
-
}), name, version, description, main$1, module$1, types, exports$1, bin, scripts, keywords, dependencies, devDependencies, engines, package_default;
|
|
1625
|
-
var init_package = __esmMin((() => {
|
|
2005
|
+
}), name, version, description, main$1, module$1, types, exports$1, bin, scripts, keywords, repository, dependencies, devDependencies, engines, package_default;
|
|
2006
|
+
var init_package = require_rolldown_runtime.__esmMin((() => {
|
|
1626
2007
|
name = "extract-youtube";
|
|
1627
|
-
version = "1.0.
|
|
1628
|
-
description = "Fast, serverless-optimized YouTube transcript extractor
|
|
2008
|
+
version = "1.0.3";
|
|
2009
|
+
description = "Fast, no-browser serverless-optimized YouTube transcript extractor";
|
|
1629
2010
|
main$1 = "dist/index.cjs";
|
|
1630
2011
|
module$1 = "dist/index.mjs";
|
|
1631
2012
|
types = "dist/index.d.ts";
|
|
@@ -1634,7 +2015,7 @@ var init_package = __esmMin((() => {
|
|
|
1634
2015
|
"require": "./dist/index.cjs",
|
|
1635
2016
|
"types": "./dist/index.d.ts"
|
|
1636
2017
|
} };
|
|
1637
|
-
bin =
|
|
2018
|
+
bin = "dist/cli.js";
|
|
1638
2019
|
scripts = {
|
|
1639
2020
|
"build": "npm run build:types && npm run build:lib && npm run build:cli",
|
|
1640
2021
|
"build:types": "tsc --emitDeclarationOnly --declaration --declarationMap",
|
|
@@ -1645,6 +2026,7 @@ var init_package = __esmMin((() => {
|
|
|
1645
2026
|
"prepare": "npm run build",
|
|
1646
2027
|
"ship": "npx standard-version --release-as patch; npm publish",
|
|
1647
2028
|
"test": "jest",
|
|
2029
|
+
"test:speeds": "bun src/cli.ts dQw4w9WgXcQ -f speeds",
|
|
1648
2030
|
"lint": "eslint src --ext .ts"
|
|
1649
2031
|
};
|
|
1650
2032
|
keywords = [
|
|
@@ -1668,17 +2050,21 @@ var init_package = __esmMin((() => {
|
|
|
1668
2050
|
"extraction",
|
|
1669
2051
|
"optimized"
|
|
1670
2052
|
];
|
|
2053
|
+
repository = {
|
|
2054
|
+
"type": "git",
|
|
2055
|
+
"url": "git+https://github.com/OpenSourceAGI/qwksearch-research-agent.git",
|
|
2056
|
+
"directory": "packages/extract-youtube"
|
|
2057
|
+
};
|
|
1671
2058
|
dependencies = {
|
|
1672
2059
|
"fast-xml-parser": "^4.2.5",
|
|
1673
2060
|
"html-entities": "^2.3.3",
|
|
1674
|
-
"https-proxy-agent": "^
|
|
1675
|
-
"
|
|
2061
|
+
"https-proxy-agent": "^7.0.6",
|
|
2062
|
+
"grab-url": "^1.6.19",
|
|
1676
2063
|
"youtube-transcript-api": "^3.0.6"
|
|
1677
2064
|
};
|
|
1678
2065
|
devDependencies = {
|
|
1679
2066
|
"@types/jest": "^29.5.14",
|
|
1680
|
-
"@types/node": "
|
|
1681
|
-
"@types/node-fetch": "^2.6.2",
|
|
2067
|
+
"@types/node": ">=22.12.0",
|
|
1682
2068
|
"jest": "^29.5.0",
|
|
1683
2069
|
"terser": "^5.46.0",
|
|
1684
2070
|
"ts-jest": "^29.1.0",
|
|
@@ -1699,6 +2085,7 @@ var init_package = __esmMin((() => {
|
|
|
1699
2085
|
keywords,
|
|
1700
2086
|
author: "",
|
|
1701
2087
|
license: "MIT",
|
|
2088
|
+
repository,
|
|
1702
2089
|
dependencies,
|
|
1703
2090
|
devDependencies,
|
|
1704
2091
|
engines
|
|
@@ -1762,7 +2149,7 @@ OPTIONS:
|
|
|
1762
2149
|
-h, --help Show this help message
|
|
1763
2150
|
-v, --version Show version number
|
|
1764
2151
|
-l, --languages <codes> Comma-separated language codes (e.g., en,de,fr)
|
|
1765
|
-
-f, --format <type> Output format: json, text, srt, webvtt, pretty (default: json)
|
|
2152
|
+
-f, --format <type> Output format: json, text, srt, webvtt, pretty, speeds (default: json)
|
|
1766
2153
|
-p, --preserve-formatting Preserve text formatting (line breaks, etc.)
|
|
1767
2154
|
--proxy <url> HTTP/HTTPS proxy URL
|
|
1768
2155
|
--webshare-user <username> Webshare proxy username
|
|
@@ -1786,10 +2173,13 @@ EXAMPLES:
|
|
|
1786
2173
|
|
|
1787
2174
|
# Extract transcript as plain text with preserved formatting
|
|
1788
2175
|
extract-youtube jNQXAC9IVRw -f text -p
|
|
2176
|
+
|
|
2177
|
+
# Extract speech speed encoding with joined text and timestamps
|
|
2178
|
+
extract-youtube jNQXAC9IVRw -f speeds
|
|
1789
2179
|
`);
|
|
1790
2180
|
}
|
|
1791
2181
|
function showVersion() {
|
|
1792
|
-
const pkg = (init_package(), __toCommonJS(package_exports).default);
|
|
2182
|
+
const pkg = (init_package(), require_rolldown_runtime.__toCommonJS(package_exports).default);
|
|
1793
2183
|
console.log(`extract-youtube v${pkg.version}`);
|
|
1794
2184
|
}
|
|
1795
2185
|
async function main() {
|
|
@@ -1836,6 +2226,15 @@ async function main() {
|
|
|
1836
2226
|
case "pretty":
|
|
1837
2227
|
output = new PrettyPrintFormatter().formatTranscript(transcript);
|
|
1838
2228
|
break;
|
|
2229
|
+
case "speeds": {
|
|
2230
|
+
const { html, word_count, speeds } = encodeTranscriptSpeeds(transcript);
|
|
2231
|
+
output = JSON.stringify({
|
|
2232
|
+
html,
|
|
2233
|
+
word_count,
|
|
2234
|
+
speeds
|
|
2235
|
+
});
|
|
2236
|
+
break;
|
|
2237
|
+
}
|
|
1839
2238
|
default: throw new Error(`Unknown format: ${format}`);
|
|
1840
2239
|
}
|
|
1841
2240
|
console.log(output);
|