vimeo: use HLS playlists instead of dash manifest

This commit is contained in:
wukko 2024-06-23 23:02:57 +06:00
parent eb05c4b938
commit 0432232ea4
No known key found for this signature in database
GPG key ID: 3E30B3F26C7B4AA2

View file

@ -1,6 +1,8 @@
import { env } from "../../config.js"; import { env } from "../../config.js";
import { cleanString } from '../../sub/utils.js'; import { cleanString } from '../../sub/utils.js';
import HLS from "hls-parser";
const resolutionMatch = { const resolutionMatch = {
"3840": "2160", "3840": "2160",
"2732": "1440", "2732": "1440",
@ -33,7 +35,7 @@ export default async function(obj) {
url.searchParams.set('h', obj.password); url.searchParams.set('h', obj.password);
} }
let api = await fetch(url) const api = await fetch(url)
.then(r => r.json()) .then(r => r.json())
.catch(() => {}); .catch(() => {});
if (!api) return { error: 'ErrorCouldntFetch' }; if (!api) return { error: 'ErrorCouldntFetch' };
@ -43,14 +45,15 @@ export default async function(obj) {
if (!obj.isAudioOnly && JSON.stringify(api).includes('"progressive":[{')) if (!obj.isAudioOnly && JSON.stringify(api).includes('"progressive":[{'))
downloadType = "progressive"; downloadType = "progressive";
let fileMetadata = { const fileMetadata = {
title: cleanString(api.video.title.trim()), title: cleanString(api.video.title.trim()),
artist: cleanString(api.video.owner.name.trim()), artist: cleanString(api.video.owner.name.trim()),
} }
if (downloadType !== "dash") { if (downloadType !== "dash") {
if (qualityMatch[quality]) quality = qualityMatch[quality]; if (qualityMatch[quality]) quality = qualityMatch[quality];
let all = api.request.files.progressive.sort((a, b) => Number(b.width) - Number(a.width));
const all = api.request.files.progressive.sort((a, b) => Number(b.width) - Number(a.width));
let best = all[0]; let best = all[0];
let bestQuality = all[0].quality.split('p')[0]; let bestQuality = all[0].quality.split('p')[0];
@ -59,7 +62,7 @@ export default async function(obj) {
} }
if (Number(quality) < Number(bestQuality)) { if (Number(quality) < Number(bestQuality)) {
best = all.find(i => i.quality.split('p')[0] === quality); best = all.find(v => v.quality.split('p')[0] === quality);
} }
if (!best) return { error: 'ErrorEmptyDownload' }; if (!best) return { error: 'ErrorEmptyDownload' };
@ -74,26 +77,43 @@ export default async function(obj) {
if (api.video.duration > env.durationLimit) if (api.video.duration > env.durationLimit)
return { error: ['ErrorLengthLimit', env.durationLimit / 60] }; return { error: ['ErrorLengthLimit', env.durationLimit / 60] };
let masterJSONURL = api.request.files.dash.cdns.akfire_interconnect_quic.url; const urlMasterHLS = api.request.files.hls.cdns.akfire_interconnect_quic.url;
let masterJSON = await fetch(masterJSONURL).then(r => r.json()).catch(() => {});
if (!masterJSON) return { error: 'ErrorCouldntFetch' }; const masterHLS = await fetch(urlMasterHLS)
if (!masterJSON.video) return { error: 'ErrorEmptyDownload' }; .then(r => r.text())
.catch(() => {});
let masterJSON_Video = masterJSON.video if (!masterHLS) return { error: 'ErrorCouldntFetch' };
.sort((a, b) => Number(b.width) - Number(a.width))
.filter(a => ["dash", "mp42"].includes(a.format));
let bestVideo = masterJSON_Video[0]; const variants = HLS.parse(masterHLS).variants.sort(
if (Number(quality) < Number(resolutionMatch[bestVideo.width])) { (a, b) => Number(b.bandwidth) - Number(a.bandwidth)
bestVideo = masterJSON_Video.find(i => resolutionMatch[i.width] === quality) );
if (!variants) return { error: 'ErrorEmptyDownload' };
let bestQuality;
if (Number(quality) < Number(resolutionMatch[variants[0].resolution.width])) {
bestQuality = variants.find(v =>
(Number(quality) === Number(resolutionMatch[v.resolution.width]))
);
}
if (!bestQuality) bestQuality = variants[0];
const expandLink = (url) => {
return new URL(url, urlMasterHLS).toString();
};
let urls = expandLink(bestQuality.uri);
const audioPath = bestQuality?.audio[0]?.uri;
if (audioPath) {
urls = [
urls,
expandLink(audioPath)
]
} }
let masterM3U8 = `${masterJSONURL.split("/sep/")[0]}/sep/video/${bestVideo.id}/master.m3u8`;
const fallbackResolution = bestVideo.height > bestVideo.width ? bestVideo.width : bestVideo.height;
return { return {
urls: masterM3U8, urls,
isM3U8: true, isM3U8: true,
fileMetadata: fileMetadata, fileMetadata: fileMetadata,
filenameAttributes: { filenameAttributes: {
@ -101,8 +121,8 @@ export default async function(obj) {
id: obj.id, id: obj.id,
title: fileMetadata.title, title: fileMetadata.title,
author: fileMetadata.artist, author: fileMetadata.artist,
resolution: `${bestVideo.width}x${bestVideo.height}`, resolution: `${bestQuality.resolution.width}x${bestQuality.resolution.height}`,
qualityLabel: `${resolutionMatch[bestVideo.width] || fallbackResolution}p`, qualityLabel: `${resolutionMatch[bestQuality.resolution.width]}p`,
extension: "mp4" extension: "mp4"
} }
} }