mirror of
https://github.com/wukko/cobalt.git
synced 2024-11-04 23:39:59 +00:00
fixes
- fixed neighbor quality picking for youtube videos - webm is now default for youtube downloads for all platforms except for ios - even more readme changes - a tiny bit of clean up - preparing stuff for next major update
This commit is contained in:
parent
74edaba2b8
commit
2fae43d890
8 changed files with 32 additions and 25 deletions
14
README.md
14
README.md
|
@ -1,12 +1,14 @@
|
||||||
# cobalt
|
# cobalt
|
||||||
Sleek and easy to use social media downloader built with JavaScript.
|
Best way to save content you love.
|
||||||
|
|
||||||
Try it now: [co.wukko.me](https://co.wukko.me/)
|
[co.wukko.me](https://co.wukko.me/)
|
||||||
|
|
||||||
![cobalt logo](https://raw.githubusercontent.com/wukko/cobalt/current/src/front/icons/wide.png "cobalt logo")
|
![cobalt logo](https://raw.githubusercontent.com/wukko/cobalt/current/src/front/icons/wide.png "cobalt logo")
|
||||||
|
|
||||||
## What's cobalt?
|
## What's cobalt?
|
||||||
cobalt aims to be the ultimate social media downloader, that is efficient, pretty, and doesn't bother you with ads or privacy invasion agreement popups. It also doesn't remux anything, so you get media in best quality possible (unless you change that in settings).
|
cobalt is social media downloader with zero bullshit. It's efficient, easy to use, and doesn't bother you with ads or privacy invasion "consent" popups.
|
||||||
|
|
||||||
|
It preserves original media quality so you get best downloads possible (unless you change that in settings).
|
||||||
|
|
||||||
## Supported services
|
## Supported services
|
||||||
|
|
||||||
|
@ -17,8 +19,7 @@ cobalt aims to be the ultimate social media downloader, that is efficient, prett
|
||||||
- TikTok
|
- TikTok
|
||||||
- Tumblr
|
- Tumblr
|
||||||
- Twitter
|
- Twitter
|
||||||
- YouTube
|
- YouTube (with HDR support)
|
||||||
- YouTube Music
|
|
||||||
- VK
|
- VK
|
||||||
|
|
||||||
### Audio
|
### Audio
|
||||||
|
@ -51,8 +52,9 @@ Take English or Russian localization from [this directory](https://github.com/wu
|
||||||
- [ ] niconico support
|
- [ ] niconico support
|
||||||
- [ ] Instagram support
|
- [ ] Instagram support
|
||||||
- [ ] SoundCloud support
|
- [ ] SoundCloud support
|
||||||
- [ ] Add an option to save Twitter GIFs as `.gif` instead of `.mp4`
|
|
||||||
- [ ] Quality switching for bilibili
|
- [ ] Quality switching for bilibili
|
||||||
|
- [ ] Find a way to get TikTok videos without a watermark
|
||||||
|
- [ ] Add an option to keep watermark on TikTok videos
|
||||||
|
|
||||||
### Other
|
### Other
|
||||||
- [ ] Language picker in settings
|
- [ ] Language picker in settings
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "cobalt",
|
"name": "cobalt",
|
||||||
"description": "probably the friendliest social media downloader yet",
|
"description": "save what you love",
|
||||||
"version": "2.2.8",
|
"version": "2.2.9",
|
||||||
"author": "wukko",
|
"author": "wukko",
|
||||||
"exports": "./src/cobalt.js",
|
"exports": "./src/cobalt.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
},
|
},
|
||||||
"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"],
|
||||||
|
"bst": ["-c:a", "copy"],
|
||||||
|
"mp3": ["-ar", "48000", "-ac", "2", "-b:a", "320k"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
let isIOS = navigator.userAgent.toLowerCase().match("iphone os");
|
let isIOS = navigator.userAgent.toLowerCase().match("iphone os");
|
||||||
let switchers = {
|
let switchers = {
|
||||||
"theme": ["auto", "light", "dark"],
|
"theme": ["auto", "light", "dark"],
|
||||||
"youtubeFormat": ["mp4", "webm", "audio"],
|
"youtubeFormat": ["webm", "mp4", "audio"],
|
||||||
"quality": ["max", "hig", "mid", "low"]
|
"quality": ["max", "hig", "mid", "low"]
|
||||||
}
|
}
|
||||||
|
let exceptions = {
|
||||||
|
"youtubeFormat": "mp4"
|
||||||
|
}
|
||||||
|
|
||||||
function eid(id) {
|
function eid(id) {
|
||||||
return document.getElementById(id)
|
return document.getElementById(id)
|
||||||
|
@ -98,9 +101,11 @@ function changeSwitcher(li, b, u) {
|
||||||
}
|
}
|
||||||
if (li == "theme") detectColorScheme();
|
if (li == "theme") detectColorScheme();
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem(li, switchers[li][0]);
|
let pref = switchers[li][0];
|
||||||
|
if (isIOS && exceptions[li]) pref = exceptions[li];
|
||||||
|
localStorage.setItem(li, pref);
|
||||||
for (i in switchers[li]) {
|
for (i in switchers[li]) {
|
||||||
(switchers[li][i] == switchers[li][0]) ? enable(`${li}-${switchers[li][0]}`) : disable(`${li}-${switchers[li][i]}`)
|
(switchers[li][i] == pref) ? enable(`${li}-${pref}`) : disable(`${li}-${switchers[li][i]}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
|
||||||
id: patternMatch["id"],
|
id: patternMatch["id"],
|
||||||
lang: lang
|
lang: lang
|
||||||
});
|
});
|
||||||
return (!r.error) ? apiJSON(1, { u: r.split('?')[0] }) : apiJSON(0, { t: r.error });
|
return (!r.error) ? apiJSON(1, { u: r }) : apiJSON(0, { t: r.error });
|
||||||
|
|
||||||
case "vk":
|
case "vk":
|
||||||
r = await vk({
|
r = await vk({
|
||||||
|
|
|
@ -39,11 +39,7 @@ export default async function (obj) {
|
||||||
if (parsbod.hasOwnProperty("extended_entities") && parsbod["extended_entities"].hasOwnProperty("media")) {
|
if (parsbod.hasOwnProperty("extended_entities") && parsbod["extended_entities"].hasOwnProperty("media")) {
|
||||||
if (parsbod["extended_entities"]["media"][0]["type"] === "video" || parsbod["extended_entities"]["media"][0]["type"] === "animated_gif") {
|
if (parsbod["extended_entities"]["media"][0]["type"] === "video" || parsbod["extended_entities"]["media"][0]["type"] === "animated_gif") {
|
||||||
let variants = parsbod["extended_entities"]["media"][0]["video_info"]["variants"]
|
let variants = parsbod["extended_entities"]["media"][0]["video_info"]["variants"]
|
||||||
return variants.filter((v) => {
|
return variants.filter((v) => { if (v["content_type"] == "video/mp4") return true; }).sort((a, b) => Number(b.bitrate) - Number(a.bitrate))[0]["url"].split('?')[0];
|
||||||
if (v["content_type"] == "video/mp4") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}).sort((a, b) => Number(b.bitrate) - Number(a.bitrate))[0]["url"]
|
|
||||||
} else {
|
} else {
|
||||||
return nothing
|
return nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,9 @@ export default async function (obj) {
|
||||||
}).sort((a, b) => Number(b.bitrate) - Number(a.bitrate));
|
}).sort((a, b) => Number(b.bitrate) - Number(a.bitrate));
|
||||||
if (obj.quality != "max") {
|
if (obj.quality != "max") {
|
||||||
if (videoMatch.length == 0) {
|
if (videoMatch.length == 0) {
|
||||||
let ss = selectQuality("youtube", obj.quality, video[0]["height"])
|
let ss = selectQuality("youtube", obj.quality, video[0]["qualityLabel"].slice(0, 5).replace('p', '').trim())
|
||||||
videoMatch = video.filter((a) => {
|
videoMatch = video.filter((a) => {
|
||||||
if (a["height"] == ss) return true;
|
if (a["qualityLabel"].slice(0, 5).replace('p', '').trim() == ss) return true;
|
||||||
})
|
})
|
||||||
} else if (fullVideoMatch.length > 0) {
|
} else if (fullVideoMatch.length > 0) {
|
||||||
videoMatch = [fullVideoMatch[0]]
|
videoMatch = [fullVideoMatch[0]]
|
||||||
|
|
|
@ -82,14 +82,16 @@ export async function streamAudioOnly(streamInfo, res) {
|
||||||
headers = { "user-agent": genericUserAgent };
|
headers = { "user-agent": genericUserAgent };
|
||||||
}
|
}
|
||||||
const audio = got.get(streamInfo.urls, { isStream: true, headers: headers });
|
const audio = got.get(streamInfo.urls, { isStream: true, headers: headers });
|
||||||
const ffmpegProcess = spawn(ffmpeg, [
|
let format = streamInfo.filename.split('.')[streamInfo.filename.split('.').length - 1], args = [
|
||||||
'-loglevel', '-8',
|
'-loglevel', '-8',
|
||||||
'-i', 'pipe:3',
|
'-i', 'pipe:3',
|
||||||
'-vn',
|
'-vn',
|
||||||
'-c:a', 'copy',
|
];
|
||||||
'-f', `${streamInfo.filename.split('.')[streamInfo.filename.split('.').length - 1]}`,
|
args = args.concat(ffmpegArgs[format])
|
||||||
'pipe:4',
|
if (streamInfo.time) args.push('-t', msToTime(streamInfo.time));
|
||||||
], {
|
args.push('-f', format, 'pipe:4');
|
||||||
|
|
||||||
|
const ffmpegProcess = spawn(ffmpeg, args, {
|
||||||
windowsHide: true,
|
windowsHide: true,
|
||||||
stdio: [
|
stdio: [
|
||||||
'inherit', 'inherit', 'inherit',
|
'inherit', 'inherit', 'inherit',
|
||||||
|
|
Loading…
Reference in a new issue