@steipete/summarize-core 0.10.0 → 0.11.1
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 +0 -1
- package/dist/esm/content/index.js +5 -5
- package/dist/esm/content/index.js.map +1 -1
- package/dist/esm/content/link-preview/client.js +20 -9
- package/dist/esm/content/link-preview/client.js.map +1 -1
- package/dist/esm/content/link-preview/content/article.js +84 -83
- package/dist/esm/content/link-preview/content/article.js.map +1 -1
- package/dist/esm/content/link-preview/content/cleaner.js +23 -20
- package/dist/esm/content/link-preview/content/cleaner.js.map +1 -1
- package/dist/esm/content/link-preview/content/constants.js.map +1 -1
- package/dist/esm/content/link-preview/content/fetcher.js +46 -40
- package/dist/esm/content/link-preview/content/fetcher.js.map +1 -1
- package/dist/esm/content/link-preview/content/firecrawl.js +16 -16
- package/dist/esm/content/link-preview/content/firecrawl.js.map +1 -1
- package/dist/esm/content/link-preview/content/html.js +29 -27
- package/dist/esm/content/link-preview/content/html.js.map +1 -1
- package/dist/esm/content/link-preview/content/index.js +141 -88
- package/dist/esm/content/link-preview/content/index.js.map +1 -1
- package/dist/esm/content/link-preview/content/jsonld.js +12 -12
- package/dist/esm/content/link-preview/content/jsonld.js.map +1 -1
- package/dist/esm/content/link-preview/content/parsers.js +20 -20
- package/dist/esm/content/link-preview/content/parsers.js.map +1 -1
- package/dist/esm/content/link-preview/content/podcast-utils.js +34 -34
- package/dist/esm/content/link-preview/content/podcast-utils.js.map +1 -1
- package/dist/esm/content/link-preview/content/readability.js +16 -15
- package/dist/esm/content/link-preview/content/readability.js.map +1 -1
- package/dist/esm/content/link-preview/content/twitter-utils.js +24 -11
- package/dist/esm/content/link-preview/content/twitter-utils.js.map +1 -1
- package/dist/esm/content/link-preview/content/types.js +1 -1
- package/dist/esm/content/link-preview/content/types.js.map +1 -1
- package/dist/esm/content/link-preview/content/utils.js +17 -17
- package/dist/esm/content/link-preview/content/utils.js.map +1 -1
- package/dist/esm/content/link-preview/content/video.js +19 -19
- package/dist/esm/content/link-preview/content/video.js.map +1 -1
- package/dist/esm/content/link-preview/content/visibility.js +121 -0
- package/dist/esm/content/link-preview/content/visibility.js.map +1 -0
- package/dist/esm/content/link-preview/content/youtube.js +10 -10
- package/dist/esm/content/link-preview/content/youtube.js.map +1 -1
- package/dist/esm/content/link-preview/deps.js +16 -16
- package/dist/esm/content/link-preview/deps.js.map +1 -1
- package/dist/esm/content/link-preview/fetch-with-timeout.js +4 -4
- package/dist/esm/content/link-preview/fetch-with-timeout.js.map +1 -1
- package/dist/esm/content/link-preview/types.js +1 -1
- package/dist/esm/content/link-preview/types.js.map +1 -1
- package/dist/esm/content/transcript/cache.js +22 -22
- package/dist/esm/content/transcript/cache.js.map +1 -1
- package/dist/esm/content/transcript/index.js +34 -24
- package/dist/esm/content/transcript/index.js.map +1 -1
- package/dist/esm/content/transcript/normalize.js +10 -10
- package/dist/esm/content/transcript/normalize.js.map +1 -1
- package/dist/esm/content/transcript/parse.js +31 -31
- package/dist/esm/content/transcript/parse.js.map +1 -1
- package/dist/esm/content/transcript/providers/generic.js +74 -78
- package/dist/esm/content/transcript/providers/generic.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/apple-flow.js +36 -36
- package/dist/esm/content/transcript/providers/podcast/apple-flow.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/apple.js +5 -5
- package/dist/esm/content/transcript/providers/podcast/apple.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/constants.js +2 -2
- package/dist/esm/content/transcript/providers/podcast/constants.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/itunes.js +44 -42
- package/dist/esm/content/transcript/providers/podcast/itunes.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/json.js +4 -4
- package/dist/esm/content/transcript/providers/podcast/json.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/media.js +58 -49
- package/dist/esm/content/transcript/providers/podcast/media.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/results.js +2 -2
- package/dist/esm/content/transcript/providers/podcast/results.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/rss.js +29 -29
- package/dist/esm/content/transcript/providers/podcast/rss.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/spotify-flow.js +38 -38
- package/dist/esm/content/transcript/providers/podcast/spotify-flow.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast/spotify.js +32 -32
- package/dist/esm/content/transcript/providers/podcast/spotify.js.map +1 -1
- package/dist/esm/content/transcript/providers/podcast.js +43 -47
- package/dist/esm/content/transcript/providers/podcast.js.map +1 -1
- package/dist/esm/content/transcript/providers/transcription-start.js +59 -31
- package/dist/esm/content/transcript/providers/transcription-start.js.map +1 -1
- package/dist/esm/content/transcript/providers/youtube/api.js +56 -56
- package/dist/esm/content/transcript/providers/youtube/api.js.map +1 -1
- package/dist/esm/content/transcript/providers/youtube/apify.js +7 -7
- package/dist/esm/content/transcript/providers/youtube/apify.js.map +1 -1
- package/dist/esm/content/transcript/providers/youtube/captions.js +76 -76
- package/dist/esm/content/transcript/providers/youtube/captions.js.map +1 -1
- package/dist/esm/content/transcript/providers/youtube/yt-dlp.js +82 -75
- package/dist/esm/content/transcript/providers/youtube/yt-dlp.js.map +1 -1
- package/dist/esm/content/transcript/providers/youtube.js +84 -77
- package/dist/esm/content/transcript/providers/youtube.js.map +1 -1
- package/dist/esm/content/transcript/timestamps.js +8 -8
- package/dist/esm/content/transcript/timestamps.js.map +1 -1
- package/dist/esm/content/transcript/transcription-config.js +14 -0
- package/dist/esm/content/transcript/transcription-config.js.map +1 -0
- package/dist/esm/content/transcript/utils.js +35 -35
- package/dist/esm/content/transcript/utils.js.map +1 -1
- package/dist/esm/content/url.js +59 -28
- package/dist/esm/content/url.js.map +1 -1
- package/dist/esm/index.js +4 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/language.js +77 -77
- package/dist/esm/language.js.map +1 -1
- package/dist/esm/openai/base-url.js +35 -0
- package/dist/esm/openai/base-url.js.map +1 -0
- package/dist/esm/processes.js +16 -16
- package/dist/esm/processes.js.map +1 -1
- package/dist/esm/prompts/cli.js +17 -17
- package/dist/esm/prompts/cli.js.map +1 -1
- package/dist/esm/prompts/file.js +54 -54
- package/dist/esm/prompts/file.js.map +1 -1
- package/dist/esm/prompts/format.js +2 -2
- package/dist/esm/prompts/format.js.map +1 -1
- package/dist/esm/prompts/index.js +5 -5
- package/dist/esm/prompts/index.js.map +1 -1
- package/dist/esm/prompts/link-summary.js +65 -65
- package/dist/esm/prompts/link-summary.js.map +1 -1
- package/dist/esm/prompts/summary-lengths.js +10 -10
- package/dist/esm/prompts/summary-lengths.js.map +1 -1
- package/dist/esm/prompts/summary-system.js +9 -9
- package/dist/esm/prompts/summary-system.js.map +1 -1
- package/dist/esm/shared/contracts.js +1 -1
- package/dist/esm/shared/contracts.js.map +1 -1
- package/dist/esm/transcription/onnx-cli.js +69 -69
- package/dist/esm/transcription/onnx-cli.js.map +1 -1
- package/dist/esm/transcription/whisper/constants.js +3 -3
- package/dist/esm/transcription/whisper/constants.js.map +1 -1
- package/dist/esm/transcription/whisper/core.js +148 -59
- package/dist/esm/transcription/whisper/core.js.map +1 -1
- package/dist/esm/transcription/whisper/fal.js +14 -14
- package/dist/esm/transcription/whisper/fal.js.map +1 -1
- package/dist/esm/transcription/whisper/ffmpeg.js +106 -106
- package/dist/esm/transcription/whisper/ffmpeg.js.map +1 -1
- package/dist/esm/transcription/whisper/groq.js +46 -0
- package/dist/esm/transcription/whisper/groq.js.map +1 -0
- package/dist/esm/transcription/whisper/openai.js +19 -13
- package/dist/esm/transcription/whisper/openai.js.map +1 -1
- package/dist/esm/transcription/whisper/utils.js +19 -19
- package/dist/esm/transcription/whisper/utils.js.map +1 -1
- package/dist/esm/transcription/whisper/whisper-cpp.js +64 -64
- package/dist/esm/transcription/whisper/whisper-cpp.js.map +1 -1
- package/dist/esm/transcription/whisper.js +4 -4
- package/dist/esm/transcription/whisper.js.map +1 -1
- package/dist/types/content/cache/types.d.ts +1 -1
- package/dist/types/content/index.d.ts +7 -7
- package/dist/types/content/link-preview/client.d.ts +7 -4
- package/dist/types/content/link-preview/content/cleaner.d.ts +1 -0
- package/dist/types/content/link-preview/content/fetcher.d.ts +2 -2
- package/dist/types/content/link-preview/content/firecrawl.d.ts +7 -7
- package/dist/types/content/link-preview/content/html.d.ts +8 -8
- package/dist/types/content/link-preview/content/index.d.ts +3 -3
- package/dist/types/content/link-preview/content/twitter-utils.d.ts +1 -0
- package/dist/types/content/link-preview/content/types.d.ts +8 -8
- package/dist/types/content/link-preview/content/utils.d.ts +3 -3
- package/dist/types/content/link-preview/content/video.d.ts +1 -1
- package/dist/types/content/link-preview/content/visibility.d.ts +1 -0
- package/dist/types/content/link-preview/deps.d.ts +36 -33
- package/dist/types/content/link-preview/types.d.ts +4 -4
- package/dist/types/content/transcript/cache.d.ts +4 -4
- package/dist/types/content/transcript/index.d.ts +7 -7
- package/dist/types/content/transcript/parse.d.ts +1 -1
- package/dist/types/content/transcript/providers/generic.d.ts +1 -1
- package/dist/types/content/transcript/providers/podcast/apple-flow.d.ts +2 -2
- package/dist/types/content/transcript/providers/podcast/flow-context.d.ts +4 -4
- package/dist/types/content/transcript/providers/podcast/media.d.ts +9 -6
- package/dist/types/content/transcript/providers/podcast/results.d.ts +3 -3
- package/dist/types/content/transcript/providers/podcast/rss.d.ts +1 -1
- package/dist/types/content/transcript/providers/podcast/spotify-flow.d.ts +2 -2
- package/dist/types/content/transcript/providers/podcast/spotify.d.ts +2 -2
- package/dist/types/content/transcript/providers/podcast.d.ts +5 -5
- package/dist/types/content/transcript/providers/transcription-start.d.ts +14 -8
- package/dist/types/content/transcript/providers/youtube/api.d.ts +1 -1
- package/dist/types/content/transcript/providers/youtube/captions.d.ts +1 -1
- package/dist/types/content/transcript/providers/youtube/yt-dlp.d.ts +11 -8
- package/dist/types/content/transcript/providers/youtube.d.ts +1 -1
- package/dist/types/content/transcript/timestamps.d.ts +1 -1
- package/dist/types/content/transcript/transcription-config.d.ts +15 -0
- package/dist/types/content/transcript/types.d.ts +12 -9
- package/dist/types/content/transcript/utils.d.ts +1 -1
- package/dist/types/content/url.d.ts +5 -3
- package/dist/types/index.d.ts +5 -4
- package/dist/types/language.d.ts +4 -4
- package/dist/types/openai/base-url.d.ts +14 -0
- package/dist/types/processes.d.ts +2 -2
- package/dist/types/prompts/cli.d.ts +3 -3
- package/dist/types/prompts/file.d.ts +2 -2
- package/dist/types/prompts/index.d.ts +6 -6
- package/dist/types/prompts/link-summary.d.ts +3 -3
- package/dist/types/prompts/summary-lengths.d.ts +1 -1
- package/dist/types/transcription/onnx-cli.d.ts +3 -3
- package/dist/types/transcription/whisper/core.d.ts +6 -3
- package/dist/types/transcription/whisper/groq.d.ts +2 -0
- package/dist/types/transcription/whisper/openai.d.ts +6 -1
- package/dist/types/transcription/whisper/types.d.ts +1 -1
- package/dist/types/transcription/whisper/whisper-cpp.d.ts +1 -1
- package/dist/types/transcription/whisper.d.ts +5 -5
- package/package.json +13 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apple-flow.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/apple-flow.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apple-flow.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/apple-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,11 +3,11 @@ export function extractAppleEpisodeTitleFromHtml(html) {
|
|
|
3
3
|
// Prefer `apple:title` (episode title only) to match RSS items.
|
|
4
4
|
const apple = html.match(/<meta\s+name=["']apple:title["']\s+content=["']([^"']+)["']/i)?.[1] ?? null;
|
|
5
5
|
const og = html.match(/<meta\s+property=["']og:title["']\s+content=["']([^"']+)["']/i)?.[1] ?? null;
|
|
6
|
-
const title = (apple ?? og ??
|
|
6
|
+
const title = (apple ?? og ?? "").trim();
|
|
7
7
|
return title.length > 0 ? title : null;
|
|
8
8
|
}
|
|
9
9
|
export function extractEmbeddedJsonUrl(html, field) {
|
|
10
|
-
const pattern = new RegExp(`"${field}":"((?:\\\\.|[^"\\\\])*)"`,
|
|
10
|
+
const pattern = new RegExp(`"${field}":"((?:\\\\.|[^"\\\\])*)"`, "i");
|
|
11
11
|
const match = html.match(pattern);
|
|
12
12
|
if (!match?.[1])
|
|
13
13
|
return null;
|
|
@@ -21,13 +21,13 @@ export function extractEmbeddedJsonUrl(html, field) {
|
|
|
21
21
|
export function extractApplePodcastIds(url) {
|
|
22
22
|
try {
|
|
23
23
|
const parsed = new URL(url);
|
|
24
|
-
const host = parsed.hostname.toLowerCase().replace(/^www\./,
|
|
25
|
-
if (host !==
|
|
24
|
+
const host = parsed.hostname.toLowerCase().replace(/^www\./, "");
|
|
25
|
+
if (host !== "podcasts.apple.com")
|
|
26
26
|
return null;
|
|
27
27
|
const showId = parsed.pathname.match(/\/id(\d+)(?:\/|$)/)?.[1] ?? null;
|
|
28
28
|
if (!showId)
|
|
29
29
|
return null;
|
|
30
|
-
const episodeIdRaw = parsed.searchParams.get(
|
|
30
|
+
const episodeIdRaw = parsed.searchParams.get("i");
|
|
31
31
|
const episodeId = episodeIdRaw && /^\d+$/.test(episodeIdRaw) ? episodeIdRaw : null;
|
|
32
32
|
return { showId, episodeId };
|
|
33
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apple.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/apple.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gCAAgC,CAAC,IAAY;IAC3D,8EAA8E;IAC9E,gEAAgE;IAChE,MAAM,KAAK,GACT,IAAI,CAAC,KAAK,CAAC,8DAA8D,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"apple.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/apple.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gCAAgC,CAAC,IAAY;IAC3D,8EAA8E;IAC9E,gEAAgE;IAChE,MAAM,KAAK,GACT,IAAI,CAAC,KAAK,CAAC,8DAA8D,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC1F,MAAM,EAAE,GACN,IAAI,CAAC,KAAK,CAAC,+DAA+D,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAC3F,MAAM,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACzC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,KAAa;IAChE,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,IAAI,KAAK,2BAA2B,EAAE,GAAG,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,CAAW,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,GAAW;IAEX,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACjE,IAAI,IAAI,KAAK,oBAAoB;YAAE,OAAO,IAAI,CAAC;QAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QACvE,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;QACnF,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -3,6 +3,6 @@ export const PODCAST_PLATFORM_HOST_PATTERN = /open\.spotify\.com|spotify\.com|po
|
|
|
3
3
|
export const TRANSCRIPTION_TIMEOUT_MS = 600_000;
|
|
4
4
|
export const MAX_REMOTE_MEDIA_BYTES = 512 * 1024 * 1024;
|
|
5
5
|
export const BLOCKED_HTML_HINT_PATTERN = /access denied|attention required|captcha|recaptcha|cloudflare|forbidden|verify you are human/i;
|
|
6
|
-
export const ITUNES_SEARCH_URL =
|
|
7
|
-
export const ITUNES_LOOKUP_URL =
|
|
6
|
+
export const ITUNES_SEARCH_URL = "https://itunes.apple.com/search";
|
|
7
|
+
export const ITUNES_LOOKUP_URL = "https://itunes.apple.com/lookup";
|
|
8
8
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,iCAAiC,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,iCAAiC,CAAC;AACvE,MAAM,CAAC,MAAM,6BAA6B,GACxC,6GAA6G,CAAC;AAChH,MAAM,CAAC,MAAM,wBAAwB,GAAG,OAAO,CAAC;AAChD,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AACxD,MAAM,CAAC,MAAM,yBAAyB,GACpC,+FAA+F,CAAC;AAClG,MAAM,CAAC,MAAM,iBAAiB,GAAG,iCAAiC,CAAC;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAG,iCAAiC,CAAC"}
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { ITUNES_LOOKUP_URL, ITUNES_SEARCH_URL, TRANSCRIPTION_TIMEOUT_MS } from
|
|
2
|
-
import { asRecordArray, getJsonArray, getRecordString } from
|
|
3
|
-
import { normalizeLooseTitle } from
|
|
1
|
+
import { ITUNES_LOOKUP_URL, ITUNES_SEARCH_URL, TRANSCRIPTION_TIMEOUT_MS } from "./constants.js";
|
|
2
|
+
import { asRecordArray, getJsonArray, getRecordString } from "./json.js";
|
|
3
|
+
import { normalizeLooseTitle } from "./rss.js";
|
|
4
4
|
export async function resolveApplePodcastEpisodeFromItunesLookup({ fetchImpl, showId, episodeId, }) {
|
|
5
5
|
const query = new URLSearchParams({
|
|
6
6
|
id: showId,
|
|
7
|
-
entity:
|
|
8
|
-
limit:
|
|
7
|
+
entity: "podcastEpisode",
|
|
8
|
+
limit: "200",
|
|
9
9
|
});
|
|
10
10
|
const res = await fetchImpl(`${ITUNES_LOOKUP_URL}?${query.toString()}`, {
|
|
11
|
-
redirect:
|
|
11
|
+
redirect: "follow",
|
|
12
12
|
signal: AbortSignal.timeout(TRANSCRIPTION_TIMEOUT_MS),
|
|
13
|
-
headers: { accept:
|
|
13
|
+
headers: { accept: "application/json" },
|
|
14
14
|
});
|
|
15
15
|
if (!res.ok)
|
|
16
16
|
return null;
|
|
17
17
|
const payload = (await res.json());
|
|
18
|
-
const results = asRecordArray(getJsonArray(payload, [
|
|
19
|
-
const show = results.find((r) => getRecordString(r,
|
|
20
|
-
const feedUrl = typeof show?.feedUrl ===
|
|
21
|
-
const episodes = results.filter((r) => getRecordString(r,
|
|
18
|
+
const results = asRecordArray(getJsonArray(payload, ["results"]));
|
|
19
|
+
const show = results.find((r) => getRecordString(r, "wrapperType") === "track" && getRecordString(r, "kind") === "podcast");
|
|
20
|
+
const feedUrl = typeof show?.feedUrl === "string" && show.feedUrl.trim() ? show.feedUrl.trim() : null;
|
|
21
|
+
const episodes = results.filter((r) => getRecordString(r, "wrapperType") === "podcastEpisode");
|
|
22
22
|
if (episodes.length === 0)
|
|
23
23
|
return null;
|
|
24
24
|
const chosen = (() => {
|
|
25
25
|
if (episodeId) {
|
|
26
|
-
const match = episodes.find((r) => String(r.trackId ??
|
|
26
|
+
const match = episodes.find((r) => String(r.trackId ?? "") === episodeId);
|
|
27
27
|
if (match)
|
|
28
28
|
return match;
|
|
29
29
|
}
|
|
30
30
|
// No i=... in URL: pick the newest episode by release date.
|
|
31
31
|
const sorted = [...episodes].sort((a, b) => {
|
|
32
|
-
const aDate = Date.parse(String(a.releaseDate ??
|
|
33
|
-
const bDate = Date.parse(String(b.releaseDate ??
|
|
32
|
+
const aDate = Date.parse(String(a.releaseDate ?? ""));
|
|
33
|
+
const bDate = Date.parse(String(b.releaseDate ?? ""));
|
|
34
34
|
if (!Number.isFinite(aDate) && !Number.isFinite(bDate))
|
|
35
35
|
return 0;
|
|
36
36
|
if (!Number.isFinite(aDate))
|
|
@@ -41,74 +41,76 @@ export async function resolveApplePodcastEpisodeFromItunesLookup({ fetchImpl, sh
|
|
|
41
41
|
});
|
|
42
42
|
return sorted[0];
|
|
43
43
|
})();
|
|
44
|
-
const episodeUrlRaw = typeof chosen.episodeUrl ===
|
|
44
|
+
const episodeUrlRaw = typeof chosen.episodeUrl === "string"
|
|
45
45
|
? chosen.episodeUrl.trim()
|
|
46
|
-
: typeof chosen.previewUrl ===
|
|
46
|
+
: typeof chosen.previewUrl === "string"
|
|
47
47
|
? chosen.previewUrl.trim()
|
|
48
|
-
:
|
|
48
|
+
: "";
|
|
49
49
|
if (!episodeUrlRaw || !/^https?:\/\//i.test(episodeUrlRaw))
|
|
50
50
|
return null;
|
|
51
|
-
const fileExtension = typeof chosen.episodeFileExtension ===
|
|
52
|
-
? chosen.episodeFileExtension.trim().replace(/^\./,
|
|
51
|
+
const fileExtension = typeof chosen.episodeFileExtension === "string" && chosen.episodeFileExtension.trim()
|
|
52
|
+
? chosen.episodeFileExtension.trim().replace(/^\./, "")
|
|
53
53
|
: null;
|
|
54
|
-
const durationSeconds = typeof chosen.trackTimeMillis ===
|
|
54
|
+
const durationSeconds = typeof chosen.trackTimeMillis === "number" && Number.isFinite(chosen.trackTimeMillis)
|
|
55
55
|
? chosen.trackTimeMillis / 1000
|
|
56
56
|
: null;
|
|
57
|
-
const episodeTitle = typeof chosen.trackName ===
|
|
57
|
+
const episodeTitle = typeof chosen.trackName === "string" && chosen.trackName.trim()
|
|
58
|
+
? chosen.trackName.trim()
|
|
59
|
+
: null;
|
|
58
60
|
return { episodeUrl: episodeUrlRaw, feedUrl, fileExtension, durationSeconds, episodeTitle };
|
|
59
61
|
}
|
|
60
62
|
export async function resolvePodcastFeedUrlFromItunesSearch(fetchImpl, showTitle) {
|
|
61
63
|
const query = new URLSearchParams({
|
|
62
64
|
term: showTitle,
|
|
63
|
-
media:
|
|
64
|
-
entity:
|
|
65
|
-
limit:
|
|
65
|
+
media: "podcast",
|
|
66
|
+
entity: "podcast",
|
|
67
|
+
limit: "10",
|
|
66
68
|
});
|
|
67
69
|
const res = await fetchImpl(`${ITUNES_SEARCH_URL}?${query.toString()}`, {
|
|
68
|
-
redirect:
|
|
70
|
+
redirect: "follow",
|
|
69
71
|
signal: AbortSignal.timeout(TRANSCRIPTION_TIMEOUT_MS),
|
|
70
|
-
headers: { accept:
|
|
72
|
+
headers: { accept: "application/json" },
|
|
71
73
|
});
|
|
72
74
|
if (!res.ok) {
|
|
73
75
|
return null;
|
|
74
76
|
}
|
|
75
77
|
const payload = (await res.json());
|
|
76
|
-
const results = asRecordArray(getJsonArray(payload, [
|
|
78
|
+
const results = asRecordArray(getJsonArray(payload, ["results"]));
|
|
77
79
|
if (results.length === 0)
|
|
78
80
|
return null;
|
|
79
81
|
const normalizedTarget = normalizeLooseTitle(showTitle);
|
|
80
|
-
const exact = results.find((r) => normalizeLooseTitle(String(r.collectionName ??
|
|
82
|
+
const exact = results.find((r) => normalizeLooseTitle(String(r.collectionName ?? "")) === normalizedTarget);
|
|
81
83
|
const best = exact ?? results[0];
|
|
82
|
-
const feedUrl = typeof best?.feedUrl ===
|
|
84
|
+
const feedUrl = typeof best?.feedUrl === "string" ? best.feedUrl.trim() : "";
|
|
83
85
|
return feedUrl && /^https?:\/\//i.test(feedUrl) ? feedUrl : null;
|
|
84
86
|
}
|
|
85
87
|
export async function resolvePodcastEpisodeFromItunesSearch(fetchImpl, showTitle, episodeTitle) {
|
|
86
88
|
const query = new URLSearchParams({
|
|
87
89
|
term: `${showTitle} ${episodeTitle}`,
|
|
88
|
-
media:
|
|
89
|
-
entity:
|
|
90
|
-
limit:
|
|
90
|
+
media: "podcast",
|
|
91
|
+
entity: "podcastEpisode",
|
|
92
|
+
limit: "25",
|
|
91
93
|
});
|
|
92
94
|
const res = await fetchImpl(`${ITUNES_SEARCH_URL}?${query.toString()}`, {
|
|
93
|
-
redirect:
|
|
95
|
+
redirect: "follow",
|
|
94
96
|
signal: AbortSignal.timeout(TRANSCRIPTION_TIMEOUT_MS),
|
|
95
|
-
headers: { accept:
|
|
97
|
+
headers: { accept: "application/json" },
|
|
96
98
|
});
|
|
97
99
|
if (!res.ok)
|
|
98
100
|
return null;
|
|
99
101
|
const payload = (await res.json());
|
|
100
|
-
const results = asRecordArray(getJsonArray(payload, [
|
|
102
|
+
const results = asRecordArray(getJsonArray(payload, ["results"]));
|
|
101
103
|
if (results.length === 0)
|
|
102
104
|
return null;
|
|
103
105
|
const normalizedShow = normalizeLooseTitle(showTitle);
|
|
104
106
|
const normalizedEpisode = normalizeLooseTitle(episodeTitle);
|
|
105
107
|
const candidates = results
|
|
106
108
|
.map((record) => {
|
|
107
|
-
const title = getRecordString(record,
|
|
108
|
-
const collection = getRecordString(record,
|
|
109
|
-
const episodeUrl = getRecordString(record,
|
|
109
|
+
const title = getRecordString(record, "trackName");
|
|
110
|
+
const collection = getRecordString(record, "collectionName");
|
|
111
|
+
const episodeUrl = getRecordString(record, "episodeUrl");
|
|
110
112
|
const durationMs = record.trackTimeMillis;
|
|
111
|
-
const durationSeconds = typeof durationMs ===
|
|
113
|
+
const durationSeconds = typeof durationMs === "number" && Number.isFinite(durationMs) ? durationMs / 1000 : null;
|
|
112
114
|
return {
|
|
113
115
|
title,
|
|
114
116
|
collection,
|
|
@@ -119,9 +121,9 @@ export async function resolvePodcastEpisodeFromItunesSearch(fetchImpl, showTitle
|
|
|
119
121
|
.filter((entry) => Boolean(entry.episodeUrl) && Boolean(entry.title));
|
|
120
122
|
if (candidates.length === 0)
|
|
121
123
|
return null;
|
|
122
|
-
const exact = candidates.find((entry) => normalizeLooseTitle(entry.title ??
|
|
123
|
-
normalizeLooseTitle(entry.collection ??
|
|
124
|
-
const exactEpisode = candidates.find((entry) => normalizeLooseTitle(entry.title ??
|
|
124
|
+
const exact = candidates.find((entry) => normalizeLooseTitle(entry.title ?? "") === normalizedEpisode &&
|
|
125
|
+
normalizeLooseTitle(entry.collection ?? "") === normalizedShow);
|
|
126
|
+
const exactEpisode = candidates.find((entry) => normalizeLooseTitle(entry.title ?? "") === normalizedEpisode);
|
|
125
127
|
const best = exact ?? exactEpisode ?? candidates[0];
|
|
126
128
|
if (!best?.episodeUrl)
|
|
127
129
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"itunes.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/itunes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"itunes.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/itunes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export function isJsonRecord(value) {
|
|
2
|
-
return typeof value ===
|
|
2
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
3
|
}
|
|
4
4
|
export function getJsonPath(value, path) {
|
|
5
5
|
let current = value;
|
|
@@ -12,11 +12,11 @@ export function getJsonPath(value, path) {
|
|
|
12
12
|
}
|
|
13
13
|
export function getJsonString(value, path) {
|
|
14
14
|
const found = getJsonPath(value, path);
|
|
15
|
-
return typeof found ===
|
|
15
|
+
return typeof found === "string" ? found : null;
|
|
16
16
|
}
|
|
17
17
|
export function getJsonNumber(value, path) {
|
|
18
18
|
const found = getJsonPath(value, path);
|
|
19
|
-
return typeof found ===
|
|
19
|
+
return typeof found === "number" && Number.isFinite(found) ? found : null;
|
|
20
20
|
}
|
|
21
21
|
export function getJsonArray(value, path) {
|
|
22
22
|
const found = getJsonPath(value, path);
|
|
@@ -29,6 +29,6 @@ export function asRecordArray(value) {
|
|
|
29
29
|
}
|
|
30
30
|
export function getRecordString(record, key) {
|
|
31
31
|
const value = record[key];
|
|
32
|
-
return typeof value ===
|
|
32
|
+
return typeof value === "string" ? value : null;
|
|
33
33
|
}
|
|
34
34
|
//# sourceMappingURL=json.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../../../../../src/content/transcript/providers/podcast/json.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,IAAuB;IACjE,IAAI,OAAO,GAAY,KAAK,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC;YAAE,OAAO,SAAS,CAAC;QAC7C,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,IAAuB;IACnE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACvC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc,EAAE,IAAuB;IACnE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACvC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAc,EAAE,IAAuB;IAClE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACvC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAmB,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAkB,EAAE,GAAW;IAC7D,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC"}
|
|
@@ -1,57 +1,63 @@
|
|
|
1
|
-
import { randomUUID } from
|
|
2
|
-
import { promises as fs } from
|
|
3
|
-
import { tmpdir } from
|
|
4
|
-
import { join } from
|
|
5
|
-
import { isFfmpegAvailable, MAX_OPENAI_UPLOAD_BYTES, probeMediaDurationSecondsWithFfprobe, transcribeMediaFileWithWhisper, transcribeMediaWithWhisper, } from
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { promises as fs } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { isFfmpegAvailable, MAX_OPENAI_UPLOAD_BYTES, probeMediaDurationSecondsWithFfprobe, transcribeMediaFileWithWhisper, transcribeMediaWithWhisper, } from "../../../../transcription/whisper.js";
|
|
6
|
+
import { resolveTranscriptionConfig, } from "../../transcription-config.js";
|
|
7
|
+
import { resolveTranscriptionStartInfo } from "../transcription-start.js";
|
|
8
|
+
import { MAX_REMOTE_MEDIA_BYTES, TRANSCRIPTION_TIMEOUT_MS } from "./constants.js";
|
|
9
|
+
export async function transcribeMediaUrl({ fetchImpl, transcription, env, url, filenameHint, durationSecondsHint, groqApiKey, openaiApiKey, falApiKey, notes, progress, }) {
|
|
9
10
|
const canChunk = await isFfmpegAvailable();
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const effectiveTranscription = resolveTranscriptionConfig({
|
|
12
|
+
env,
|
|
13
|
+
transcription,
|
|
14
|
+
groqApiKey,
|
|
13
15
|
openaiApiKey,
|
|
14
16
|
falApiKey,
|
|
15
17
|
});
|
|
18
|
+
const effectiveEnv = effectiveTranscription.env ?? process.env;
|
|
19
|
+
const startInfo = await resolveTranscriptionStartInfo({
|
|
20
|
+
transcription: effectiveTranscription,
|
|
21
|
+
});
|
|
16
22
|
const providerHint = startInfo.providerHint;
|
|
17
23
|
const modelId = startInfo.modelId;
|
|
18
24
|
const head = await probeRemoteMedia(fetchImpl, url);
|
|
19
25
|
if (head.contentLength !== null && head.contentLength > MAX_REMOTE_MEDIA_BYTES) {
|
|
20
26
|
throw new Error(`Remote media too large (${formatBytes(head.contentLength)}). Limit is ${formatBytes(MAX_REMOTE_MEDIA_BYTES)}.`);
|
|
21
27
|
}
|
|
22
|
-
const mediaType = head.mediaType ??
|
|
28
|
+
const mediaType = head.mediaType ?? "application/octet-stream";
|
|
23
29
|
const filename = head.filename ?? filenameHint;
|
|
24
30
|
const totalBytes = head.contentLength;
|
|
25
31
|
progress?.onProgress?.({
|
|
26
|
-
kind:
|
|
32
|
+
kind: "transcript-media-download-start",
|
|
27
33
|
url: progress.url,
|
|
28
34
|
service: progress.service,
|
|
29
35
|
mediaUrl: url,
|
|
30
|
-
mediaKind:
|
|
36
|
+
mediaKind: "audio",
|
|
31
37
|
totalBytes,
|
|
32
38
|
});
|
|
33
39
|
if (!canChunk) {
|
|
34
40
|
const bytes = await downloadCappedBytes(fetchImpl, url, MAX_OPENAI_UPLOAD_BYTES, {
|
|
35
41
|
totalBytes,
|
|
36
42
|
onProgress: (downloadedBytes) => progress?.onProgress?.({
|
|
37
|
-
kind:
|
|
43
|
+
kind: "transcript-media-download-progress",
|
|
38
44
|
url: progress.url,
|
|
39
45
|
service: progress.service,
|
|
40
46
|
downloadedBytes,
|
|
41
47
|
totalBytes,
|
|
42
|
-
mediaKind:
|
|
48
|
+
mediaKind: "audio",
|
|
43
49
|
}),
|
|
44
50
|
});
|
|
45
51
|
progress?.onProgress?.({
|
|
46
|
-
kind:
|
|
52
|
+
kind: "transcript-media-download-done",
|
|
47
53
|
url: progress.url,
|
|
48
54
|
service: progress.service,
|
|
49
55
|
downloadedBytes: bytes.byteLength,
|
|
50
56
|
totalBytes,
|
|
51
|
-
mediaKind:
|
|
57
|
+
mediaKind: "audio",
|
|
52
58
|
});
|
|
53
59
|
progress?.onProgress?.({
|
|
54
|
-
kind:
|
|
60
|
+
kind: "transcript-whisper-start",
|
|
55
61
|
url: progress.url,
|
|
56
62
|
service: progress.service,
|
|
57
63
|
providerHint,
|
|
@@ -64,13 +70,14 @@ export async function transcribeMediaUrl({ fetchImpl, env, url, filenameHint, du
|
|
|
64
70
|
bytes,
|
|
65
71
|
mediaType,
|
|
66
72
|
filename,
|
|
67
|
-
|
|
68
|
-
|
|
73
|
+
groqApiKey: effectiveTranscription.groqApiKey,
|
|
74
|
+
openaiApiKey: effectiveTranscription.openaiApiKey,
|
|
75
|
+
falApiKey: effectiveTranscription.falApiKey,
|
|
69
76
|
totalDurationSeconds: durationSecondsHint,
|
|
70
77
|
env: effectiveEnv,
|
|
71
78
|
onProgress: (event) => {
|
|
72
79
|
progress?.onProgress?.({
|
|
73
|
-
kind:
|
|
80
|
+
kind: "transcript-whisper-progress",
|
|
74
81
|
url: progress.url,
|
|
75
82
|
service: progress.service,
|
|
76
83
|
processedDurationSeconds: event.processedDurationSeconds,
|
|
@@ -88,24 +95,24 @@ export async function transcribeMediaUrl({ fetchImpl, env, url, filenameHint, du
|
|
|
88
95
|
const bytes = await downloadCappedBytes(fetchImpl, url, MAX_OPENAI_UPLOAD_BYTES, {
|
|
89
96
|
totalBytes,
|
|
90
97
|
onProgress: (downloadedBytes) => progress?.onProgress?.({
|
|
91
|
-
kind:
|
|
98
|
+
kind: "transcript-media-download-progress",
|
|
92
99
|
url: progress.url,
|
|
93
100
|
service: progress.service,
|
|
94
101
|
downloadedBytes,
|
|
95
102
|
totalBytes,
|
|
96
|
-
mediaKind:
|
|
103
|
+
mediaKind: "audio",
|
|
97
104
|
}),
|
|
98
105
|
});
|
|
99
106
|
progress?.onProgress?.({
|
|
100
|
-
kind:
|
|
107
|
+
kind: "transcript-media-download-done",
|
|
101
108
|
url: progress.url,
|
|
102
109
|
service: progress.service,
|
|
103
110
|
downloadedBytes: bytes.byteLength,
|
|
104
111
|
totalBytes,
|
|
105
|
-
mediaKind:
|
|
112
|
+
mediaKind: "audio",
|
|
106
113
|
});
|
|
107
114
|
progress?.onProgress?.({
|
|
108
|
-
kind:
|
|
115
|
+
kind: "transcript-whisper-start",
|
|
109
116
|
url: progress.url,
|
|
110
117
|
service: progress.service,
|
|
111
118
|
providerHint,
|
|
@@ -117,13 +124,14 @@ export async function transcribeMediaUrl({ fetchImpl, env, url, filenameHint, du
|
|
|
117
124
|
bytes,
|
|
118
125
|
mediaType,
|
|
119
126
|
filename,
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
groqApiKey: effectiveTranscription.groqApiKey,
|
|
128
|
+
openaiApiKey: effectiveTranscription.openaiApiKey,
|
|
129
|
+
falApiKey: effectiveTranscription.falApiKey,
|
|
122
130
|
totalDurationSeconds: durationSecondsHint,
|
|
123
131
|
env: effectiveEnv,
|
|
124
132
|
onProgress: (event) => {
|
|
125
133
|
progress?.onProgress?.({
|
|
126
|
-
kind:
|
|
134
|
+
kind: "transcript-whisper-progress",
|
|
127
135
|
url: progress.url,
|
|
128
136
|
service: progress.service,
|
|
129
137
|
processedDurationSeconds: event.processedDurationSeconds,
|
|
@@ -142,25 +150,25 @@ export async function transcribeMediaUrl({ fetchImpl, env, url, filenameHint, du
|
|
|
142
150
|
const downloadedBytes = await downloadToFile(fetchImpl, url, tmpFile, {
|
|
143
151
|
totalBytes,
|
|
144
152
|
onProgress: (nextDownloadedBytes) => progress?.onProgress?.({
|
|
145
|
-
kind:
|
|
153
|
+
kind: "transcript-media-download-progress",
|
|
146
154
|
url: progress.url,
|
|
147
155
|
service: progress.service,
|
|
148
156
|
downloadedBytes: nextDownloadedBytes,
|
|
149
157
|
totalBytes,
|
|
150
|
-
mediaKind:
|
|
158
|
+
mediaKind: "audio",
|
|
151
159
|
}),
|
|
152
160
|
});
|
|
153
161
|
progress?.onProgress?.({
|
|
154
|
-
kind:
|
|
162
|
+
kind: "transcript-media-download-done",
|
|
155
163
|
url: progress.url,
|
|
156
164
|
service: progress.service,
|
|
157
165
|
downloadedBytes,
|
|
158
166
|
totalBytes,
|
|
159
|
-
mediaKind:
|
|
167
|
+
mediaKind: "audio",
|
|
160
168
|
});
|
|
161
169
|
const probedDurationSeconds = durationSecondsHint ?? (await probeMediaDurationSecondsWithFfprobe(tmpFile));
|
|
162
170
|
progress?.onProgress?.({
|
|
163
|
-
kind:
|
|
171
|
+
kind: "transcript-whisper-start",
|
|
164
172
|
url: progress.url,
|
|
165
173
|
service: progress.service,
|
|
166
174
|
providerHint,
|
|
@@ -172,13 +180,14 @@ export async function transcribeMediaUrl({ fetchImpl, env, url, filenameHint, du
|
|
|
172
180
|
filePath: tmpFile,
|
|
173
181
|
mediaType,
|
|
174
182
|
filename,
|
|
175
|
-
|
|
176
|
-
|
|
183
|
+
groqApiKey: effectiveTranscription.groqApiKey,
|
|
184
|
+
openaiApiKey: effectiveTranscription.openaiApiKey,
|
|
185
|
+
falApiKey: effectiveTranscription.falApiKey,
|
|
177
186
|
totalDurationSeconds: probedDurationSeconds,
|
|
178
187
|
env: effectiveEnv,
|
|
179
188
|
onProgress: (event) => {
|
|
180
189
|
progress?.onProgress?.({
|
|
181
|
-
kind:
|
|
190
|
+
kind: "transcript-whisper-progress",
|
|
182
191
|
url: progress.url,
|
|
183
192
|
service: progress.service,
|
|
184
193
|
processedDurationSeconds: event.processedDurationSeconds,
|
|
@@ -199,14 +208,14 @@ export async function transcribeMediaUrl({ fetchImpl, env, url, filenameHint, du
|
|
|
199
208
|
export async function probeRemoteMedia(fetchImpl, url) {
|
|
200
209
|
try {
|
|
201
210
|
const res = await fetchImpl(url, {
|
|
202
|
-
method:
|
|
203
|
-
redirect:
|
|
211
|
+
method: "HEAD",
|
|
212
|
+
redirect: "follow",
|
|
204
213
|
signal: AbortSignal.timeout(TRANSCRIPTION_TIMEOUT_MS),
|
|
205
214
|
});
|
|
206
215
|
if (!res.ok)
|
|
207
|
-
throw new Error(
|
|
208
|
-
const contentLength = parseContentLength(res.headers.get(
|
|
209
|
-
const mediaType = normalizeHeaderType(res.headers.get(
|
|
216
|
+
throw new Error("head failed");
|
|
217
|
+
const contentLength = parseContentLength(res.headers.get("content-length"));
|
|
218
|
+
const mediaType = normalizeHeaderType(res.headers.get("content-type"));
|
|
210
219
|
const filename = filenameFromUrl(url);
|
|
211
220
|
return { contentLength, mediaType, filename };
|
|
212
221
|
}
|
|
@@ -216,7 +225,7 @@ export async function probeRemoteMedia(fetchImpl, url) {
|
|
|
216
225
|
}
|
|
217
226
|
export async function downloadCappedBytes(fetchImpl, url, maxBytes, options) {
|
|
218
227
|
const res = await fetchImpl(url, {
|
|
219
|
-
redirect:
|
|
228
|
+
redirect: "follow",
|
|
220
229
|
headers: { Range: `bytes=0-${maxBytes - 1}` },
|
|
221
230
|
signal: AbortSignal.timeout(TRANSCRIPTION_TIMEOUT_MS),
|
|
222
231
|
});
|
|
@@ -265,7 +274,7 @@ export async function downloadCappedBytes(fetchImpl, url, maxBytes, options) {
|
|
|
265
274
|
}
|
|
266
275
|
export async function downloadToFile(fetchImpl, url, filePath, options) {
|
|
267
276
|
const res = await fetchImpl(url, {
|
|
268
|
-
redirect:
|
|
277
|
+
redirect: "follow",
|
|
269
278
|
signal: AbortSignal.timeout(TRANSCRIPTION_TIMEOUT_MS),
|
|
270
279
|
});
|
|
271
280
|
if (!res.ok) {
|
|
@@ -278,7 +287,7 @@ export async function downloadToFile(fetchImpl, url, filePath, options) {
|
|
|
278
287
|
options?.onProgress?.(bytes.byteLength);
|
|
279
288
|
return bytes.byteLength;
|
|
280
289
|
}
|
|
281
|
-
const handle = await fs.open(filePath,
|
|
290
|
+
const handle = await fs.open(filePath, "w");
|
|
282
291
|
let downloadedBytes = 0;
|
|
283
292
|
let lastReported = 0;
|
|
284
293
|
try {
|
|
@@ -314,7 +323,7 @@ export function normalizeHeaderType(value) {
|
|
|
314
323
|
const trimmed = value.trim();
|
|
315
324
|
if (!trimmed)
|
|
316
325
|
return null;
|
|
317
|
-
return trimmed.split(
|
|
326
|
+
return trimmed.split(";")[0]?.trim().toLowerCase() ?? null;
|
|
318
327
|
}
|
|
319
328
|
export function parseContentLength(value) {
|
|
320
329
|
if (!value)
|
|
@@ -325,7 +334,7 @@ export function parseContentLength(value) {
|
|
|
325
334
|
export function filenameFromUrl(url) {
|
|
326
335
|
try {
|
|
327
336
|
const parsed = new URL(url);
|
|
328
|
-
const base = parsed.pathname.split(
|
|
337
|
+
const base = parsed.pathname.split("/").pop() ?? "";
|
|
329
338
|
return base.trim().length > 0 ? base : null;
|
|
330
339
|
}
|
|
331
340
|
catch {
|
|
@@ -333,7 +342,7 @@ export function filenameFromUrl(url) {
|
|
|
333
342
|
}
|
|
334
343
|
}
|
|
335
344
|
export function formatBytes(bytes) {
|
|
336
|
-
const units = [
|
|
345
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
337
346
|
let value = bytes;
|
|
338
347
|
let idx = 0;
|
|
339
348
|
while (value >= 1024 && idx < units.length - 1) {
|