summd 0.1.10 → 0.1.12

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.
Files changed (2) hide show
  1. package/dist/url-to-md.js +50 -21
  2. package/package.json +1 -1
package/dist/url-to-md.js CHANGED
@@ -80,14 +80,12 @@ async function fetchYouTubeTitle(url, videoId) {
80
80
  }
81
81
  // Browser cookie sources — tried in order, first working one is reused for all runs.
82
82
  const BROWSERS = ['chrome', 'chromium', 'firefox', 'safari', 'edge'];
83
- // Subtitle strategies tried in order, stop at first that produces output.
84
- // Each downloads only the requested languages, not everything.
85
- const SUB_STRATEGIES = [
86
- // 1. Original-language ASR: yt-dlp 'orig' matches the video's primary language
87
- ['--write-auto-subs', '--sub-langs', 'orig'],
88
- // 2. English manual + ASR
83
+ // Subtitle fallback strategies used when native language detection fails.
84
+ // Tried in order after the native-language attempt.
85
+ const SUB_FALLBACKS = [
86
+ // 1. English manual + ASR
89
87
  ['--write-subs', '--write-auto-subs', '--sub-langs', 'en'],
90
- // 3. Most-spoken languages by global user count (covers remaining cases)
88
+ // 2. Most-spoken languages by global user count (covers remaining cases)
91
89
  ['--write-subs', '--write-auto-subs', '--sub-langs', 'zh-Hans,zh,ja,ko,fr,de,es,pt,hi,ar,ru'],
92
90
  ];
93
91
  async function ytDlpTranscript(url, videoId) {
@@ -139,25 +137,56 @@ async function ytDlpTranscript(url, videoId) {
139
137
  return null;
140
138
  }
141
139
  };
142
- // Phase 1: find a working browser cookie source using the first subtitle strategy.
143
- // The result tells us both which browser works AND whether strategy 1 produced output.
140
+ // Phase 1: find a working browser cookie source AND detect native language in one call.
141
+ // --dump-json is lightweight (no download) and returns metadata including `language`.
144
142
  let cookieArgs = [];
143
+ let nativeLang = null;
145
144
  for (const browser of BROWSERS) {
146
- const outcome = await run(SUB_STRATEGIES[0], ['--cookies-from-browser', browser]);
145
+ try {
146
+ const { stdout } = await execFileAsync('yt-dlp', [
147
+ '--dump-json', '--no-playlist', '--quiet',
148
+ '--cookies-from-browser', browser, url,
149
+ ], { timeout: 15_000 });
150
+ cookieArgs = ['--cookies-from-browser', browser];
151
+ nativeLang = JSON.parse(stdout).language ?? null;
152
+ break;
153
+ }
154
+ catch (e) {
155
+ const err = e;
156
+ if (err.code === 'ENOENT')
157
+ return { transcript: null, reason: 'not-installed' };
158
+ const stderr = err.stderr ?? '';
159
+ if (stderr.includes('Could not find') || stderr.includes('cookies from browser'))
160
+ continue;
161
+ // Other errors (bot-detection without cookies, etc.) — stop trying browsers
162
+ break;
163
+ }
164
+ }
165
+ // If no browser worked, try cookie-less metadata fetch for language detection.
166
+ if (!cookieArgs.length) {
167
+ try {
168
+ const { stdout } = await execFileAsync('yt-dlp', [
169
+ '--dump-json', '--no-playlist', '--quiet', url,
170
+ ], { timeout: 15_000 });
171
+ nativeLang = JSON.parse(stdout).language ?? null;
172
+ }
173
+ catch (e) {
174
+ const err = e;
175
+ if (err.code === 'ENOENT')
176
+ return { transcript: null, reason: 'not-installed' };
177
+ }
178
+ }
179
+ // Phase 2: try native language subtitles first (most accurate).
180
+ if (nativeLang) {
181
+ const outcome = await run(['--write-subs', '--write-auto-subs', '--sub-langs', nativeLang], cookieArgs);
147
182
  if (outcome === 'not-installed')
148
183
  return { transcript: null, reason: 'not-installed' };
149
- if (outcome === 'cookie-error')
150
- continue; // browser not available, try next
151
- cookieArgs = ['--cookies-from-browser', browser];
152
- break;
184
+ const t = readAndClean();
185
+ if (t)
186
+ return { transcript: t };
153
187
  }
154
- // cookieArgs is empty if no browser found — fall back to cookie-less requests
155
- // Check if strategy 1 produced output
156
- const t1 = readAndClean();
157
- if (t1)
158
- return { transcript: t1 };
159
- // Phase 2: try remaining subtitle strategies with the confirmed cookie source
160
- for (const subArgs of SUB_STRATEGIES.slice(1)) {
188
+ // Phase 3: fallback strategies with the confirmed cookie source.
189
+ for (const subArgs of SUB_FALLBACKS) {
161
190
  const outcome = await run(subArgs, cookieArgs);
162
191
  if (outcome === 'not-installed')
163
192
  return { transcript: null, reason: 'not-installed' };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "summd",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "CLI for sum.md — Sum to anything.",
5
5
  "license": "MIT",
6
6
  "bin": {