mirror of
https://github.com/imputnet/cobalt.git
synced 2025-07-14 01:08:27 +00:00
Add video title to YouTube download filename
This commit is contained in:
parent
b62627058e
commit
e8a48c53f2
@ -1,4 +1,4 @@
|
||||
import { apiJSON } from "../sub/utils.js";
|
||||
import { apiJSON, PostInfo } from "../sub/utils.js";
|
||||
import { errorUnsupported, genericError, brokenLink } from "../sub/errors.js";
|
||||
|
||||
import loc from "../../localization/manager.js";
|
||||
@ -16,6 +16,48 @@ import tumblr from "./services/tumblr.js";
|
||||
import vimeo from "./services/vimeo.js";
|
||||
import soundcloud from "./services/soundcloud.js";
|
||||
|
||||
export class YouTubeFetchInfo {
|
||||
/**
|
||||
* ID of the YouTube video.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
id
|
||||
/**
|
||||
* Quality of the YouTube video.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
quality
|
||||
/**
|
||||
* Format of the YouTube video to be downloaded.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
format
|
||||
/**
|
||||
* Whether only the audio of the YouTube video should be gotten.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isAudioOnly
|
||||
/**
|
||||
* Whether audio of the YouTube video should be muted.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isAudioMuted
|
||||
/**
|
||||
* Dub language to use for the video.
|
||||
*
|
||||
* @type {boolean | string}
|
||||
*/
|
||||
dubLang
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PostInfo} obj Post information
|
||||
*/
|
||||
export default async function (host, patternMatch, url, lang, obj) {
|
||||
try {
|
||||
let r, isAudioOnly = !!obj.isAudioOnly;
|
||||
@ -44,6 +86,7 @@ export default async function (host, patternMatch, url, lang, obj) {
|
||||
});
|
||||
break;
|
||||
case "youtube":
|
||||
/** @type {YouTubeFetchInfo} */
|
||||
let fetchInfo = {
|
||||
id: patternMatch["id"].slice(0, 11),
|
||||
quality: obj.vQuality,
|
||||
@ -113,6 +156,7 @@ export default async function (host, patternMatch, url, lang, obj) {
|
||||
|
||||
return matchActionDecider(r, host, obj.ip, obj.aFormat, isAudioOnly, lang, isAudioMuted);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return apiJSON(0, { t: genericError(lang, host) })
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Innertube } from 'youtubei.js';
|
||||
import { maxVideoDuration } from '../../config.js';
|
||||
import { YouTubeFetchInfo } from '../match.js';
|
||||
|
||||
const yt = await Innertube.create();
|
||||
|
||||
@ -21,7 +22,30 @@ const c = {
|
||||
}
|
||||
}
|
||||
|
||||
export default async function(o) {
|
||||
/**
|
||||
* Creates a filename to be downloaded for the requested YouTube video.
|
||||
*
|
||||
* @param {YouTubeFetchInfo} fi Fetch info to utilize for filename
|
||||
* @param vi Video info to utilize for filename
|
||||
* @param format Video format object to pull info from
|
||||
* @param {string} container Video container type (file extension)
|
||||
*/
|
||||
function youtubeFilename(fi, vi, format, container) {
|
||||
return [
|
||||
'youtube',
|
||||
vi.basic_info.title,
|
||||
fi.id,
|
||||
format.width + 'x' + format.height,
|
||||
fi.format + (fi.dubLang ? "_" + fi.dubLang : ""),
|
||||
].join('_') + ('.' + container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Core logic for running the YouTube processor.
|
||||
*
|
||||
* @param {YouTubeFetchInfo} o Fetch information for YouTube video
|
||||
*/
|
||||
export default async function youtube(o) {
|
||||
let info, isDubbed, quality = o.quality === "max" ? "9000" : o.quality; //set quality 9000(p) to be interpreted as max
|
||||
try {
|
||||
info = await yt.getBasicInfo(o.id, 'ANDROID');
|
||||
@ -59,7 +83,7 @@ export default async function(o) {
|
||||
type: "render",
|
||||
isAudioOnly: true,
|
||||
urls: audio.url,
|
||||
audioFilename: `youtube_${o.id}_audio${isDubbed ? `_${o.dubLang}`:''}`,
|
||||
audioFilename: `youtube_${o.id}_audio${isDubbed ? `_${o.dubLang}` : ''}`,
|
||||
fileMetadata: {
|
||||
title: info.basic_info.title,
|
||||
artist: info.basic_info.author.replace("- Topic", "").trim(),
|
||||
@ -90,7 +114,8 @@ export default async function(o) {
|
||||
if (video && audio) return {
|
||||
type: "render",
|
||||
urls: [video.url, audio.url],
|
||||
filename: `youtube_${o.id}_${video.width}x${video.height}_${o.format}${isDubbed ? `_${o.dubLang}`:''}.${c[o.format].container}`
|
||||
filename: youtubeFilename(o, info, video, c[o.format].container),
|
||||
// filename: `youtube_${o.id}_${video.width}x${video.height}_${o.format}${isDubbed ? `_${o.dubLang}` : ''}.${c[o.format].container}`
|
||||
};
|
||||
|
||||
return { error: 'ErrorYTTryOtherCodec' }
|
||||
|
@ -63,7 +63,7 @@ export function msToTime(d) {
|
||||
}
|
||||
export function cleanURL(url, host) {
|
||||
let forbiddenChars = ['}', '{', '(', ')', '\\', '%', '>', '<', '^', '*', '!', '~', ';', ':', ',', '`', '[', ']', '#', '$', '"', "'", "@"]
|
||||
switch(host) {
|
||||
switch (host) {
|
||||
case "vk":
|
||||
case "youtube":
|
||||
url = url.split('&')[0];
|
||||
@ -95,7 +95,68 @@ export function unicodeDecode(str) {
|
||||
return String.fromCharCode(parseInt(unicode.replace(/\\u/g, ""), 16));
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Post information for a given media post.
|
||||
*/
|
||||
export class PostInfo {
|
||||
/**
|
||||
* Codec used by the post's media.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
vCodec
|
||||
/**
|
||||
* Quality of the post's media.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
vQuality
|
||||
/**
|
||||
* Format to get of the post's media.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
aFormat
|
||||
/**
|
||||
* Whether the media should be gotten as audio only.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isAudioOnly
|
||||
/**
|
||||
* Whether the TikTok watermark should be absent from the gotten media.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isNoTTWatermark
|
||||
/**
|
||||
* Whether the TikTok media should be gotten with full audio.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isTTFullAudio
|
||||
/**
|
||||
* Whether the media should be gotten with the audio muted.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
isAudioMuted
|
||||
/**
|
||||
* Language to get the video dubbed in, or not to dub at all. Usually pulled from
|
||||
* the request's 'Accept-Language' header, but defaults to false.
|
||||
*
|
||||
* @type {boolean | string}
|
||||
*/
|
||||
dubLang = false
|
||||
/**
|
||||
* Whether to get DASH video files from the Vimeo platform.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
vimeoDash
|
||||
}
|
||||
export function checkJSONPost(obj) {
|
||||
/** @type {PostInfo} */
|
||||
let def = {
|
||||
vCodec: "h264",
|
||||
vQuality: "720",
|
||||
|
Loading…
Reference in New Issue
Block a user