This commit is contained in:
wukko 2022-08-16 13:14:19 +06:00
parent a5e081e2bf
commit e11ee6fb62
24 changed files with 106 additions and 115 deletions

View file

@ -61,7 +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) - [ ] Remake video quality picking
- [ ] 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)
@ -96,8 +96,6 @@ Setup script installs all needed `npm` dependencies, but you have to install `No
## Disclaimer ## Disclaimer
This is my passion project, so update scheduele depends solely on my motivation. Don't expect any consistency in that. This is my passion project, so update scheduele depends solely on my motivation. Don't expect any consistency in that.
## Third party stuff
[Fluent Emoji](https://github.com/microsoft/fluentui-emoji) by Microsoft.
## License ## License
cobalt is under [AGPL-3.0](https://github.com/wukko/cobalt/blob/current/LICENSE). cobalt is under [AGPL-3.0](https://github.com/wukko/cobalt/blob/current/LICENSE).
[Fluent Emoji](https://github.com/microsoft/fluentui-emoji) by Microsoft is under [MIT](https://github.com/microsoft/fluentui-emoji/blob/main/LICENSE).

View file

@ -51,7 +51,7 @@ function changeDownloadButton(action, text) {
break; break;
} }
} }
document.addEventListener("keydown", function (event) { document.addEventListener("keydown", (event) => {
if (event.key == "Tab") { if (event.key == "Tab") {
eid("download-button").value = '>>' eid("download-button").value = '>>'
eid("download-button").style.padding = '0 1rem' eid("download-button").style.padding = '0 1rem'
@ -257,7 +257,7 @@ async function download(url) {
} }
}).catch((error) => internetError()); }).catch((error) => internetError());
} }
window.onload = function () { window.onload = () => {
loadSettings(); loadSettings();
detectColorScheme(); detectColorScheme();
changeDownloadButton(0, '>>'); changeDownloadButton(0, '>>');
@ -274,6 +274,6 @@ window.onload = function () {
eid("url-input-area").addEventListener("keyup", (event) => { eid("url-input-area").addEventListener("keyup", (event) => {
if (event.key === 'Enter') eid("download-button").click(); if (event.key === 'Enter') eid("download-button").click();
}) })
document.onkeydown = function(event) { document.onkeydown = (event) => {
if (event.key === 'Escape') hideAllPopups(); if (event.key === 'Escape') hideAllPopups();
}; };

View file

@ -59,7 +59,7 @@
"SettingsEnableDownloadPopup": "спрашивать, как сохранять", "SettingsEnableDownloadPopup": "спрашивать, как сохранять",
"AccessibilityEnableDownloadPopup": "спрашивать, что делать с загрузками", "AccessibilityEnableDownloadPopup": "спрашивать, что делать с загрузками",
"SettingsFormatDescription": "выбирай webm, если хочешь максимальное качество. webm обычно лучше по качеству, но устройства на ios не могут проигрывать их без сторонних приложений.", "SettingsFormatDescription": "выбирай webm, если хочешь максимальное качество. webm обычно лучше по качеству, но устройства на ios не могут проигрывать их без сторонних приложений.",
"SettingsQualityDescription": "если выбранное разрешение недоступно, то выбирается ближайшее к нему. если ты хочешь твитнуть загруженное видео, то выбирай комбинацию из mp4 и 720p. такие видео твиттер обычно воспринимает намного лучше.", "SettingsQualityDescription": "если выбранное разрешение недоступно, то выбирается ближайшее к нему. если ты хочешь твитнуть загруженное видео, то выбирай комбинацию из mp4 и 720p. твиттер такие видео обычно воспринимает намного лучше.",
"DonateSubtitle": "помоги мне платить за хостинг", "DonateSubtitle": "помоги мне платить за хостинг",
"DonateDescription": "я не люблю крипто в его текущем состоянии, но у меня нет другого надёжного способа оплаты хостинга.", "DonateDescription": "я не люблю крипто в его текущем состоянии, но у меня нет другого надёжного способа оплаты хостинга.",
"LinkGitHubIssues": ">> сообщай о проблемах и смотри исходный код на github", "LinkGitHubIssues": ">> сообщай о проблемах и смотри исходный код на github",

View file

@ -87,7 +87,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
break; break;
case "vimeo": case "vimeo":
r = await vimeo({ r = await vimeo({
id: patternMatch["id"], quality: quality, id: patternMatch["id"].slice(0, 11), quality: quality,
lang: lang lang: lang
}); });
break; break;

View file

@ -1,7 +1,7 @@
import { backdropLink, checkbox, footerButtons, multiPagePopup, popup, settingsCategory, switcher } from "./elements.js";
import { services, appName, authorInfo, version, quality, repo, donations, supportedAudio } from "../config.js"; import { services, appName, authorInfo, version, quality, repo, donations, supportedAudio } from "../config.js";
import { getCommitInfo } from "../sub/currentCommit.js"; import { getCommitInfo } from "../sub/currentCommit.js";
import loc from "../../localization/manager.js"; import loc from "../../localization/manager.js";
import { backdropLink, checkbox, footerButtons, multiPagePopup, popup, settingsCategory, switcher } from "./elements.js";
import emoji from "../emoji.js"; import emoji from "../emoji.js";
let s = services; let s = services;

View file

@ -15,14 +15,16 @@ export default async function(obj) {
obj.postId = html.body.split('video/')[1].split('/?')[0] obj.postId = html.body.split('video/')[1].split('/?')[0]
} }
} }
let iteminfo = await got.get(`https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=${obj.postId}`, {headers: { let iteminfo = await got.get(`https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=${obj.postId}`, {
headers: {
'authority': 'www.iesdouyin.com', 'authority': 'www.iesdouyin.com',
'user-agent': genericUserAgent, 'user-agent': genericUserAgent,
'content-type': 'application/x-www-form-urlencoded', 'content-type': 'application/x-www-form-urlencoded',
'accept': '*/*', 'accept': '*/*',
'referer': `https://www.iesdouyin.com/share/video/${obj.postId}/?region=CN&u_code=15b9142gf&titleType=title&utm_source=copy_link&utm_campaign=client_share&utm_medium=android&app=aweme`, 'referer': `https://www.iesdouyin.com/share/video/${obj.postId}/?region=CN&u_code=15b9142gf&titleType=title&utm_source=copy_link&utm_campaign=client_share&utm_medium=android&app=aweme`,
'accept-language': 'zh-CN,zh;q=0.9,en-GB;q=0.8,en;q=0.7' 'accept-language': 'zh-CN,zh;q=0.9,en-GB;q=0.8,en;q=0.7'
}}); }
});
iteminfo.on('error', (err) => { iteminfo.on('error', (err) => {
return { error: loc(obj.lang, 'ErrorCantConnectToServiceAPI', 'douyin') }; return { error: loc(obj.lang, 'ErrorCantConnectToServiceAPI', 'douyin') };
}); });

View file

@ -41,18 +41,24 @@ export default async function (obj) {
if (!obj.isAudioOnly && videoMatch.length > 0) { if (!obj.isAudioOnly && videoMatch.length > 0) {
if (video.length > 0 && audio.length > 0) { if (video.length > 0 && audio.length > 0) {
if (videoMatch[0]["hasVideo"] && videoMatch[0]["hasAudio"]) { if (videoMatch[0]["hasVideo"] && videoMatch[0]["hasAudio"]) {
return { type: "bridge", urls: videoMatch[0]["url"], time: videoMatch[0]["approxDurationMs"], return {
filename: `youtube_${obj.id}_${videoMatch[0]["width"]}x${videoMatch[0]["height"]}.${obj.format}` }; type: "bridge", urls: videoMatch[0]["url"], time: videoMatch[0]["approxDurationMs"],
filename: `youtube_${obj.id}_${videoMatch[0]["width"]}x${videoMatch[0]["height"]}.${obj.format}`
};
} else { } else {
return { type: "render", urls: [videoMatch[0]["url"], audio[0]["url"]], time: videoMatch[0]["approxDurationMs"], return {
filename: `youtube_${obj.id}_${videoMatch[0]["width"]}x${videoMatch[0]["height"]}.${obj.format}` }; type: "render", urls: [videoMatch[0]["url"], audio[0]["url"]], time: videoMatch[0]["approxDurationMs"],
filename: `youtube_${obj.id}_${videoMatch[0]["width"]}x${videoMatch[0]["height"]}.${obj.format}`
};
} }
} else { } else {
return { error: loc(obj.lang, 'ErrorBadFetch') }; return { error: loc(obj.lang, 'ErrorBadFetch') };
} }
} else if (!obj.isAudioOnly) { } else if (!obj.isAudioOnly) {
return { type: "render", urls: [video[0]["url"], audio[0]["url"]], time: video[0]["approxDurationMs"], return {
filename: `youtube_${obj.id}_${video[0]["width"]}x${video[0]["height"]}.${video[0]["container"]}` }; type: "render", urls: [video[0]["url"], audio[0]["url"]], time: video[0]["approxDurationMs"],
filename: `youtube_${obj.id}_${video[0]["width"]}x${video[0]["height"]}.${video[0]["container"]}`
};
} else if (audio.length > 0) { } else if (audio.length > 0) {
return { type: "bridge", isAudioOnly: true, urls: audio[0]["url"], audioFilename: `youtube_${obj.id}_audio` }; return { type: "bridge", isAudioOnly: true, urls: audio[0]["url"], audioFilename: `youtube_${obj.id}_audio` };
} else { } else {

View file

@ -40,6 +40,7 @@
"enabled": true "enabled": true
}, },
"youtube": { "youtube": {
"alias": "youtube, youtube music",
"patterns": ["watch?v=:id"], "patterns": ["watch?v=:id"],
"quality_match": ["2160", "1440", "1080", "720", "480", "360", "240", "144"], "quality_match": ["2160", "1440", "1080", "720", "480", "360", "240", "144"],
"quality": { "quality": {
@ -49,18 +50,10 @@
}, },
"enabled": true "enabled": true
}, },
"youtube music": {
"patterns": ["watch?v=:id"],
"enabled": true
},
"tumblr": { "tumblr": {
"patterns": ["post/:id", "blog/view/:user/:id"], "patterns": ["post/:id", "blog/view/:user/:id"],
"enabled": true "enabled": true
}, },
"instagram": {
"patterns": [":type/:id"],
"enabled": false
},
"tiktok": { "tiktok": {
"patterns": [":user/video/:postId", ":id", "t/:id"], "patterns": [":user/video/:postId", ":id", "t/:id"],
"enabled": true "enabled": true

View file

@ -7,16 +7,13 @@ function closest(goal, array) {
} }
export default function(service, quality, maxQuality) { export default function(service, quality, maxQuality) {
if (quality == "max") { if (quality == "max") return maxQuality;
return maxQuality
}
quality = parseInt(mq[quality]) quality = parseInt(mq[quality])
maxQuality = parseInt(maxQuality) maxQuality = parseInt(maxQuality)
if (quality >= maxQuality || quality == maxQuality) { if (quality >= maxQuality || quality == maxQuality) return maxQuality;
return maxQuality
}
if (quality < maxQuality) { if (quality < maxQuality) {
if (services[service]["quality"][quality]) { if (services[service]["quality"][quality]) {
return quality return quality

View file

@ -55,27 +55,22 @@ export async function streamLiveRender(streamInfo, res) {
ffmpegProcess.on('error', (err) => { ffmpegProcess.on('error', (err) => {
ffmpegProcess.kill(); ffmpegProcess.kill();
res.end(); res.end();
return;
}); });
video.pipe(ffmpegProcess.stdio[3]).on('error', (err) => { video.pipe(ffmpegProcess.stdio[3]).on('error', (err) => {
ffmpegProcess.kill(); ffmpegProcess.kill();
res.end(); res.end();
return;
}); });
audio.pipe(ffmpegProcess.stdio[4]).on('error', (err) => { audio.pipe(ffmpegProcess.stdio[4]).on('error', (err) => {
ffmpegProcess.kill(); ffmpegProcess.kill();
res.end(); res.end();
return;
}); });
audio.on('error', (err) => { audio.on('error', (err) => {
ffmpegProcess.kill(); ffmpegProcess.kill();
res.end(); res.end();
return;
}); });
video.on('error', (err) => { video.on('error', (err) => {
ffmpegProcess.kill(); ffmpegProcess.kill();
res.end(); res.end();
return;
}); });
} else { } else {
res.end(); res.end();