added support for vimeo and wav audio conversion
This commit is contained in:
parent
519c9eb782
commit
7ff5f56538
9 changed files with 61 additions and 6 deletions
|
@ -22,6 +22,7 @@ It preserves original media quality so you get best downloads possible (unless y
|
||||||
- YouTube (with HDR support)
|
- YouTube (with HDR support)
|
||||||
|
|
||||||
### Only video
|
### Only video
|
||||||
|
- Vimeo
|
||||||
- VK
|
- VK
|
||||||
|
|
||||||
### Only audio
|
### Only audio
|
||||||
|
@ -45,8 +46,8 @@ Take English or Russian localization from [this directory](https://github.com/wu
|
||||||
- You can add wordplays or puns if it feels natural to do so.
|
- You can add wordplays or puns if it feels natural to do so.
|
||||||
- Even though I love cursing, keep that away from translations.
|
- Even though I love cursing, keep that away from translations.
|
||||||
- Always check if there are issues in UI with your localization.
|
- Always check if there are issues in UI with your localization.
|
||||||
- There's no need to translate `ChangelogContentTitle` and `ChangelogContent`, because those are very often changed.
|
- There's no need to translate `ChangelogContentTitle` and `ChangelogContent`, because those are very often changed. You can remove both of them from your translation file.
|
||||||
- Add "(in english)" to `ChangelogLastCommit` and `ChangelogLastMajor`, because those are almost always kept exclusively in English. Remove that phrase if you do translate major update changelog.
|
- Add "(in english)" in translation language to `ChangelogLastCommit` and `ChangelogLastMajor`, because those are almost always kept exclusively in English. Remove that phrase if you do translate major update changelog.
|
||||||
- Be nice.
|
- Be nice.
|
||||||
|
|
||||||
## TO-DO
|
## TO-DO
|
||||||
|
@ -60,6 +61,7 @@ Take English or Russian localization from [this directory](https://github.com/wu
|
||||||
- [ ] Add an option to keep watermark on TikTok videos
|
- [ ] Add an option to keep watermark on TikTok videos
|
||||||
|
|
||||||
### Other
|
### Other
|
||||||
|
- [ ] Remake video quality picking (do it more like I did in Vimeo module)
|
||||||
- [ ] Add support for emoji in localization
|
- [ ] Add support for emoji in localization
|
||||||
- [ ] Language picker in settings
|
- [ ] Language picker in settings
|
||||||
- [ ] Make cobalt fully PWA compatible (add a service worker)
|
- [ ] Make cobalt fully PWA compatible (add a service worker)
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
"mid": "720",
|
"mid": "720",
|
||||||
"low": "480"
|
"low": "480"
|
||||||
},
|
},
|
||||||
"supportedAudio": ["mp3", "ogg", "opus"],
|
"supportedAudio": ["mp3", "ogg", "wav", "opus"],
|
||||||
"ffmpegArgs": {
|
"ffmpegArgs": {
|
||||||
"webm": ["-c:v", "copy", "-c:a", "copy"],
|
"webm": ["-c:v", "copy", "-c:a", "copy"],
|
||||||
"mp4": ["-c:v", "copy", "-c:a", "copy", "-movflags", "frag_keyframe+empty_moov"],
|
"mp4": ["-c:v", "copy", "-c:a", "copy", "-movflags", "frag_keyframe+empty_moov"],
|
||||||
|
|
|
@ -5,7 +5,7 @@ let switchers = {
|
||||||
"theme": ["auto", "light", "dark"],
|
"theme": ["auto", "light", "dark"],
|
||||||
"ytFormat": ["webm", "mp4"],
|
"ytFormat": ["webm", "mp4"],
|
||||||
"quality": ["max", "hig", "mid", "low"],
|
"quality": ["max", "hig", "mid", "low"],
|
||||||
"audioFormat": ["best", "mp3", "ogg", "opus"]
|
"audioFormat": ["best", "mp3", "ogg", "wav", "opus"]
|
||||||
}
|
}
|
||||||
let exceptions = { // fuck you apple
|
let exceptions = { // fuck you apple
|
||||||
"ytFormat": "mp4",
|
"ytFormat": "mp4",
|
||||||
|
|
|
@ -12,6 +12,7 @@ import tiktok from "./services/tiktok.js";
|
||||||
import douyin from "./services/douyin.js";
|
import douyin from "./services/douyin.js";
|
||||||
import tumblr from "./services/tumblr.js";
|
import tumblr from "./services/tumblr.js";
|
||||||
import matchActionDecider from "./sub/matchActionDecider.js";
|
import matchActionDecider from "./sub/matchActionDecider.js";
|
||||||
|
import vimeo from "./services/vimeo.js";
|
||||||
|
|
||||||
export default async function (host, patternMatch, url, ip, lang, format, quality, audioFormat, isAudioOnly) {
|
export default async function (host, patternMatch, url, ip, lang, format, quality, audioFormat, isAudioOnly) {
|
||||||
try {
|
try {
|
||||||
|
@ -84,6 +85,12 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
|
||||||
lang: lang
|
lang: lang
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "vimeo":
|
||||||
|
r = await vimeo({
|
||||||
|
id: patternMatch["id"], quality: quality,
|
||||||
|
lang: lang
|
||||||
|
});
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return apiJSON(0, { t: errorUnsupported(lang) });
|
return apiJSON(0, { t: errorUnsupported(lang) });
|
||||||
}
|
}
|
||||||
|
|
38
src/modules/services/vimeo.js
Normal file
38
src/modules/services/vimeo.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import got from "got";
|
||||||
|
import loc from "../../localization/manager.js";
|
||||||
|
import { genericUserAgent, quality } from "../config.js";
|
||||||
|
|
||||||
|
export default async function(obj) {
|
||||||
|
try {
|
||||||
|
let api = await got.get(`https://player.vimeo.com/video/${obj.id}/config`, { headers: { "user-agent": genericUserAgent } });
|
||||||
|
api.on('error', (err) => {
|
||||||
|
return { error: loc(obj.lang, 'ErrorCouldntFetch', 'vimeo') };
|
||||||
|
});
|
||||||
|
api = api.body
|
||||||
|
if (api.includes('}}},"progressive":[{')) {
|
||||||
|
api = JSON.parse(api)
|
||||||
|
if (api["request"]["files"]["progressive"]) {
|
||||||
|
let all = api["request"]["files"]["progressive"].sort((a, b) => Number(b.width) - Number(a.width));
|
||||||
|
let best = all[0]
|
||||||
|
try {
|
||||||
|
if (obj.quality != "max") {
|
||||||
|
let pref = parseInt(quality[obj.quality])
|
||||||
|
for (let i in all) {
|
||||||
|
let currQuality = parseInt(all[i]["quality"].replace('p', ''))
|
||||||
|
if (currQuality < pref) {
|
||||||
|
break;
|
||||||
|
} else if (currQuality == pref) {
|
||||||
|
best = all[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
best = all[0]
|
||||||
|
}
|
||||||
|
return { urls: best["url"], audioFilename: loc(obj.lang, 'ErrorEmptyDownload') }
|
||||||
|
} else return { error: loc(obj.lang, 'ErrorEmptyDownload') }
|
||||||
|
} else return { error: loc(obj.lang, 'ErrorBrokenLink', 'vimeo') }
|
||||||
|
} catch (e) {
|
||||||
|
return { error: loc(obj.lang, 'ErrorBadFetch') };
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ export default async function(obj) {
|
||||||
let userQuality = selectQuality('vk', obj.quality, Object.entries(services.vk.quality_match).reduce((r, [k, v]) => { r[v] = k; return r;})[maxQuality])
|
let userQuality = selectQuality('vk', obj.quality, Object.entries(services.vk.quality_match).reduce((r, [k, v]) => { r[v] = k; return r;})[maxQuality])
|
||||||
let id = js["player"]["params"][0][selectedQuality].split("id=")[1]
|
let id = js["player"]["params"][0][selectedQuality].split("id=")[1]
|
||||||
if (selectedQuality in js["player"]["params"][0]) {
|
if (selectedQuality in js["player"]["params"][0]) {
|
||||||
return { urls: js["player"]["params"][0][selectedQuality].replace(`type=${maxQuality}`, `type=${services.vk.quality_match[userQuality]}`), filename: `vk_${js["player"]["params"][0][selectedQuality].split("id=")[1]}_${attr['width']}x${attr['height']}.mp4`, audioFilename: loc(obj.lang, 'ErrorEmptyDownload') };
|
return { urls: js["player"]["params"][0][selectedQuality].replace(`type=${maxQuality}`, `type=${services.vk.quality_match[userQuality]}`), filename: `vk_${id}_${attr['width']}x${attr['height']}.mp4`, audioFilename: loc(obj.lang, 'ErrorEmptyDownload') };
|
||||||
} else {
|
} else {
|
||||||
return { error: loc(obj.lang, 'ErrorEmptyDownload') };
|
return { error: loc(obj.lang, 'ErrorEmptyDownload') };
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,5 +68,9 @@
|
||||||
"douyin": {
|
"douyin": {
|
||||||
"patterns": ["video/:postId", ":id"],
|
"patterns": ["video/:postId", ":id"],
|
||||||
"enabled": true
|
"enabled": true
|
||||||
|
},
|
||||||
|
"vimeo": {
|
||||||
|
"patterns": [":id"],
|
||||||
|
"enabled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,4 +19,6 @@ export let testers = {
|
||||||
|
|
||||||
"tumblr": (patternMatch) => ((patternMatch["id"] && patternMatch["id"].length < 21) ||
|
"tumblr": (patternMatch) => ((patternMatch["id"] && patternMatch["id"].length < 21) ||
|
||||||
(patternMatch["id"] && patternMatch["id"].length < 21 && patternMatch["user"] && patternMatch["user"].length <= 32)),
|
(patternMatch["id"] && patternMatch["id"].length < 21 && patternMatch["user"] && patternMatch["user"].length <= 32)),
|
||||||
|
|
||||||
|
"vimeo": (patternMatch) => ((patternMatch["id"] && patternMatch["id"].length <= 11)),
|
||||||
};
|
};
|
|
@ -41,6 +41,8 @@ export default function(r, host, ip, audioFormat, isAudioOnly) {
|
||||||
})
|
})
|
||||||
case "tumblr":
|
case "tumblr":
|
||||||
return apiJSON(1, { u: r.urls })
|
return apiJSON(1, { u: r.urls })
|
||||||
|
case "vimeo":
|
||||||
|
return apiJSON(1, { u: r.urls })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let type = "render"
|
let type = "render"
|
||||||
|
@ -55,7 +57,7 @@ export default function(r, host, ip, audioFormat, isAudioOnly) {
|
||||||
type = "bridge"
|
type = "bridge"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (host == "reddit" && r.typeId == 1 || host == "vk") return apiJSON(0, { t: r.audioFilename });
|
if (host == "reddit" && r.typeId == 1 || host == "vk" || host == "vimeo") return apiJSON(0, { t: r.audioFilename });
|
||||||
return apiJSON(2, {
|
return apiJSON(2, {
|
||||||
type: type,
|
type: type,
|
||||||
u: Array.isArray(r.urls) ? r.urls[1] : r.urls, service: host, ip: ip,
|
u: Array.isArray(r.urls) ? r.urls[1] : r.urls, service: host, ip: ip,
|
||||||
|
|
Loading…
Reference in a new issue