diff --git a/api/src/processing/helpers/captions.js b/api/src/processing/helpers/captions.js index 3e3307cd..7109bcac 100644 --- a/api/src/processing/helpers/captions.js +++ b/api/src/processing/helpers/captions.js @@ -1,5 +1,36 @@ const normalizedLanguage = language => language?.toLowerCase().replace("_", "-"); +export const createCaptionResponse = ({ + url, + format, + language, + service, + id, + title, + author, + source, + headers, +}) => ({ + type: "captions", + isCaptionOnly: true, + urls: url, + headers, + captionFormat: format, + captionLanguage: language, + filenameAttributes: { + service, + id, + title: title || `${service}_${id}`, + author, + }, + captionMetadata: { + title, + author, + language, + source, + }, +}); + export const selectCaptionTrack = (tracks, subtitleLang, allowAutomatic = false) => { const allowed = tracks.filter(track => allowAutomatic || track.kind !== "asr"); if (!allowed.length) return; diff --git a/api/src/processing/match.js b/api/src/processing/match.js index 9966cbb8..c3373cde 100644 --- a/api/src/processing/match.js +++ b/api/src/processing/match.js @@ -7,6 +7,7 @@ import { testers } from "./service-patterns.js"; import matchAction from "./match-action.js"; import { friendlyServiceName } from "./service-alias.js"; +import { captionOnlyServices } from "./service-config.js"; import bilibili from "./services/bilibili.js"; import reddit from "./services/reddit.js"; @@ -66,7 +67,7 @@ export default async function({ host, patternMatch, params, authType }) { }); } - if (isCaptionOnly && host !== "youtube") { + if (isCaptionOnly && !captionOnlyServices.has(host)) { return createResponse("error", { code: "error.api.service.captions_not_supported" }); diff --git a/api/src/processing/service-config.js b/api/src/processing/service-config.js index fbe25805..fbcc26d2 100644 --- a/api/src/processing/service-config.js +++ b/api/src/processing/service-config.js @@ -1,6 +1,7 @@ import UrlPattern from "url-pattern"; export const audioIgnore = new Set(["vk", "ok", "loom"]); +export const captionOnlyServices = new Set(["youtube"]); export const hlsExceptions = new Set(["dailymotion", "vimeo", "rutube", "bsky", "youtube"]); export const services = { diff --git a/api/src/stream/captions.js b/api/src/stream/captions.js index dbe94ad4..02251d14 100644 --- a/api/src/stream/captions.js +++ b/api/src/stream/captions.js @@ -28,6 +28,7 @@ export default async function captions(streamInfo, res) { signal: abortController.signal, maxRedirections: 4, dispatcher: defaultAgent, + headers: streamInfo.headers, }); if (response.statusCode < 200 || response.statusCode > 299) { diff --git a/docs/api.md b/docs/api.md index a0c24311..067bc45a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -95,10 +95,11 @@ all keys except for `url` are optional. value options are separated by `/`. | `youtubeBetterAudio` | `boolean` | prefer higher quality youtube audio if possible | `false` | | `youtubeHLS` | `boolean` | use HLS formats when downloading from youtube | `false` | -#### standalone youtube captions +#### standalone captions set `downloadMode` to `captions` to download a caption or transcript file without -downloading video or audio. this mode currently supports youtube links. +downloading video or audio. supported services are listed in the +[api readme](/api/README.md#supported-services). `captionLanguage` selects the caption language, falling back to `subtitleLang` when omitted. if both are omitted, cobalt prefers the first manually provided track and diff --git a/web/i18n/en/error/api.json b/web/i18n/en/error/api.json index fcd0cbec..c2e38960 100644 --- a/web/i18n/en/error/api.json +++ b/web/i18n/en/error/api.json @@ -25,7 +25,7 @@ "service.unsupported": "this service is not supported yet. have you pasted the right link?", "service.disabled": "this service is generally supported by cobalt, but it's disabled on this processing instance. try a link from another service!", "service.audio_not_supported": "this service doesn't support audio extraction. try a link from another service!", - "service.captions_not_supported": "standalone transcripts are only available for youtube links right now.", + "service.captions_not_supported": "this service doesn't support standalone transcripts.", "link.invalid": "your link is invalid or this service is not supported yet. have you pasted the right link?", "link.unsupported": "{{ service }} is supported, but i couldn't recognize your link. have you pasted the right one?",