@tacone/prosey 0.8.0 → 0.9.0
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/bin/prosey +74 -10
- package/package.json +1 -1
- package/src/default-config.toml +2 -2
- package/src/html.ts +29 -6
- package/src/index.ts +64 -2
package/bin/prosey
CHANGED
|
@@ -103177,14 +103177,21 @@ var LOGO_DATA_URI = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(LOGO_
|
|
|
103177
103177
|
function escapeHtml(text) {
|
|
103178
103178
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
103179
103179
|
}
|
|
103180
|
-
function watchMetaHtml(duration, wordCount, videoId) {
|
|
103180
|
+
function watchMetaHtml(duration, wordCount, videoId, channelName, channelId, channelDescription) {
|
|
103181
|
+
const sep = '<span style="opacity: 0.4"> | </span>';
|
|
103181
103182
|
const h2 = Math.floor(duration / 3600);
|
|
103182
103183
|
const m3 = Math.round(duration % 3600 / 60);
|
|
103183
103184
|
const durStr = h2 > 0 ? `${h2} h ${m3} min` : `${m3} min`;
|
|
103184
103185
|
const readTime = Math.ceil(wordCount / 200);
|
|
103185
|
-
const
|
|
103186
|
-
|
|
103187
|
-
|
|
103186
|
+
const watchUrl = `https://youtube.com/watch?v=${videoId}`;
|
|
103187
|
+
let parts = "";
|
|
103188
|
+
if (channelName) {
|
|
103189
|
+
const chUrl = channelId ? `https://youtube.com/channel/${channelId}` : `https://youtube.com/@${encodeURIComponent(channelName)}`;
|
|
103190
|
+
const chDesc = channelDescription || channelName;
|
|
103191
|
+
parts += `<a href="${chUrl}" class="watch-link" title="${escapeHtml(chDesc)}">${escapeHtml(channelName)}</a>${sep}`;
|
|
103192
|
+
}
|
|
103193
|
+
parts += `<a href="${watchUrl}" class="watch-link">${durStr} watch</a>${sep}${readTime} min read`;
|
|
103194
|
+
return parts;
|
|
103188
103195
|
}
|
|
103189
103196
|
async function generateHtml(markdown, title, watchMeta) {
|
|
103190
103197
|
const [css, body] = await Promise.all([getPicoCss(), g2.parse(markdown)]);
|
|
@@ -103275,7 +103282,7 @@ img[alt="Prosey"]:hover, img[alt="Prosey"]:active, img[alt="Prosey"]:focus { fil
|
|
|
103275
103282
|
<body>
|
|
103276
103283
|
<div style="display:flex;align-items:center;justify-content:space-between;padding:1rem 1rem 0">
|
|
103277
103284
|
<img src="${LOGO_DATA_URI}" alt="Prosey" title="Prosey" style="vertical-align:top;flex-shrink:0">
|
|
103278
|
-
<div style="flex:1;text-align:center;font-size:.85rem;color:var(--pico-muted-color)">${watchMeta ? watchMetaHtml(watchMeta.duration, watchMeta.wordCount, watchMeta.videoId) : ""}</div>
|
|
103285
|
+
<div style="flex:1;text-align:center;font-size:.85rem;color:var(--pico-muted-color)">${watchMeta ? watchMetaHtml(watchMeta.duration, watchMeta.wordCount, watchMeta.videoId, watchMeta.channelName, watchMeta.channelId, watchMeta.channelDescription) : ""}</div>
|
|
103279
103286
|
<button id="theme-btn" type="button" style="background:none;border:none;cursor:pointer;padding:0;line-height:1;opacity:.5;filter:grayscale(100%);transition:all 0.3s;flex-shrink:0">\uD83D\uDCA1</button>
|
|
103280
103287
|
</div>
|
|
103281
103288
|
<main class="content">
|
|
@@ -103313,7 +103320,7 @@ function openInBrowser(htmlPath) {
|
|
|
103313
103320
|
// package.json
|
|
103314
103321
|
var package_default = {
|
|
103315
103322
|
name: "@tacone/prosey",
|
|
103316
|
-
version: "0.
|
|
103323
|
+
version: "0.9.0",
|
|
103317
103324
|
description: "Download YouTube video transcripts from the CLI",
|
|
103318
103325
|
module: "src/index.ts",
|
|
103319
103326
|
type: "module",
|
|
@@ -121940,6 +121947,25 @@ var debugApis = {
|
|
|
121940
121947
|
};
|
|
121941
121948
|
|
|
121942
121949
|
// src/index.ts
|
|
121950
|
+
var YT_INNERTUBE_API_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
|
|
121951
|
+
async function fetchChannelDescription(channelId) {
|
|
121952
|
+
try {
|
|
121953
|
+
const resp = await fetch(`https://www.youtube.com/youtubei/v1/browse?key=${YT_INNERTUBE_API_KEY}`, {
|
|
121954
|
+
method: "POST",
|
|
121955
|
+
headers: { "Content-Type": "application/json" },
|
|
121956
|
+
body: JSON.stringify({
|
|
121957
|
+
context: {
|
|
121958
|
+
client: { clientName: "WEB", clientVersion: "2.20240101.00.00" }
|
|
121959
|
+
},
|
|
121960
|
+
browseId: channelId
|
|
121961
|
+
})
|
|
121962
|
+
});
|
|
121963
|
+
const data = await resp.json();
|
|
121964
|
+
return data?.metadata?.channelMetadataRenderer?.description;
|
|
121965
|
+
} catch {
|
|
121966
|
+
return;
|
|
121967
|
+
}
|
|
121968
|
+
}
|
|
121943
121969
|
process.stdout.on("error", (err) => {
|
|
121944
121970
|
if (err.code === "EPIPE")
|
|
121945
121971
|
process.exit(0);
|
|
@@ -122340,15 +122366,23 @@ try {
|
|
|
122340
122366
|
let structuredContent;
|
|
122341
122367
|
let videoTitle;
|
|
122342
122368
|
let videoDuration = 0;
|
|
122369
|
+
let channelName;
|
|
122370
|
+
let channelId;
|
|
122371
|
+
let channelDescription;
|
|
122343
122372
|
if (!segments2) {
|
|
122344
122373
|
info("Fetching transcript...");
|
|
122345
122374
|
const opts = lang ? { lang, videoDetails: true } : { videoDetails: true };
|
|
122346
122375
|
const result = await fetchTranscript(videoId, opts);
|
|
122347
122376
|
segments2 = result.segments;
|
|
122348
122377
|
videoDuration = result.videoDetails.lengthSeconds;
|
|
122378
|
+
channelName = result.videoDetails.author;
|
|
122379
|
+
channelId = result.videoDetails.channelId;
|
|
122380
|
+
channelDescription = await fetchChannelDescription(channelId);
|
|
122349
122381
|
const infoJson = JSON.stringify({
|
|
122350
122382
|
title: result.videoDetails.title,
|
|
122351
|
-
channel:
|
|
122383
|
+
channel: channelName,
|
|
122384
|
+
channelId,
|
|
122385
|
+
channelDescription,
|
|
122352
122386
|
description: result.videoDetails.description,
|
|
122353
122387
|
duration: videoDuration
|
|
122354
122388
|
});
|
|
@@ -122385,9 +122419,14 @@ ${structuredContent}
|
|
|
122385
122419
|
const fallbackOpts = lang ? { lang, videoDetails: true } : { videoDetails: true };
|
|
122386
122420
|
const fallbackResult = await fetchTranscript(videoId, fallbackOpts);
|
|
122387
122421
|
videoDuration = fallbackResult.videoDetails.lengthSeconds;
|
|
122422
|
+
channelName = fallbackResult.videoDetails.author;
|
|
122423
|
+
channelId = fallbackResult.videoDetails.channelId;
|
|
122424
|
+
channelDescription = await fetchChannelDescription(channelId);
|
|
122388
122425
|
cachedInfo = JSON.stringify({
|
|
122389
122426
|
title: fallbackResult.videoDetails.title,
|
|
122390
122427
|
channel: fallbackResult.videoDetails.author,
|
|
122428
|
+
channelId,
|
|
122429
|
+
channelDescription,
|
|
122391
122430
|
description: fallbackResult.videoDetails.description,
|
|
122392
122431
|
duration: videoDuration
|
|
122393
122432
|
});
|
|
@@ -122403,6 +122442,9 @@ ${structuredContent}
|
|
|
122403
122442
|
const cachedInfoObj = JSON.parse(cachedInfo);
|
|
122404
122443
|
videoTitle = cachedInfoObj.title;
|
|
122405
122444
|
videoDuration = cachedInfoObj.duration ?? 0;
|
|
122445
|
+
channelName = cachedInfoObj.channel;
|
|
122446
|
+
channelId = cachedInfoObj.channelId;
|
|
122447
|
+
channelDescription = cachedInfoObj.channelDescription;
|
|
122406
122448
|
const truncatedInfo = JSON.stringify({
|
|
122407
122449
|
title: cachedInfoObj.title,
|
|
122408
122450
|
channel: cachedInfoObj.channel,
|
|
@@ -122439,7 +122481,10 @@ ${structuredContent}
|
|
|
122439
122481
|
const htmlContent = await generateHtml(formatted, videoTitle, {
|
|
122440
122482
|
videoId,
|
|
122441
122483
|
duration: videoDuration,
|
|
122442
|
-
wordCount
|
|
122484
|
+
wordCount,
|
|
122485
|
+
channelName,
|
|
122486
|
+
channelId,
|
|
122487
|
+
channelDescription
|
|
122443
122488
|
});
|
|
122444
122489
|
const htmlPath = join5(dir2, "summary.html");
|
|
122445
122490
|
await writeFile3(htmlPath, htmlContent, "utf8");
|
|
@@ -122473,6 +122518,9 @@ ${structuredContent}
|
|
|
122473
122518
|
let md = null;
|
|
122474
122519
|
let videoTitle;
|
|
122475
122520
|
let videoDuration = 0;
|
|
122521
|
+
let channelName;
|
|
122522
|
+
let channelId;
|
|
122523
|
+
let channelDescription;
|
|
122476
122524
|
startTimer();
|
|
122477
122525
|
let cachedInfo = null;
|
|
122478
122526
|
if (!noCache) {
|
|
@@ -122501,9 +122549,14 @@ ${structuredContent}
|
|
|
122501
122549
|
const result = await fetchTranscript(videoId, opts);
|
|
122502
122550
|
segments2 = result.segments;
|
|
122503
122551
|
videoDuration = result.videoDetails.lengthSeconds;
|
|
122552
|
+
channelName = result.videoDetails.author;
|
|
122553
|
+
channelId = result.videoDetails.channelId;
|
|
122554
|
+
channelDescription = await fetchChannelDescription(channelId);
|
|
122504
122555
|
const infoJson = JSON.stringify({
|
|
122505
122556
|
title: result.videoDetails.title,
|
|
122506
|
-
channel:
|
|
122557
|
+
channel: channelName,
|
|
122558
|
+
channelId,
|
|
122559
|
+
channelDescription,
|
|
122507
122560
|
description: result.videoDetails.description,
|
|
122508
122561
|
duration: videoDuration
|
|
122509
122562
|
});
|
|
@@ -122555,9 +122608,14 @@ ${structuredContent}
|
|
|
122555
122608
|
const fallbackOpts = lang ? { lang, videoDetails: true } : { videoDetails: true };
|
|
122556
122609
|
const fallbackResult = await fetchTranscript(videoId, fallbackOpts);
|
|
122557
122610
|
videoDuration = fallbackResult.videoDetails.lengthSeconds;
|
|
122611
|
+
channelName = fallbackResult.videoDetails.author;
|
|
122612
|
+
channelId = fallbackResult.videoDetails.channelId;
|
|
122613
|
+
channelDescription = await fetchChannelDescription(channelId);
|
|
122558
122614
|
cachedInfo = JSON.stringify({
|
|
122559
122615
|
title: fallbackResult.videoDetails.title,
|
|
122560
122616
|
channel: fallbackResult.videoDetails.author,
|
|
122617
|
+
channelId,
|
|
122618
|
+
channelDescription,
|
|
122561
122619
|
description: fallbackResult.videoDetails.description,
|
|
122562
122620
|
duration: videoDuration
|
|
122563
122621
|
});
|
|
@@ -122573,6 +122631,9 @@ ${structuredContent}
|
|
|
122573
122631
|
const cachedInfoObj = JSON.parse(cachedInfo);
|
|
122574
122632
|
videoTitle = cachedInfoObj.title;
|
|
122575
122633
|
videoDuration = cachedInfoObj.duration ?? 0;
|
|
122634
|
+
channelName = cachedInfoObj.channel;
|
|
122635
|
+
channelId = cachedInfoObj.channelId;
|
|
122636
|
+
channelDescription = cachedInfoObj.channelDescription;
|
|
122576
122637
|
const truncatedInfo = JSON.stringify({
|
|
122577
122638
|
title: cachedInfoObj.title,
|
|
122578
122639
|
channel: cachedInfoObj.channel,
|
|
@@ -122605,7 +122666,10 @@ ${transcriptText}`;
|
|
|
122605
122666
|
const htmlContent = await generateHtml(formatted, videoTitle, {
|
|
122606
122667
|
videoId,
|
|
122607
122668
|
duration: videoDuration,
|
|
122608
|
-
wordCount
|
|
122669
|
+
wordCount,
|
|
122670
|
+
channelName,
|
|
122671
|
+
channelId,
|
|
122672
|
+
channelDescription
|
|
122609
122673
|
});
|
|
122610
122674
|
const htmlPath = join5(dir2, "transcript.html");
|
|
122611
122675
|
await writeFile3(htmlPath, htmlContent, "utf8");
|
package/package.json
CHANGED
package/src/default-config.toml
CHANGED
|
@@ -25,7 +25,7 @@ hints = true
|
|
|
25
25
|
# OPENCODE_PERMISSION='{"read":"allow","write":"deny","edit":"deny","bash":"deny","glob":"deny","grep":"deny","webfetch":\"deny\",\"task\":\"deny\",\"todowrite\":\"deny\",\"websearch\":\"deny","lsp":"deny"}' opencode run --pure
|
|
26
26
|
# copilot -s --deny-all-tools --read-only
|
|
27
27
|
|
|
28
|
-
command = "OPENCODE_PERMISSION='{\"read\":\"allow\",\"write\":\"deny\",\"edit\":\"deny\",\"bash\":\"deny\",\"glob\":\"deny\",\"grep\":\"deny\",\"webfetch\":\"deny\",\"task\":\"deny\",\"todowrite\":\"deny\",\"websearch\":\"deny\",\"lsp\":\"deny\"}' opencode run --pure --variant low"
|
|
28
|
+
command = "OPENCODE_PERMISSION='{\"read\":\"allow\",\"write\":\"deny\",\"edit\":\"deny\",\"bash\":\"deny\",\"glob\":\"deny\",\"grep\":\"deny\",\"webfetch\":\"deny\",\"task\":\"deny\",\"todowrite\":\"deny\",\"websearch\":\"deny\",\"lsp\":\"deny\"}' opencode run --pure --model opencode/deepseek-v4-flash-free --variant low"
|
|
29
29
|
|
|
30
30
|
[summarize]
|
|
31
31
|
|
|
@@ -41,7 +41,7 @@ Guidelines:
|
|
|
41
41
|
- use the TIMESTAMPS only to understand the structure, don't output time markers
|
|
42
42
|
- content length: aim to be the same range as the original text or more.
|
|
43
43
|
- section titles should be h2 headers
|
|
44
|
-
- paragraph length soft-limit
|
|
44
|
+
- paragraph length: soft-limit 250 characters, hard-limit 350 characters.
|
|
45
45
|
|
|
46
46
|
Content considerations:
|
|
47
47
|
|
package/src/html.ts
CHANGED
|
@@ -34,20 +34,43 @@ function escapeHtml(text: string): string {
|
|
|
34
34
|
.replace(/"/g, """);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function watchMetaHtml(
|
|
37
|
+
function watchMetaHtml(
|
|
38
|
+
duration: number,
|
|
39
|
+
wordCount: number,
|
|
40
|
+
videoId: string,
|
|
41
|
+
channelName?: string,
|
|
42
|
+
channelId?: string,
|
|
43
|
+
channelDescription?: string,
|
|
44
|
+
): string {
|
|
45
|
+
const sep = '<span style="opacity: 0.4"> | </span>';
|
|
38
46
|
const h = Math.floor(duration / 3600);
|
|
39
47
|
const m = Math.round((duration % 3600) / 60);
|
|
40
48
|
const durStr = h > 0 ? `${h} h ${m} min` : `${m} min`;
|
|
41
49
|
const readTime = Math.ceil(wordCount / 200);
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
const watchUrl = `https://youtube.com/watch?v=${videoId}`;
|
|
51
|
+
let parts = "";
|
|
52
|
+
if (channelName) {
|
|
53
|
+
const chUrl = channelId
|
|
54
|
+
? `https://youtube.com/channel/${channelId}`
|
|
55
|
+
: `https://youtube.com/@${encodeURIComponent(channelName)}`;
|
|
56
|
+
const chDesc = channelDescription || channelName;
|
|
57
|
+
parts += `<a href="${chUrl}" class="watch-link" title="${escapeHtml(chDesc)}">${escapeHtml(channelName)}</a>${sep}`;
|
|
58
|
+
}
|
|
59
|
+
parts += `<a href="${watchUrl}" class="watch-link">${durStr} watch</a>${sep}${readTime} min read`;
|
|
60
|
+
return parts;
|
|
45
61
|
}
|
|
46
62
|
|
|
47
63
|
export async function generateHtml(
|
|
48
64
|
markdown: string,
|
|
49
65
|
title?: string,
|
|
50
|
-
watchMeta?: {
|
|
66
|
+
watchMeta?: {
|
|
67
|
+
videoId: string;
|
|
68
|
+
duration: number;
|
|
69
|
+
wordCount: number;
|
|
70
|
+
channelName?: string;
|
|
71
|
+
channelId?: string;
|
|
72
|
+
channelDescription?: string;
|
|
73
|
+
},
|
|
51
74
|
): Promise<string> {
|
|
52
75
|
const [css, body] = await Promise.all([getPicoCss(), marked.parse(markdown)]);
|
|
53
76
|
|
|
@@ -138,7 +161,7 @@ img[alt="Prosey"]:hover, img[alt="Prosey"]:active, img[alt="Prosey"]:focus { fil
|
|
|
138
161
|
<body>
|
|
139
162
|
<div style="display:flex;align-items:center;justify-content:space-between;padding:1rem 1rem 0">
|
|
140
163
|
<img src="${LOGO_DATA_URI}" alt="Prosey" title="Prosey" style="vertical-align:top;flex-shrink:0">
|
|
141
|
-
<div style="flex:1;text-align:center;font-size:.85rem;color:var(--pico-muted-color)">${watchMeta ? watchMetaHtml(watchMeta.duration, watchMeta.wordCount, watchMeta.videoId) : ""}</div>
|
|
164
|
+
<div style="flex:1;text-align:center;font-size:.85rem;color:var(--pico-muted-color)">${watchMeta ? watchMetaHtml(watchMeta.duration, watchMeta.wordCount, watchMeta.videoId, watchMeta.channelName, watchMeta.channelId, watchMeta.channelDescription) : ""}</div>
|
|
142
165
|
<button id="theme-btn" type="button" style="background:none;border:none;cursor:pointer;padding:0;line-height:1;opacity:.5;filter:grayscale(100%);transition:all 0.3s;flex-shrink:0">💡</button>
|
|
143
166
|
</div>
|
|
144
167
|
<main class="content">
|
package/src/index.ts
CHANGED
|
@@ -25,6 +25,30 @@ import { checkVersion } from "./version-check";
|
|
|
25
25
|
import pkg from "../package.json";
|
|
26
26
|
import prettier from "prettier";
|
|
27
27
|
|
|
28
|
+
const YT_INNERTUBE_API_KEY = "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8";
|
|
29
|
+
|
|
30
|
+
async function fetchChannelDescription(channelId: string): Promise<string | undefined> {
|
|
31
|
+
try {
|
|
32
|
+
const resp = await fetch(
|
|
33
|
+
`https://www.youtube.com/youtubei/v1/browse?key=${YT_INNERTUBE_API_KEY}`,
|
|
34
|
+
{
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: { "Content-Type": "application/json" },
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
context: {
|
|
39
|
+
client: { clientName: "WEB", clientVersion: "2.20240101.00.00" },
|
|
40
|
+
},
|
|
41
|
+
browseId: channelId,
|
|
42
|
+
}),
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
const data: any = await resp.json();
|
|
46
|
+
return data?.metadata?.channelMetadataRenderer?.description;
|
|
47
|
+
} catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
28
52
|
process.stdout.on("error", (err: NodeJS.ErrnoException) => {
|
|
29
53
|
if (err.code === "EPIPE") process.exit(0);
|
|
30
54
|
});
|
|
@@ -484,6 +508,9 @@ try {
|
|
|
484
508
|
let structuredContent: string;
|
|
485
509
|
let videoTitle: string | undefined;
|
|
486
510
|
let videoDuration = 0;
|
|
511
|
+
let channelName: string | undefined;
|
|
512
|
+
let channelId: string | undefined;
|
|
513
|
+
let channelDescription: string | undefined;
|
|
487
514
|
|
|
488
515
|
if (!segments) {
|
|
489
516
|
info("Fetching transcript...");
|
|
@@ -494,9 +521,14 @@ try {
|
|
|
494
521
|
};
|
|
495
522
|
segments = result.segments;
|
|
496
523
|
videoDuration = result.videoDetails.lengthSeconds;
|
|
524
|
+
channelName = result.videoDetails.author;
|
|
525
|
+
channelId = result.videoDetails.channelId;
|
|
526
|
+
channelDescription = await fetchChannelDescription(channelId);
|
|
497
527
|
const infoJson = JSON.stringify({
|
|
498
528
|
title: result.videoDetails.title,
|
|
499
|
-
channel:
|
|
529
|
+
channel: channelName,
|
|
530
|
+
channelId: channelId,
|
|
531
|
+
channelDescription: channelDescription,
|
|
500
532
|
description: result.videoDetails.description,
|
|
501
533
|
duration: videoDuration,
|
|
502
534
|
});
|
|
@@ -533,9 +565,14 @@ try {
|
|
|
533
565
|
segments: TranscriptSegment[];
|
|
534
566
|
};
|
|
535
567
|
videoDuration = fallbackResult.videoDetails.lengthSeconds;
|
|
568
|
+
channelName = fallbackResult.videoDetails.author;
|
|
569
|
+
channelId = fallbackResult.videoDetails.channelId;
|
|
570
|
+
channelDescription = await fetchChannelDescription(channelId);
|
|
536
571
|
cachedInfo = JSON.stringify({
|
|
537
572
|
title: fallbackResult.videoDetails.title,
|
|
538
573
|
channel: fallbackResult.videoDetails.author,
|
|
574
|
+
channelId: channelId,
|
|
575
|
+
channelDescription: channelDescription,
|
|
539
576
|
description: fallbackResult.videoDetails.description,
|
|
540
577
|
duration: videoDuration,
|
|
541
578
|
});
|
|
@@ -553,6 +590,9 @@ try {
|
|
|
553
590
|
const cachedInfoObj = JSON.parse(cachedInfo);
|
|
554
591
|
videoTitle = cachedInfoObj.title;
|
|
555
592
|
videoDuration = cachedInfoObj.duration ?? 0;
|
|
593
|
+
channelName = cachedInfoObj.channel;
|
|
594
|
+
channelId = cachedInfoObj.channelId;
|
|
595
|
+
channelDescription = cachedInfoObj.channelDescription;
|
|
556
596
|
const truncatedInfo = JSON.stringify({
|
|
557
597
|
title: cachedInfoObj.title,
|
|
558
598
|
channel: cachedInfoObj.channel,
|
|
@@ -586,6 +626,9 @@ try {
|
|
|
586
626
|
videoId,
|
|
587
627
|
duration: videoDuration,
|
|
588
628
|
wordCount,
|
|
629
|
+
channelName,
|
|
630
|
+
channelId,
|
|
631
|
+
channelDescription,
|
|
589
632
|
});
|
|
590
633
|
const htmlPath = join(dir, "summary.html");
|
|
591
634
|
await writeFile(htmlPath, htmlContent, "utf8");
|
|
@@ -622,6 +665,9 @@ try {
|
|
|
622
665
|
let md: string | null = null;
|
|
623
666
|
let videoTitle: string | undefined;
|
|
624
667
|
let videoDuration = 0;
|
|
668
|
+
let channelName: string | undefined;
|
|
669
|
+
let channelId: string | undefined;
|
|
670
|
+
let channelDescription: string | undefined;
|
|
625
671
|
|
|
626
672
|
startTimer();
|
|
627
673
|
|
|
@@ -660,9 +706,14 @@ try {
|
|
|
660
706
|
};
|
|
661
707
|
segments = result.segments;
|
|
662
708
|
videoDuration = result.videoDetails.lengthSeconds;
|
|
709
|
+
channelName = result.videoDetails.author;
|
|
710
|
+
channelId = result.videoDetails.channelId;
|
|
711
|
+
channelDescription = await fetchChannelDescription(channelId);
|
|
663
712
|
const infoJson = JSON.stringify({
|
|
664
713
|
title: result.videoDetails.title,
|
|
665
|
-
channel:
|
|
714
|
+
channel: channelName,
|
|
715
|
+
channelId: channelId,
|
|
716
|
+
channelDescription: channelDescription,
|
|
666
717
|
description: result.videoDetails.description,
|
|
667
718
|
duration: videoDuration,
|
|
668
719
|
});
|
|
@@ -712,9 +763,14 @@ try {
|
|
|
712
763
|
segments: TranscriptSegment[];
|
|
713
764
|
};
|
|
714
765
|
videoDuration = fallbackResult.videoDetails.lengthSeconds;
|
|
766
|
+
channelName = fallbackResult.videoDetails.author;
|
|
767
|
+
channelId = fallbackResult.videoDetails.channelId;
|
|
768
|
+
channelDescription = await fetchChannelDescription(channelId);
|
|
715
769
|
cachedInfo = JSON.stringify({
|
|
716
770
|
title: fallbackResult.videoDetails.title,
|
|
717
771
|
channel: fallbackResult.videoDetails.author,
|
|
772
|
+
channelId: channelId,
|
|
773
|
+
channelDescription: channelDescription,
|
|
718
774
|
description: fallbackResult.videoDetails.description,
|
|
719
775
|
duration: videoDuration,
|
|
720
776
|
});
|
|
@@ -732,6 +788,9 @@ try {
|
|
|
732
788
|
const cachedInfoObj = JSON.parse(cachedInfo);
|
|
733
789
|
videoTitle = cachedInfoObj.title;
|
|
734
790
|
videoDuration = cachedInfoObj.duration ?? 0;
|
|
791
|
+
channelName = cachedInfoObj.channel;
|
|
792
|
+
channelId = cachedInfoObj.channelId;
|
|
793
|
+
channelDescription = cachedInfoObj.channelDescription;
|
|
735
794
|
const truncatedInfo = JSON.stringify({
|
|
736
795
|
title: cachedInfoObj.title,
|
|
737
796
|
channel: cachedInfoObj.channel,
|
|
@@ -760,6 +819,9 @@ try {
|
|
|
760
819
|
videoId,
|
|
761
820
|
duration: videoDuration,
|
|
762
821
|
wordCount,
|
|
822
|
+
channelName,
|
|
823
|
+
channelId,
|
|
824
|
+
channelDescription,
|
|
763
825
|
});
|
|
764
826
|
const htmlPath = join(dir, "transcript.html");
|
|
765
827
|
await writeFile(htmlPath, htmlContent, "utf8");
|