cobalt/src/modules/processing/services/vimeo.js

109 lines
3.4 KiB
JavaScript

import { env } from "../../config.js";
import { cleanString } from '../../sub/utils.js';
const resolutionMatch = {
"3840": "2160",
"2732": "1440",
"2560": "1440",
"2048": "1080",
"1920": "1080",
"1366": "720",
"1280": "720",
"960": "480",
"640": "360",
"426": "240"
}
const qualityMatch = {
"2160": "4K",
"1440": "2K",
"480": "540",
"4K": "2160",
"2K": "1440",
"540": "480"
}
export default async function(obj) {
let quality = obj.quality === "max" ? "9000" : obj.quality;
if (!quality || obj.isAudioOnly) quality = "9000";
const url = new URL(`https://player.vimeo.com/video/${obj.id}/config`);
if (obj.password) {
url.searchParams.set('h', obj.password);
}
let api = await fetch(url)
.then(r => r.json())
.catch(() => {});
if (!api) return { error: 'ErrorCouldntFetch' };
let downloadType = "dash";
if (!obj.isAudioOnly && JSON.stringify(api).includes('"progressive":[{'))
downloadType = "progressive";
let fileMetadata = {
title: cleanString(api.video.title.trim()),
artist: cleanString(api.video.owner.name.trim()),
}
if (downloadType !== "dash") {
if (qualityMatch[quality]) quality = qualityMatch[quality];
let all = api.request.files.progressive.sort((a, b) => Number(b.width) - Number(a.width));
let best = all[0];
let bestQuality = all[0].quality.split('p')[0];
if (qualityMatch[bestQuality]) {
bestQuality = qualityMatch[bestQuality]
}
if (Number(quality) < Number(bestQuality)) {
best = all.find(i => i.quality.split('p')[0] === quality);
}
if (!best) return { error: 'ErrorEmptyDownload' };
return {
urls: best.url,
audioFilename: `vimeo_${obj.id}_audio`,
filename: `vimeo_${obj.id}_${best.width}x${best.height}.mp4`
}
}
if (api.video.duration > env.durationLimit)
return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
let masterJSONURL = api.request.files.dash.cdns.akfire_interconnect_quic.url;
let masterJSON = await fetch(masterJSONURL).then(r => r.json()).catch(() => {});
if (!masterJSON) return { error: 'ErrorCouldntFetch' };
if (!masterJSON.video) return { error: 'ErrorEmptyDownload' };
let masterJSON_Video = masterJSON.video
.sort((a, b) => Number(b.width) - Number(a.width))
.filter(a => ["dash", "mp42"].includes(a.format));
let bestVideo = masterJSON_Video[0];
if (Number(quality) < Number(resolutionMatch[bestVideo.width])) {
bestVideo = masterJSON_Video.find(i => resolutionMatch[i.width] === quality)
}
let masterM3U8 = `${masterJSONURL.split("/sep/")[0]}/sep/video/${bestVideo.id}/master.m3u8`;
const fallbackResolution = bestVideo.height > bestVideo.width ? bestVideo.width : bestVideo.height;
return {
urls: masterM3U8,
isM3U8: true,
fileMetadata: fileMetadata,
filenameAttributes: {
service: "vimeo",
id: obj.id,
title: fileMetadata.title,
author: fileMetadata.artist,
resolution: `${bestVideo.width}x${bestVideo.height}`,
qualityLabel: `${resolutionMatch[bestVideo.width] || fallbackResolution}p`,
extension: "mp4"
}
}
}