api/loom: add transcription subtitles
Some checks are pending
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
Run service tests / test service functionality (push) Waiting to run
Run service tests / test service: ${{ matrix.service }} (push) Blocked by required conditions
Run tests / api sanity check (push) Waiting to run
Run tests / check lockfile correctness (push) Waiting to run
Run tests / web sanity check (push) Waiting to run

since there's no language selection (at all), we just add the only transcription if a user wants subtitles
This commit is contained in:
wukko 2025-06-20 18:59:35 +06:00
parent 17ab8dd709
commit ab526c234e
No known key found for this signature in database
GPG Key ID: 3E30B3F26C7B4AA2
3 changed files with 53 additions and 3 deletions

View File

@ -161,6 +161,14 @@ export default function({
}
break;
case "loom":
if (r.subtitles) {
params = { type: "remux" };
} else {
responseType = "redirect";
}
break;
case "ok":
case "vk":
case "tiktok":
@ -174,7 +182,6 @@ export default function({
case "pinterest":
case "streamable":
case "snapchat":
case "loom":
case "twitch":
responseType = "redirect";
break;

View File

@ -235,7 +235,8 @@ export default async function({ host, patternMatch, params, isSession, isApiKey
case "loom":
r = await loom({
id: patternMatch.id
id: patternMatch.id,
subtitleLang,
});
break;

View File

@ -50,7 +50,42 @@ async function fromRawURL(id) {
}
}
export default async function({ id }) {
async function getTranscript(id) {
const gql = await fetch(`https://www.loom.com/graphql`, {
method: "POST",
headers: craftHeaders(id),
body: JSON.stringify({
operationName: "FetchVideoTranscriptForFetchTranscript",
variables: {
videoId: id,
password: null,
},
query: `
query FetchVideoTranscriptForFetchTranscript($videoId: ID!, $password: String) {
fetchVideoTranscript(videoId: $videoId, password: $password) {
... on VideoTranscriptDetails {
captions_source_url
language
__typename
}
... on GenericError {
message
__typename
}
__typename
}
}`,
})
})
.then(r => r.status === 200 && r.json())
.catch(() => {});
if (gql?.data?.fetchVideoTranscript?.captions_source_url?.includes('.vtt?')) {
return gql.data.fetchVideoTranscript.captions_source_url;
}
}
export default async function({ id, subtitleLang }) {
let url = await fromTranscodedURL(id);
url ??= await fromRawURL(id);
@ -58,8 +93,15 @@ export default async function({ id }) {
return { error: "fetch.empty" }
}
let subtitles;
if (subtitleLang) {
const transcript = await getTranscript(id);
if (transcript) subtitles = transcript;
}
return {
urls: url,
subtitles,
filename: `loom_${id}.mp4`,
audioFilename: `loom_${id}_audio`
}