Spaces:
Paused
Paused
| import { env } from "../../config.js"; | |
| const gqlURL = "https://gql.twitch.tv/gql"; | |
| const clientIdHead = { "client-id": "kimne78kx3ncx6brgo4mv6wki5h1ko" }; | |
| export default async function (obj) { | |
| const req_metadata = await fetch(gqlURL, { | |
| method: "POST", | |
| headers: clientIdHead, | |
| body: JSON.stringify({ | |
| query: `{ | |
| clip(slug: "${obj.clipId}") { | |
| broadcaster { | |
| login | |
| } | |
| createdAt | |
| curator { | |
| login | |
| } | |
| durationSeconds | |
| id | |
| medium: thumbnailURL(width: 480, height: 272) | |
| title | |
| videoQualities { | |
| quality | |
| sourceURL | |
| } | |
| } | |
| }` | |
| }) | |
| }).then(r => r.status === 200 ? r.json() : false).catch(() => {}); | |
| if (!req_metadata) return { error: "fetch.fail" }; | |
| const clipMetadata = req_metadata.data.clip; | |
| if (clipMetadata.durationSeconds > env.durationLimit) { | |
| return { error: "content.too_long" }; | |
| } | |
| if (!clipMetadata.videoQualities || !clipMetadata.broadcaster) { | |
| return { error: "fetch.empty" }; | |
| } | |
| const req_token = await fetch(gqlURL, { | |
| method: "POST", | |
| headers: clientIdHead, | |
| body: JSON.stringify([ | |
| { | |
| "operationName": "VideoAccessToken_Clip", | |
| "variables": { | |
| "slug": obj.clipId | |
| }, | |
| "extensions": { | |
| "persistedQuery": { | |
| "version": 1, | |
| "sha256Hash": "36b89d2507fce29e5ca551df756d27c1cfe079e2609642b4390aa4c35796eb11" | |
| } | |
| } | |
| } | |
| ]) | |
| }).then(r => r.status === 200 ? r.json() : false).catch(() => {}); | |
| if (!req_token) return { error: "fetch.fail" }; | |
| const formats = clipMetadata.videoQualities; | |
| const format = formats.find(f => f.quality === obj.quality) || formats[0]; | |
| return { | |
| type: "proxy", | |
| urls: `${format.sourceURL}?${new URLSearchParams({ | |
| sig: req_token[0].data.clip.playbackAccessToken.signature, | |
| token: req_token[0].data.clip.playbackAccessToken.value | |
| })}`, | |
| fileMetadata: { | |
| title: clipMetadata.title.trim(), | |
| artist: `Twitch Clip by @${clipMetadata.broadcaster.login}, clipped by @${clipMetadata.curator.login}`, | |
| }, | |
| filenameAttributes: { | |
| service: "twitch", | |
| id: clipMetadata.id, | |
| title: clipMetadata.title.trim(), | |
| author: `${clipMetadata.broadcaster.login}, clipped by ${clipMetadata.curator.login}`, | |
| qualityLabel: `${format.quality}p`, | |
| extension: 'mp4' | |
| }, | |
| filename: `twitchclip_${clipMetadata.id}_${format.quality}p.mp4`, | |
| audioFilename: `twitchclip_${clipMetadata.id}_audio` | |
| } | |
| } | |