Compare commits

...

11 commits

Author SHA1 Message Date
Solyn 7c7607048e
Merge ca34525fac into 080fc043ea 2024-04-30 13:54:03 +05:00
jj 080fc043ea
best audio picking improvements for youtube, tiktok, and soundcloud (#476) 2024-04-30 09:39:32 +02:00
wukko 95925c9864
soundcloud: replace filter with find and clean up 2024-04-30 13:38:01 +06:00
wukko ed8af6ca96
tiktok & soundcloud: proper best audio picking
also improved tiktok audio file naming scheme. full audio now has the "_audio_original" tag. audio extracted from video is simply "_audio".
2024-04-30 13:22:29 +06:00
wukko 276caa011a
youtube: fall back to m4a audio if opus isn't available 2024-04-30 11:24:12 +06:00
Solyn ca34525fac
Merge branch 'wukko:current' into current 2024-04-29 00:17:58 +01:00
Solyn bb6690bde4
Merge branch 'wukko:current' into current 2024-04-27 19:26:17 +01:00
Solyn 032be4103f
Merge branch 'wukko:current' into current 2024-04-20 22:01:34 +01:00
Solyn 8f1cbf44dd 📪 * Grammar fixes :/ 2024-04-20 12:36:59 +01:00
Solyn 52fa96b6b3 😳 * Fix a little oopsies 2024-04-20 12:07:35 +01:00
Solyn e0ae124ce9 🇧🇷 * Added portuguese translations 2024-04-20 12:03:58 +01:00
7 changed files with 214 additions and 61 deletions

View file

@ -157,4 +157,4 @@
"SettingsYoutubeDub": "use browser language",
"SettingsYoutubeDubDescription": "uses your browser's default language for youtube dubbed audio tracks. works even if cobalt ui isn't translated to your language."
}
}
}

View file

@ -0,0 +1,164 @@
{
"name": "Português",
"substrings": {
"ContactLink": "verifique a <a class=\"text-backdrop link\" href=\"{statusPage}\" target=\"_blank\">página de status</a> ou <a class=\"text-backdrop link\" href=\"{repo}\" target=\"_blank\">crie um problema no GitHub</a>"
},
"strings": {
"AppTitleCobalt": "cobalt",
"LinkInput": "cole o link aqui",
"AboutSummary": "cobalt é o seu lugar ideal para downloads de redes sociais e para plataformas de média. sem anúncios, rastreadores, ou outro tipo de besteiras assustadoras. simplesmente cole o link e você está pronto para arrasar!",
"EmbedBriefDescription": "salve o que você ama. sem anúncios, rastreadores, ou outras besteiras assustadoras",
"MadeWithLove": "feito com &lt;3 por wukko",
"AccessibilityInputArea": "área de entrada do link",
"AccessibilityOpenAbout": "abrir pop-up de informações",
"AccessibilityDownloadButton": "botão de download",
"AccessibilityOpenSettings": "abrir pop-up de configurações",
"AccessibilityOpenDonate": "abrir pop-up de doações",
"TitlePopupAbout": "o que é o cobalt?",
"TitlePopupSettings": "configurações",
"TitlePopupChangelog": "o que tem de novo?",
"TitlePopupDonate": "apoie o cobalt",
"TitlePopupDownload": "como salvar?",
"ErrorSomethingWentWrong": "algo de errado ocorreu e eu não consegui encontrar nada para você. tente novamente, mas se o problema continuar ocorrendo, {ContactLink}.",
"ErrorUnsupported": "parece que o serviço ainda não é suportado ou o seu link é invalido. você colou o link correto?",
"ErrorBrokenLink": "{s} é suportado, mas algo está errado com o seu link, talvez você não colou o link completo?",
"ErrorNoLink": "nãp consigo adivinhar o que você quer baixar! por favor me de um link :(",
"ErrorPageRenderFail": "se você está lendo isso, então tem algo de errado com a renderização da pagina, por favor {ContactLink} tenha certeza de providenciar o dominio que esse erro está sendo apresentado e o hash do commit ({s}). obrigado desde já :D",
"ErrorRateLimit": "você está enviando muitos pedidos. tente novamente em alguns minutos!",
"ErrorCouldntFetch": "eu não consegui encontrar nada sobre esse link. verifique se ele está funcionando e tente novamente! alguns conteúdos podem ter bloqueio regional, então tenha isso em mente. ",
"ErrorLengthLimit": "eu não consigo processar vídeos com uma duração maior que {s} minutos, então escolha algo mais curto!",
"ErrorBadFetch": "algo de errado aconteceu quando eu tentei receber informações do seu link. você tem certeza que o seu link está funcionando? verifique se está e tente novamente.",
"ErrorNoInternet": "você não está conectado a nenhuma internet ou a api do cobalt está temporariamente indisponível, verifique a sua conexão e tente novamente.",
"ErrorCantConnectToServiceAPI": "Eu não consegui conectar a api do serviço. talvez esteja fora do ar, ou o cobalt foi bloqueado. tente novamente mais tarde, mas se o problema persistir {ContactLink}.",
"ErrorEmptyDownload": "eu não encontro nada que eu possa baixar do seu link. tente um link diferente!",
"ErrorLiveVideo": "esse vídeo é uma transmissão, ainda estou para aprender como olhar para futuro. espere a transmissão acabar e tente novamente!",
"SettingsAppearanceSubtitle": "aparência",
"SettingsThemeSubtitle": "tema",
"SettingsFormatSubtitle": "formato",
"SettingsQualitySubtitle": "qualidade",
"SettingsThemeAuto": "automático",
"SettingsThemeLight": "claro",
"SettingsThemeDark": "escuro",
"SettingsKeepDownloadButton": "manter &gt;&gt; visível",
"AccessibilityKeepDownloadButton": "manter o botão de download visível",
"SettingsEnableDownloadPopup": "perguntar como salvar",
"AccessibilityEnableDownloadPopup": "perguntar o que fazer com os downloads",
"SettingsQualityDescription": "se a qualidade selecionada não estiver disponível, então a mais próxima será usada.",
"NoScriptMessage": "cobalt usa JavaScript para pedidos de API e interface interativa. você tem de permitir o acesso a JavaScript para usar esse site. não tem nenhum script irritante, promessa de mindinho.",
"DownloadPopupDescriptionIOS": "como salvar fotos:\n1. adicionar um <a class=\"text-backdrop link\" href=\"{saveToGalleryShortcut}\" target=\"_blank\">atalho para salvar para a galeria</a>.\n2. pressione o botão \"partilhar\" acima desse texto.\n3. selecione \"salvar para a galeria\" na planilha de compartilhamento i.\n\ncomo salvar o arquivo\n1. adicione um <a class=\"text-backdrop link\" href=\"{saveToFilesShortcut}\" target=\"_blank\">atalho para salvar nos ficheiros</a>.\n2. pressione o botão \"compartilhar\" acima desse texto \n3. selecione \"salvar nos ficheiros\" nessa planilha de compartilhamento.\n4. selecione a pasta que você quer salvar o arquivo e pressione \"abrir\".\n\n ambos os atalhos podem apenas ser usados na aplicação web do cobalt.",
"DownloadPopupDescription": "o botão de download abre uma nova aba com o arquivo pedido. você pode desabilitar esse pop-up nas configurações.",
"ClickToCopy": "pressione para copiar",
"Download": "baixar",
"CopyURL": "copiar",
"AboutTab": "sobre",
"ChangelogTab": "registo de mudanças",
"DonationsTab": "doações",
"SettingsVideoTab": "vídeos",
"SettingsAudioTab": "áudios",
"SettingsOtherTab": "outros",
"ChangelogLastMajor": "versão atual & commit",
"AccessibilityModeToggle": "ativar modo de download",
"DonateLinksDescription": "essa é a melhor maneira para doar se você quer que eu receba a doação diretamente.",
"SettingsAudioFormatBest": "melhor",
"SettingsAudioFormatDescription": "quando o \"melhor\" formato está selecionado, você recebe o áudio na maneira que está no lado do serviço. Ele não é recodificado. ",
"Keyphrase": "salve o que você ama",
"ErrorPopupCloseButton": "entendi",
"ErrorLengthAudioConvert": "eu não consigo converter áudios com duração maior que {s} minutos. selecione o \"melhor\" formato se você quiser evitar limitações!",
"SettingsAudioFullTikTok": "áudio completo",
"SettingsAudioFullTikTokDescription": "baixa o áudio original usado no vídeo sem mudanças adicionais pelo autor do post.",
"ErrorCantGetID": "eu não consegui obter as informações completas do link curto. tenha certeza que ele funciona ou tente um link completo! se o problema persistir, {ContactLink}.",
"ErrorNoVideosInTweet": "eu não consegui achar nenhum arquivo nesse tweet. tente um diferente!",
"ImagePickerTitle": "selecione as imagens para baixar",
"ImagePickerDownloadAudio": "baixar áudio",
"ImagePickerExplanationPC": "dê um clique direito na imagem para salvar.",
"ImagePickerExplanationPhone": "pressione e segure uma imagem para salvá-la.",
"ErrorNoUrlReturned": "eu não recebi um link de download do servidor. isso nunca deve acontecer. tente novamente, mas se ainda assim não funcionar, {ContactLink}.",
"ErrorUnknownStatus": "eu recebi uma resposta que não consigo processar. isso nunca deve acontecer. tente novamente, mas se ainda assim não funcionar, {ContactLink}.",
"PasteFromClipboard": "colar",
"ChangelogOlder": "versão anterior",
"ChangelogPressToExpand": "expandir",
"Miscellaneous": "diversos",
"ModeToggleAuto": "automático",
"ModeToggleAudio": "áudio",
"MediaPickerTitle": "selecione o que salvar",
"MediaPickerExplanationPC": "clique ou dê um clique-direito para baixar o que você quer.",
"MediaPickerExplanationPhone": "pressione ou pressione e segure para baixar o que você quer.",
"TwitterSpaceWasntRecorded": "esse espaço do Twitter não foi gravado, então não tem nada para baixar. tente com outro!",
"ErrorCantProcess": "eu não consegui processar o seu pedido :(\nvocê pode tentar novamente, mas se o problema persistir, por favor {ContactLink}.",
"ChangelogPressToHide": "esconder",
"Donate": "doar",
"DonateSub": "ajude a ficar online",
"DonateExplanation": "o cobalt não joga anúncios na sua cara e não vende as suas informações pessoais, isso significa que é <span class=\"text-backdrop\">completamente grátis</span> para todos. mas o desenvolvimento e manutenção de uma plataforma com muita média usado por aproximadamente 750 mil pessoas pode ser meio caro. tanto em termos de tempo quanto de dinheiro. \n\n se o cobalt já te ajudou no passado e se você quer que ele continue crescendo e evoluindo, você pode retribuir o favor fazendo uma doação!\n\n a sua doação vai ajudar todos os utilizadores do cobalt: educadores, estudantes, criadores de conteúdo, artistas, músicos, e muito, muito mais!\n\nno passado, doações permitiram o cobalt:\n*; aumentar a sua estabilidade e tempo de atividade para perto dos 100% .\n*; acelerar TODOS os downloads, especialmente os mais pesados.\n*; abrir a API para uso publico gratuito\n*; aguentar vários influxos de usuários com 0 tempo de inatividade\n*; adicionar funções intensivas em recursos (como a conversão de gifs).\n*; continuar a melhorar a nossa infraestrutura.\n*; deixar os desenvolvedores felizes.\n\n<span class=\"text-backdrop\">todos os centavos importam e são altamente valorizados</span>, você pode realmente fazer a diferença\n\n se você não pode doar, compartilhe o cobalt com um amigo, nos não temos anúncios em nenhum lugar, então o cobalt é espalhado de boca em boca. \ncompartilhar é a maneira mais fácil de ajudar a alcançar o objetivo de uma Internet melhor para todos.",
"DonateVia": "doar via",
"DonateHireMe": "...ou você pode <a class=\"text-backdrop link\" href=\"{s}\" target=\"_blank\">me contratar</a> :)",
"SettingsVideoMute": "silenciar áudio",
"SettingsVideoMuteExplanation": "remove o áudio do vídeo baixado quando possível.",
"ErrorSoundCloudNoClientId": "eu não consegui obter o token temporário que é necessário para baixar sons do SoundCloud. tente novamente, mas se o problema persistir, {ContactLink}.",
"CollapseServices": "serviços suportados",
"CollapseSupport": "suporte & código fonte",
"CollapsePrivacy": "politica de privacidade",
"ServicesNote": "esta lista não está finalizada e continua expandindo ao longo do tempo, tenha certeza de dar uma olhada ao longo do tempo!",
"FollowSupport": "mantenha contato com o cobalt para receber notícias, suporte e mais: ",
"SourceCode": "explore o código fonte, denuncie problemas, dê uma estrela, ou ramifique o repositório:",
"PrivacyPolicy": "a política de privacidade do cobalt é simples: nenhuma informação sua é coletada ou guardada, zero, zilch, nothing, nada.\no que você baixa é exclusivamente da sua conta, não da minha ou de mais alguém \n\nse o download necessita de renderização, então dados sobre o conteúdo pedido é encriptado e temporariamente guardado na RAM do servidor. isso é necessário para essa função funcionar\n\ndados encriptados são guardados por: <span class=\"text-backdrop\">90 segundos</span> e depois permanentemente apagadas.\n\ndados guardado são apenas possíveis de descriptografar com uma chave única do seu link de download, além disso, a base de código oficial do cobalt não fornece uma maneira para ler dados temporariamente guardados fora das funções de processamento \n\nvocê pode verificar o <a class=\"text-backdrop link\" href=\"{repo}\" target=\"_blank\">código fonte</a> do cobalt você mesmo, e verificar tudo o que é dito",
"ErrorYTUnavailable": "este vídeo do Youtube está indisponível, ele pode ter um bloqueio de região ou ter restrição de idade. tente um diferente!",
"ErrorYTTryOtherCodec": "eu não consegui encontrar nada para baixar com as suas configurações. tente outra codec ou qualidade! \n\nas vezes a api do Youtube age inesperadamente. tente novamente ou tente outra configuração.",
"SettingsCodecSubtitle": "codec do Youtube",
"SettingsCodecDescription": "h264: suporte do reprodutor geralmente melhor, mas a qualidade máxima é 1080p.\nav1: suporte de reprodutor fraco, mas suporta 8k & HDR.\nvp9: geralmente bitrates altimissimos, preserva a maioria dos detalhes. suporta 4k & HDR. \n\nselecione h264 se você quiser a melhor compatibilidade entre editor/player/redes sociais.",
"SettingsAudioDub": "faixa de áudio do Youtube",
"SettingsAudioDubDescription": "define que faixa de áudio será usada. se o áudio dublado não estiver disponível, então a linguagem original do vídeo será usada. \n\noriginal: a linguagem original do vídeo é usada. \nautomático: a linguagem padrão do seu navegador (e do cobalt) é usada.",
"SettingsDubDefault": "original",
"SettingsDubAuto": "automático",
"SettingsVimeoPrefer": "tipos de downloads do vimeo",
"SettingsVimeoPreferDescription": "progressivo: link direto da cdn do vimeo. a qualidade máxima é 1080p. \ndash: o vídeo e o áudio são misturados pelo cobalt em um arquivo. a qualidade máxima é 4k.\n\nselecione \"progressivo\" se você quiser a melhor compatibilidade entre editor/player/redes sociais..",
"ShareURL": "partilhar",
"ErrorTweetUnavailable": "não pode achar nada sobre esse tweet. isso pode ser devido a sua visibilidade limitada. tente um diferente!",
"ErrorTwitterRIP": "o Twitter restringiu o acesso a qualquer conteúdo a usuários não autenticados. embora tenha uma maneira de obter tweets regulares, os espaços são, infelizmente, impossíveis de obter neste momento. eu estou procurando possiveis soluções",
"PopupCloseDone": "feito",
"Accessibility": "acessibilidade",
"SettingsReduceTransparency": "reduzir transparência",
"SettingsDisableAnimations": "desabilitar animações",
"FeatureErrorGeneric": "o seu navegador não permite ou não suporta esta função. verifique se tem novas atualizações disponíveis e tente novamente!",
"ClipboardErrorFirefox": "você esta usando o Firefox onde todas as funções de leitura da área de transferências estão desabilitadas.\n\nvocê pode consertar isso seguindo os seguintes passos listados: <a class=\"text-backdrop link\" href=\"{repo}/blob/current/docs/troubleshooting.md#how-to-fix-clipboard-pasting-in-firefox\" target=\"_blank\">aqui!</a>\n\n... ou você pode colar o link manualmente aqui!",
"ClipboardErrorNoPermission": "o cobalt não consegue aceder ao item mais recente da sua área de transferência sem a sua permissão. \n\nse você não quiser dar acesso, então cole o link manualmente aqui .\n\nse você quiser dar permissão, vá as configurações do site e habilite as permissões de acesso a área de transferência.",
"SupportSelfTroubleshooting": "tendo problemas? tente um desses passos primeiro:",
"AccessibilityGoBack": "voltar e fechar esse pop-up",
"CollapseKeyboard": "atalhos de teclado",
"KeyboardShortcutsIntro": "uso o cobalt mais rapidamente com os atalhos de teclado: ",
"KeyboardShortcutQuickPaste": "colar o link",
"KeyboardShortcutClear": "limpar a área de entrada do link",
"KeyboardShortcutClosePopup": "fechar todos os pop-ups",
"CollapseLegal": "termos e éticas",
"FairUse": "o cobalt é uma ferramenta web que faz com que seja mais fácil baixar conteúdo da internet e não assume <span class=\"text-backdrop\">nenhuma responsabilidade</span>. servidores de processamento funcionam como <span class=\"text-backdrop\">proxies limitados</span>, então nenhum conteúdo de media é armazenado no cache ou guardado. \n\nvocê (o utilizador final) é responsável pelo que você baixa, como você usa e distribui o conteúdo. por favor, tenha em mente que ao usar conteúdo dos outros sempre dê créditos aos criadores originais. \n\nquando usado em fins educacionais (palestras, deveres de casa, etc) por favor anexe o link da fonte.\n\nuso justo e créditos beneficiam a todos.",
"SettingsDisableMetadata": "não adicionar meta dados",
"NewDomainWelcomeTitle": "olá!",
"NewDomainWelcome": "o cobalt está movendo! mesmas funções, mesmo dono, simplesmente um domínio mais lembrável. e ainda sem anúncios. \n\n<span class=\"text-backdrop\">cobalt.tools</span> é o novo domínio, também conhecido como: onde você está agora. tenha certeza de atualizar o seu marcador e reinstalar a aplicação web!",
"DataTransferSuccess": "alias, as suas funções foram transferidas automaticamente :)",
"DataTransferError": "algo de errado ocorreu ao transferir as suas preferências. você terá de abrir as configurações e configurar o cobalt manualmente.",
"SupportNotAffiliated": "o cobalt <span class=\"text-backdrop\">não é afiliado</span> com quaisquer serviços listados acima.",
"SponsoredBy": "patrocinado por",
"FilenameTitle": "estilo de nome de arquivo",
"FilenamePatternClassic": "clássico",
"FilenamePatternPretty": "bonito",
"FilenamePatternBasic": "básico",
"FilenamePatternNerdy": "nerd",
"FilenameDescription": "clássico: nome de arquivo padrão do cobalt.\nbásico: titulo e informações básicas entre parêntese.\nbonito: titulo e informações entre parêntese\nnerd: titulo e todas as informações entre parênteses\n\nalguns serviços não suportam nomes de arquivo detalhados e sempre usam o estilo clássico.",
"Preview": "previsualizar",
"FilenamePreviewVideoTitle": "Titulo do Vídeo",
"FilenamePreviewAudioTitle": "Titulo do Áudio",
"FilenamePreviewAudioAuthor": "Autor do Áudio",
"StatusPage": "pagina de estado do serviço",
"TroubleshootingGuide": "guia de autodiagnóstico",
"DonateImageDescription": "gato dormindo num teclado de Notebook e digitando letras repetidamente",
"SettingsTwitterGif": "converter gifs para .gif",
"SettingsTwitterGifDescription": "converter vídeos em loop para .gif reduz a qualidade e aumenta significativamente o tamanho do arquivo. se você quiser uma melhor eficiência, mantenha essa configuração desativada.",
"ErrorTweetProtected": "esse tweet é de uma conta privada, então eu não o consigo ver. tente um diferente!",
"ErrorTweetNSFW": "esse tweet contém conteúdo sensível, então eu não o consigo ver. tente um diferente! ",
"UpdateEncryption": "encriptação e novos serviços",
"PrivateAnalytics": "analíticas privadas",
"SettingsDisableAnalytics": "sair das analíticas privadas",
"SettingsAnalyticsExplanation": "habilite se você não quiser ser incluído nas estáticas anonimas de tráfego. leia mais sobre isso em sobre > política de privacidade (Muito Longo; Não Li: nada sobre você é armazenado ou rastreado, nenhum cookie é usado).",
"AnalyticsDescription": "cobalt utiliza uma instância plausible auto-hospedada para conseguir um número aproximado de quantas pessoas o utilizam. \n\nplausible está totalmente em conformidade com o RGPD, CCPA e PECR, não utiliza cookies e nunca guarda nenhuma informação identificável, nem mesmo o seu endereço de IP\n\ntodos os dados são agregados e nunca personalizados. nada sobre o que você baixa é salvo em qualquer lugar. é usado apenas para estáticas de tráfego anonimas, nada mais. \n\nplausible é totalmente de código aberto, que nem o cobalt, e se você quiser aprender mais sobre, você o pode fazer <a class=\"text-backdrop link\" href=\"https://plausible.io\" target=\"_blank\">aqui</a>. se você quiser sair das estáticas de trafego, você o pode fazer em configurações > outros."
}
}

View file

@ -137,40 +137,22 @@ export default function(r, host, userFormat, isAudioOnly, lang, isAudioMuted, di
audioFormat = "best"
}
const serviceBestAudio = r.bestAudio || services[host]["bestAudio"];
const isBestAudio = audioFormat === "best";
const isBestOrMp3 = audioFormat === "mp3" || isBestAudio;
const isBestAudioDefined = isBestAudio && services[host]["bestAudio"];
const isBestHostAudio = services[host]["bestAudio"] && (audioFormat === services[host]["bestAudio"]);
const isBestOrMp3 = isBestAudio || audioFormat === "mp3";
const isBestAudioDefined = isBestAudio && serviceBestAudio;
const isBestHostAudio = serviceBestAudio && (audioFormat === serviceBestAudio);
const isTikTok = host === "tiktok" || host === "douyin";
const isTumblrAudio = host === "tumblr" && !r.filename;
const isSoundCloud = host === "soundcloud";
if (isTikTok && services.tiktok.audioFormats.includes(audioFormat)) {
if (r.isMp3 && isBestOrMp3) {
audioFormat = "mp3";
processType = "bridge"
} else if (isBestAudio) {
audioFormat = "m4a";
processType = "bridge"
}
}
if (isSoundCloud && services.soundcloud.audioFormats.includes(audioFormat)) {
if (r.isMp3 && isBestOrMp3) {
audioFormat = "mp3";
processType = "render"
copy = true
} else if (isBestAudio || audioFormat === "opus") {
audioFormat = "opus";
processType = "render"
copy = true
}
}
if (isBestAudioDefined || isBestHostAudio) {
audioFormat = services[host]["bestAudio"];
audioFormat = serviceBestAudio;
processType = "bridge";
if (isSoundCloud) {
processType = "render"
copy = true
}
} else if (isBestAudio && !isSoundCloud) {
audioFormat = "m4a";
copy = true

View file

@ -4,7 +4,7 @@ import { cleanString } from "../../sub/utils.js";
const cachedID = {
version: '',
id: ''
};
}
async function findClientID() {
try {
@ -32,9 +32,7 @@ async function findClientID() {
cachedID.id = clientid;
return clientid;
} catch (e) {
return false;
}
} catch {}
}
export default async function(obj) {
@ -58,27 +56,30 @@ export default async function(obj) {
let json = await fetch(`https://api-v2.soundcloud.com/resolve?url=${link}&client_id=${clientId}`).then((r) => {
return r.status === 200 ? r.json() : false
}).catch(() => { return false });
}).catch(() => {});
if (!json) return { error: 'ErrorCouldntFetch' };
if (!json["media"]["transcodings"]) return { error: 'ErrorEmptyDownload' };
let isMp3,
selectedStream = json.media.transcodings.filter(v => v.preset === "opus_0_0")
let bestAudio = "opus",
selectedStream = json.media.transcodings.find(v => v.preset === "opus_0_0");
// fall back to mp3 if no opus is available
if (selectedStream.length === 0) {
selectedStream = json.media.transcodings.filter(v => v.preset === "mp3_0_0")
isMp3 = true
selectedStream = json.media.transcodings.find(v => v.preset === "mp3_0_0");
bestAudio = "mp3"
}
let fileUrlBase = selectedStream[0]["url"];
let fileUrlBase = selectedStream.url;
let fileUrl = `${fileUrlBase}${fileUrlBase.includes("?") ? "&" : "?"}client_id=${clientId}&track_authorization=${json.track_authorization}`;
if (fileUrl.substring(0, 54) !== "https://api-v2.soundcloud.com/media/soundcloud:tracks:") return { error: 'ErrorEmptyDownload' };
if (json.duration > maxVideoDuration) return { error: ['ErrorLengthAudioConvert', maxVideoDuration / 60000] };
if (json.duration > maxVideoDuration)
return { error: ['ErrorLengthAudioConvert', maxVideoDuration / 60000] };
let file = await fetch(fileUrl).then(async (r) => { return (await r.json()).url }).catch(() => { return false });
let file = await fetch(fileUrl).then(async (r) => { return (await r.json()).url }).catch(() => {});
if (!file) return { error: 'ErrorCouldntFetch' };
let fileMetadata = {
@ -94,7 +95,7 @@ export default async function(obj) {
title: fileMetadata.title,
author: fileMetadata.artist
},
isMp3,
bestAudio,
fileMetadata
}
}

View file

@ -41,8 +41,9 @@ export default async function(obj) {
detail = detail?.aweme_list?.find(v => v.aweme_id === postId);
if (!detail) return { error: 'ErrorCouldntFetch' };
let video, videoFilename, audioFilename, isMp3, audio, images,
filenameBase = `tiktok_${detail.author.unique_id}_${postId}`;
let video, videoFilename, audioFilename, audio, images,
filenameBase = `tiktok_${detail.author.unique_id}_${postId}`,
bestAudio = 'm4a';
images = detail.image_post_info?.images;
@ -56,12 +57,12 @@ export default async function(obj) {
} else {
let fallback = playAddr.url_list[0];
audio = fallback;
audioFilename = `${filenameBase}_audio_fv`; // fv - from video
audioFilename = `${filenameBase}_audio`;
if (obj.fullAudio || fallback.includes("music")) {
audio = detail.music.play_url.url_list[0]
audioFilename = `${filenameBase}_audio`
audioFilename = `${filenameBase}_audio_original`
}
if (audio.slice(-4) === ".mp3") isMp3 = true;
if (audio.slice(-4) === ".mp3") bestAudio = 'mp3';
}
if (video) return {
@ -72,7 +73,7 @@ export default async function(obj) {
urls: audio,
audioFilename: audioFilename,
isAudioOnly: true,
isMp3: isMp3
bestAudio
}
if (images) {
let imageLinks = [];
@ -86,13 +87,13 @@ export default async function(obj) {
urls: audio,
audioFilename: audioFilename,
isAudioOnly: true,
isMp3: isMp3
bestAudio
}
}
if (audio) return {
urls: audio,
audioFilename: audioFilename,
isAudioOnly: true,
isMp3: isMp3
bestAudio
}
}

View file

@ -4,7 +4,7 @@ import { cleanString } from '../../sub/utils.js';
const yt = await Innertube.create();
const c = {
const codecMatch = {
h264: {
codec: "avc1",
aCodec: "mp4a",
@ -23,8 +23,8 @@ const c = {
}
export default async function(o) {
let info, isDubbed,
quality = o.quality === "max" ? "9000" : o.quality; // 9000(p) - max quality
let info, isDubbed, format = o.format || "h264";
let quality = o.quality === "max" ? "9000" : o.quality; // 9000(p) - max quality
function qual(i) {
if (!i.quality_label) {
@ -56,10 +56,16 @@ export default async function(o) {
let bestQuality, hasAudio;
let adaptive_formats = info.streaming_data.adaptive_formats.filter(e =>
e.mime_type.includes(c[o.format].codec) || e.mime_type.includes(c[o.format].aCodec)
const filterByCodec = (formats) => formats.filter(e =>
e.mime_type.includes(codecMatch[format].codec) || e.mime_type.includes(codecMatch[format].aCodec)
).sort((a, b) => Number(b.bitrate) - Number(a.bitrate));
let adaptive_formats = filterByCodec(info.streaming_data.adaptive_formats);
if (adaptive_formats.length === 0 && format === "vp9") {
format = "h264"
adaptive_formats = filterByCodec(info.streaming_data.adaptive_formats)
}
bestQuality = adaptive_formats.find(i => i.has_video);
hasAudio = adaptive_formats.find(i => i.has_audio);
@ -105,14 +111,15 @@ export default async function(o) {
isAudioOnly: true,
urls: audio.decipher(yt.session.player),
filenameAttributes: filenameAttributes,
fileMetadata: fileMetadata
fileMetadata: fileMetadata,
bestAudio: format === "h264" ? 'm4a' : 'opus'
}
const matchingQuality = Number(quality) > Number(bestQuality) ? bestQuality : quality,
checkSingle = i => qual(i) === matchingQuality && i.mime_type.includes(c[o.format].codec),
checkSingle = i => qual(i) === matchingQuality && i.mime_type.includes(codecMatch[format].codec),
checkRender = i => qual(i) === matchingQuality && i.has_video && !i.has_audio;
let match, type, urls;
if (!o.isAudioOnly && !o.isAudioMuted && o.format === 'h264') {
if (!o.isAudioOnly && !o.isAudioMuted && format === 'h264') {
match = info.streaming_data.formats.find(checkSingle);
type = "bridge";
urls = match?.decipher(yt.session.player);
@ -128,8 +135,8 @@ export default async function(o) {
if (match) {
filenameAttributes.qualityLabel = match.quality_label;
filenameAttributes.resolution = `${match.width}x${match.height}`;
filenameAttributes.extension = c[o.format].container;
filenameAttributes.youtubeFormat = o.format;
filenameAttributes.extension = codecMatch[format].container;
filenameAttributes.youtubeFormat = format;
return {
type,
urls,

View file

@ -57,7 +57,6 @@
"alias": "tiktok videos, photos & audio",
"patterns": [":user/video/:postId", ":id", "t/:id", ":user/photo/:postId"],
"subdomains": ["vt", "vm"],
"audioFormats": ["best", "m4a", "mp3"],
"enabled": true
},
"douyin": {
@ -74,7 +73,6 @@
"soundcloud": {
"patterns": [":author/:song/s-:accessKey", ":author/:song", ":shortLink"],
"subdomains": ["on", "m"],
"audioFormats": ["best", "opus", "mp3"],
"enabled": true
},
"instagram": {