From df17b5b4e561f1c927d3fda765d67c618171715e Mon Sep 17 00:00:00 2001 From: Scrub <72096833+ScrubN@users.noreply.github.com> Date: Sat, 24 Feb 2024 18:44:14 -0500 Subject: [PATCH 1/8] Fix badges and bits not obeying custom scaling when the font size is set to 24 (#975) --- TwitchDownloaderCore/ChatRenderer.cs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/TwitchDownloaderCore/ChatRenderer.cs b/TwitchDownloaderCore/ChatRenderer.cs index 850aec93..1ed581e2 100644 --- a/TwitchDownloaderCore/ChatRenderer.cs +++ b/TwitchDownloaderCore/ChatRenderer.cs @@ -1628,11 +1628,11 @@ private async Task> GetScaledBadges(CancellationToken cancellati foreach (var badge in badgeTask) { // Assume badges are always 2x scale, not 1x or 4x - if (Math.Abs(renderOptions.ReferenceScale - 1.0) > 0.01) + var newScale = renderOptions.ReferenceScale * renderOptions.BadgeScale; + if (Math.Abs(newScale - 1.0) > 0.01) { - badge.Resize(renderOptions.ReferenceScale * renderOptions.BadgeScale); + badge.Resize(newScale); } - badge.VersionsData.Clear(); // Clear the image byte[]s as we aren't embedding to an output file } return badgeTask; @@ -1644,12 +1644,12 @@ private async Task> GetScaledEmotes(CancellationToken cancella foreach (var emote in emoteTask) { - double newScale = (2.0 / emote.ImageScale) * renderOptions.ReferenceScale * renderOptions.EmoteScale; + // Assume emojis are 4x scale + double newScale = emote.ImageScale * 0.5 * renderOptions.ReferenceScale * renderOptions.EmoteScale; if (Math.Abs(newScale - 1.0) > 0.01) { emote.Resize(newScale); } - emote.ImageData = Array.Empty(); // Clear the image byte[] as we aren't embedding to an output file } return emoteTask; @@ -1662,12 +1662,12 @@ private async Task> GetScaledThirdEmotes(CancellationToken can foreach (var emote in emoteThirdTask) { - double newScale = (2.0 / emote.ImageScale) * renderOptions.ReferenceScale * renderOptions.EmoteScale; + // Assume emojis are 4x scale + double newScale = emote.ImageScale * 0.5 * renderOptions.ReferenceScale * renderOptions.EmoteScale; if (Math.Abs(newScale - 1.0) > 0.01) { emote.Resize(newScale); } - emote.ImageData = Array.Empty(); // Clear the image byte[] as we aren't embedding to an output file } return emoteThirdTask; @@ -1680,14 +1680,10 @@ private async Task> GetScaledBits(CancellationToken cancellatio foreach (var cheer in cheerTask) { //Assume cheermotes are always 2x scale, not 1x or 4x - if (Math.Abs(renderOptions.ReferenceScale - 1.0) > 0.01) - { - cheer.Resize(renderOptions.ReferenceScale * renderOptions.EmoteScale); - } - - foreach (var tier in cheer.tierList) + var newScale = renderOptions.ReferenceScale * renderOptions.EmoteScale; + if (Math.Abs(newScale - 1.0) > 0.01) { - tier.Value.ImageData = Array.Empty(); // Clear the image byte[]s as we aren't embedding to an output file + cheer.Resize(newScale); } } From d1f9d424b6e17c6fdb42b89492eb757a62b1138d Mon Sep 17 00:00:00 2001 From: Wh1t3st4r <69942196+Wh1t3st4r@users.noreply.github.com> Date: Sat, 24 Feb 2024 20:44:30 -0300 Subject: [PATCH 2/8] Add Brazilian Portuguese Language (#972) * Added Brazilian Portuguese README file * Added Brazilian Portuguese Translation for the GUI application * Updated Translations Fixed a misunderstanding of trailing spaces --- README_ptbr.md | 218 +++++ .../Translations/Strings.ptbr.resx | 839 ++++++++++++++++++ 2 files changed, 1057 insertions(+) create mode 100644 README_ptbr.md create mode 100644 TwitchDownloaderWPF/Translations/Strings.ptbr.resx diff --git a/README_ptbr.md b/README_ptbr.md new file mode 100644 index 00000000..a440da51 --- /dev/null +++ b/README_ptbr.md @@ -0,0 +1,218 @@ +
+ + Logo + + +

Twitch Downloader

+ +
+ Baixador de VOD/Clip/Chat da Twitch e Renderizador de Chat +
+
+ Report Bug +
+
+ +**Este arquivo Readme pode estar desatualizado, considere lê-lo em [**inglês**](README.md)** + +## Exemplo do Chat Renderizado + +https://user-images.githubusercontent.com/1060681/197653099-c3fd12c2-f03a-4580-84e4-63ce3f36be8d.mp4 + + +## O quê ele pode fazer? + +- Baixar VODs da Twitch +- Baixar Clips da Twitch +- Baixar o chat para VODs e Clips, seja em um arquivo [JSON com todas as informações originais](https://github.com/lay295/TwitchDownloader/files/13495494/ExampleMoonMoonJsonFile.json), um arquivo de browser HTML, ou um [arquivo de texto normal](https://github.com/lay295/TwitchDownloader/files/13495523/ExampleMoonMoonTextFile.txt) +- Atualizar os conteúdos de um arquivo do chat em JSON gerado préviamente com uma opção para salvar em outro formato +- Usar um arquivo do chat em JSON gerado préviamente para renderizar o chat com o Twitter Twemoji ou Google Noto Color emojis e emotes BTTV, FFZ, 7TV estáticos e animados + +# GUI + +## Windows WPF + +![](https://i.imgur.com/bLegxGX.gif) + +### [Veja a documentação completa do WPF aqui](TwitchDownloaderWPF/README.md). + +### Funcionalidade + +O GUI do Windows WPF implementa todas as principais funcionalidades do programa acompanhado com umas funcionalidades extras de conveniência: +- Programe múltiplos trabalhos de baixar/renderizar para que funcionem simultâneamente +- Criar uma lista de arquivos para baixar por uma lista de links de vods/clips +- Buscar e baixar múltiplos VODs/clips de qualquer streamer sem sair do aplicativo + +### Suporte à Múltiplas línguas + +O GUI do Windows WPF está disponível em múltiplas linguagens graças à traduções da comunidade. Veja a [Sessão de localização](TwitchDownloaderWPF/README.md#localization) do [WPF README](TwitchDownloaderWPF/README.md) para mais detalhes. + +### Tema + +O GUI do Windows WPF vêm com tanto o tema claro como o escuro, junto de uma opção para atualizar automaticamente de acordo com o tema do Windows. Ele também suporta temas criados pelo usuário! Veja a [Sessão de Tema](TwitchDownloaderWPF/README.md#theming) dos [WPF README](TwitchDownloaderWPF/README.md) para mais detalhes. + +### Demonstração em Vídeo + +https://www.youtube.com/watch?v=0W3MhfhnYjk +(versão mais antiga, mesmo conceito) + +## Linux? + +Veja twitch-downloader-gui no [github](https://github.com/mohad12211/twitch-downloader-gui) ou no [AUR](https://aur.archlinux.org/packages/twitch-downloader-gui) para um GUI wrapper para o CLI Linux . + +## MacOS? + +Nenhum GUI disponível pro MacOS até o momento :( + +# CLI + +### [Veja a documentação completa do CLI aqui](TwitchDownloaderCLI/README.md). + +O CLI é cross-platform e implementa as principais funcionalidades do programa. Funciona no Windows, Linux, e MacOS*. + +*Somente Macs com Intel foram testadas + +Com o CLI, é possível automatizar processamento de vídeo processing com scripts externos. Por exemplo, você poderia copiar e colar o código a seguir num arquivo `.bat` no Windows para baixar um VOD e seu chat, e depois renderizar o chat, tudo de um único valor. +```bat +@echo off +set /p vodid="Insira a ID da VOD: " +TwitchDownloaderCLI.exe videodownload --id %vodid% --ffmpeg-path "ffmpeg.exe" -o %vodid%.mp4 +TwitchDownloaderCLI.exe chatdownload --id %vodid% -o %vodid%_chat.json -E +TwitchDownloaderCLI.exe chatrender -i %vodid%_chat.json -h 1080 -w 422 --framerate 30 --update-rate 0 --font-size 18 -o %vodid%_chat.mp4 +``` + +## Windows - Instalação + +1. Vá para [Releases](https://github.com/lay295/TwitchDownloader/releases/) e baixe a versão mais recente para Windows ou [construa do código-fonte](#building-from-source). +2. Extraia o `TwitchDownloaderCLI.exe`. +3. Navegue para onde você extraiu o executável: +``` +cd C:\folder\containing\TwitchDownloaderCLI +``` +4. Se você não tem o FFmpeg, você pode instalar-lo via o [gerenciador de pacotes Chocolatey](https://community.chocolatey.org/), todavia também podes obter-lo como um arquivo separado no [ffmpeg.org](https://ffmpeg.org/download.html) ou usando o TwitchDownloaderCLI: +``` +TwitchDownloaderCLI.exe ffmpeg --download +``` +5. Você pode começar a usar o TwitchDownloaderCLI, por exemplo: +``` +TwitchDownloaderCLI.exe videodownload --id -o out.mp4 +``` +Você pode encontrar mais comandos no [CLI README](TwitchDownloaderCLI/README.md#example-commands). + +## Linux – Instalação + +1. Algumas distros, como o Alpine Linux, não têm fontes para algumas linguagens (Árabe, Persa, Tailandês, etc.) Se este for seu caso, instale fontes familiares adicionais como [Noto](https://fonts.google.com/noto/specimen/Noto+Sans) ou leia a página da wiki de sua distro em fontes, tendo que deve haver um comando de instalação para essa situação específica, como a página de fontes do [Alpine Linux ](https://wiki.alpinelinux.org/wiki/Fonts). +2. Verifique que ambos `fontconfig` e `libfontconfig1` estão instalados. `apt-get install fontconfig libfontconfig1` no Ubuntu. +3. Vá para [Releases](https://github.com/lay295/TwitchDownloader/releases/) e baixe o binário mais recente pro Linux, pegue o [Pacote AUR](https://aur.archlinux.org/packages/twitch-downloader-bin/) pro Arch Linux, ou [construa do código-fonte](#building-from-source). +4. Extraia o `TwitchDownloaderCLI`. +5. Navegue para onde você extraiu o binário: +``` +cd directory/containing/TwitchDownloaderCLI +``` +6. Dê ao binário direitos de execução: +``` +sudo chmod +x TwitchDownloaderCLI +``` +7. a) Se você não tem o FFmpeg, você deve instalar-lo no sistema todo pelo gerenciador de pacotes da sua distro, todavia também podes obter-lo como um arquivo separado no [ffmpeg.org](https://ffmpeg.org/download.html) ou usando o TwitchDownloaderCLI: +``` +./TwitchDownloaderCLI ffmpeg --download +``` +7. b) Se baixado como um arquivo separado, também deve dar-lo direitos de execução com: +``` +sudo chmod +x ffmpeg +``` +8. Você pode começar usando o TwitchDownloaderCLI, por exemplo: +``` +./TwitchDownloaderCLI videodownload --id -o out.mp4 +``` +Você pode encontrar mais comandos no [CLI README](TwitchDownloaderCLI/README.md#example-commands). + +## MacOS – Instalação +1. Se seu dispositivo tem um processador série-M Apple Silicon, certifique-se que baixaste o binário do arm64, todavia se você prefere usar o binário em x64 no Apple Silicon deve ser rodado por uma sessão do terminal rodando dentro do Rosetta 2: +``` +arch -x86_64 zsh +``` +2. Vá para [Releases](https://github.com/lay295/TwitchDownloader/releases/) e baixe a versão mais recente para MacOS ou [construa do código-fonte](#building-from-source). +3. Extraia o `TwitchDownloaderCLI`. +4. Navegue para onde você extraiu o binário: +``` +cd directory/containing/TwitchDownloaderCLI +``` +5. Dê ao binário direitos de execução: +``` +chmod +x TwitchDownloaderCLI +``` +6. a) Se você não tem o FFmpeg, você deve instalar-lo no sistema todo pelo [gerenciador de pacotes Homebrew](https://brew.sh/), todavia também podes obter-lo como um arquivo separado no [ffmpeg.org](https://ffmpeg.org/download.html) ou usando o TwitchDownloaderCLI: +``` +./TwitchDownloaderCLI ffmpeg --download +``` +6. b) Se baixado como um arquivo separado, também deve dar-lo direitos de execução com: +``` +chmod +x ffmpeg +``` +7. Você pode começar a usar o TwitchDownloaderCLI, por exemplo: +``` +./TwitchDownloaderCLI videodownload --id -o out.mp4 +``` +Você pode encontrar mais comandos no [CLI README](TwitchDownloaderCLI/README.md#example-commands). + +# Construíndo do código-fonte + +## Requerimentos + +- [.NET 6.0.x SDK](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) +- Mais ou menos 1GB de espaço de disco. + +## Instruções para construção + +1. Clone o repositório: +``` +git clone https://github.com/lay295/TwitchDownloader.git +``` +2. Navegue até a pasta da solução: +``` +cd TwitchDownloader +``` +3. Restaure a solução: +``` +dotnet restore +``` +- Dispositivos que não usam Windows devem especificar explicitamente um projeto para restaurar, i.e. `dotnet restore TwitchDownloaderCLI` +4. a) Construa o GUI: +``` +dotnet publish TwitchDownloaderWPF -p:PublishProfile=Windows +``` + +- Perfis Aplicáveis: `Windows`, `Linux`, `LinuxAlpine`, `LinuxArm`, `LinuxArm64`, `MacOS`, `MacOSArm64` +5. a) Navegue para a pasta do GUI: +``` +cd TwitchDownloaderWPF/bin/Release/net6.0-windows/publish/win-x64 +``` +5. b) Navegue para a pasta do CLI: +``` +cd TwitchDownloaderCLI/bin/Release/net6.0/publish +``` + +# Créditos de terçeiros + +Renderizações do Chat são renderizadas com [SkiaSharp](https://github.com/mono/SkiaSharp) e [HarfBuzzSharp](https://github.com/mono/SkiaSharp) © Microsoft Corporation. + +Renderizações do Chat são codificados e Downloads do Vídeo são finalizados com [FFmpeg](https://ffmpeg.org/) © The FFmpeg developers. + +Renderizações do Chat devem usar [Noto Color Emoji](https://github.com/googlefonts/noto-emoji) © Google e contributors. + +Renderizações do Chat devem usar [Twemoji](https://github.com/twitter/twemoji) © Twitter e contributors. + +Binários pré-instalados do FFmpeg são pegos do [gyan.dev](https://www.gyan.dev/ffmpeg/) © Gyan Doshi. + +Binários do FFmpeg pegos são runtime são baixados usando [Xabe.FFmpeg.Downloader](https://github.com/tomaszzmuda/Xabe.FFmpeg) © Xabe. + +Exportações do Chat em Html utilizam o typeface _Inter_ hosteados pelo [Google Fonts API](https://fonts.google.com/) © Google. + +Para uma lista completa de bibliotecas externas, veja [THIRD-PARTY-LICENSES.txt](./TwitchDownloaderCore/Resources/THIRD-PARTY-LICENSES.txt). + +# Licença + +[MIT](./LICENSE.txt) + +TwitchDownloader não é de modo algum associado com a Twitch Interactive, Inc. ou suas filiais. \ No newline at end of file diff --git a/TwitchDownloaderWPF/Translations/Strings.ptbr.resx b/TwitchDownloaderWPF/Translations/Strings.ptbr.resx new file mode 100644 index 00000000..c4c3b304 --- /dev/null +++ b/TwitchDownloaderWPF/Translations/Strings.ptbr.resx @@ -0,0 +1,839 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Aceitar + + + Adicionar à Fila + + + Você selecionou um canal Alfa (transparência) para um container/codec que não o suporta. Remova transparêmcia ou codifique com MOV + RLE/PRORES ou WEBM + VP8/VP9 + + + Tema + Deixe um espaço no final + + + Clique para saber mais em como fazer seu próprio tema! + + + Parâmetros disponíveis são: + + + Cor do Plano de Fundo: + + + Lista de Palavras Banidas + Deixe um espaço no final + + + Lista de palavras banidas ou frases - separados por vírgulas, espaços ao redor das vírgulas serão ignoradas, NÃO é sensível à capitalização. + + + Navegue + + + Emotes do BTTV: + + + Pasta de Cache: + + + Chats: + + + Filtro de Insígnia do Chat: + + + Insígnia do Chat: + + + Corte: + + + Fazer o download o Chat + + + Downloads do Chat + + + Fonte: + + + Tamanho da Fonte: + + + Altura: + + + Renderização do Chat + + + Renderizações do Chat + + + Atualização do Chat + + + Atualizador do Chat + + + Largura: + + + Limpar + + + Tem certeza que quer limpar seu cache?\nFazei isso somente se o aplicativo não estiver funcionando corretamente + + + Fazer o download o Clip + + + Downloads de Clips + + + Link/ID do Clip: + + + Clips: + + + Fim + + + Começo + + + Cortar o Vídeo: + + + A formatação date_custom é baseada no + + + Strings no formato padrão de data e tempo do C# + + + Deletar a Confirmation + + + Usa o programa regularmente e quer me ajudar? Compre-me um café :) + + + Download + + + Conexões: + + + Templates de Nomes do Arquivo de Download: + + + Formato de Download: + + + Processos do Download: + + + Imagens imbutidas + Deixe um espaço no final + + + Embuta emotes first party, insígnias, e cheermotes no arquivo de download para renderização offline. Útil para propósitos de preservação, o tamanho do arquivo será maior. + + + Embuta os Perdidos + Deixe um espaço no final + + + Embuta emotes perdidos, insígnias, e cheermotes. Imagens já imbutidas serão tocadas. + + + Faça o Download da Fila + + + Faça a Renderização da Fila + + + Atualize a Fila + + + ERRO: + Deixe um espaço no final + + + Insira Argumentos: + + + Clique aqui para aprender sobre as opções do FFmpeg + + + Output dos Argumentos: + + + {fps} {height} {width} {max_int} {save_path} + Não traduza + + + Restaurar para os padrões + + + Emotes do FFZ: + + + {title} {id} {date} {channel} {date_custom=""} {random_string} {crop_start} {crop_end} {crop_start_custom=""} {crop_end_custom=""} {length} {length_custom=""} {views} {game} + Não traduza + + + Cor da Fonte: + + + Gerar uma máscara: + + + Pegar Informações + + + Esconder o botão de Doação: + + + Ignorar a Lista de Usuários + Deixe um espaço no final + + + Lista de nomes de usuário - separados por vírgulas, espaços ao redor das vírgulas serão ignoradas, NÃO é sensível à capitalização. + + + Link/ID do Clip é Inválido + + + Por favor coloque um Link/ID válido\nExemplos:\nhttps://clips.twitch.tv/ImportantPlausibleMetalOSsloth\nImportantPlausibleMetalOSsloth + + + Dados de Corte Inválidos + + + Tempo de início ou fim Inválidos + + + Link/ID do vídeo é Inválido + + + Por favor coloque um Link/ID de vídeo válido\nExamples:\nhttps://www.twitch.tv/videos/470741744\n470741744 + + + Aqrquivo JSON: + + + Comprimento: + + + Lista de VODs/Clips (Um por linha) + + + Relatório: + + + Downloads em Massa + + + OAuth (opcional) + Deixe um espaço no final + + + Requerido apenas para VODs disponíveis só pra subs. Todos tokens OAuth 3rd party não funcionarão. Clique para ver um vídeo do YouTube em como obter seu token OAuth. + + + Offline + Deixe um espaço no final + + + Renderizar o chat usando somente recursos embutidos no arquivp do chat em json. + + + Linha de cobertura: + + + Limites de Trabalhos em Paralelo + + + Renderização Parcial + + + Qualidade: + + + Renderizar + + + Isto é somente para usuários avançados. Se teres um erro 'pipe ended', este provavelmente é o motivo. + + + Formato de arquivo: + + + Framerate: + + + Codec: + + + Codificação + + + FFmpeg + + + Geral + + + Prévia + + + Renderizando + + + Dimensionamento + + + Largura e altura devem ser uniformes + + + Trocar Embutidos + Deixe um espaço no final + + + Trocar todos os emotes embutidos, insígnias, e cheermotes no arquivo. Todas imagens embutidas serão sobrescritos! + + + Procurar Clips + + + Procurar VODs + + + Selecionar Todos + + + Itens Selecionados: + + + Colocar Canal + + + Organizar: + + + Feito + + + Baixando + + + ERRO + + + Dormindo + + + Renderizando + + + Atualizando + + + Streamer: + + + Emotes 7TV: + + + Mensagens de Sub: + + + Cancelar + + + Erro + + + Fila de Trabalhos + + + Emotes 3rd Party + Deixe um espaço no final + + + Também embuta emotes third party no arquivo. O tamanho do arquivo será muito mais largo. + + + Formato de Tempo: + + + Nenhum + + + Relativo + + + Tempos: + + + UTC + + + Maior De todos os Tempos + + + Maior em 7 Dias + + + Maior em 30 Dias + + + Maior em 24 Horas + + + Incapaz de achar a thumbnail + + + Incapaz de pegar informações do Clip. Por favor verifique o ID do Clip e tente novamente. + + + Incapaz de pegar a informação + + + Incapaz de pegar a informação do Video/Clip. Por favor verifique o link e tente novamente. + + + Incapaz de pegar a informação do Vídeo. Por favor verifique se o Link/ID está correto e tente novamente. + + + Incapaz de pegar argumentos + + + Por favor verifique se os argumentos são válidos + + + Incapaz de pegar o link + + + Por favor verifique o link do VOD/Clip + + + Desconhecido + + + Atualizar + + + Taxa de Atualização: + + + Lista de URL + + + Saída de Erros com Ladainha + + + Erros com Ladainha: + + + Criado: + + + Título: + + + Link do VOD/Clip: + + + Download da VOD + + + Downloads de VODs + + + Vídeo está expirado ou o ID embutido está corrupto + + + Link/ID da VOD: + + + VODs: + + + Download do Chat + + + Pasta de Download: + + + Download do Vídeo + + + Linguagem + Deixe um espaço no final + + + Renderizar o Chat + + + Marcar a Escala de Corte: + + + Marcar a Escala de Marcação: + + + Escala de Insígnia: + + + Escala de Emoji: + + + Escala de Emote: + + + Escala de Espaçamento de Emote: + + + Escala de Preenchimento Lateral: + + + Escala da Seção de Altura: + + + Escala de Espaçamento Vertical: + + + Escala do Espaçamento de Palavras: + + + Arquivo não Encontrado: + Deixe um espaço no final + + + Erro Fatal + + + Tema não encontrado + + + {theme} não foi encontrado. Revertendo tema pro Sistema + Não Traduza {theme} + + + Dispersação + Deixe um espaço no final + + + Em Novembro de 2022 uma mudança do API da Twitch fez mensagens do chat baixar somente em segundos inteiros. Esta opção usa metadados adicionais para tentar restaurar mensagens quando elas foram realmente enviadas. Isto deve resultar em uma ordem de comentários diferente. + + + Compressão: + + + Nenhuma + + + Gzip + Não Traduza + + + Alguns temas inclusos falharam a serem escritas. + + + Configurações Globais + + + Opções de Fila + + + Selecione a Faixa a ser Renderizada(Segundos) + + + Download em Massa da Lista de URL + + + Download em Massa de Vídeo + + + Download em Massa de Clip + + + O TwitchDownloaderWPF não está disponível em sua languagem nativa? Clique para aprender como ajudar a traduzir! + + + Diretório da Pasta Inválido + + + A pasta não existe + + + Cancelado + + + Cancelando + + + Banda Máxima de Processo Deixe um espaço no final + + + A banda máxima que um novo processo de download será permitido a usar, em kibibytes por segundo. + + + Clareando: + + + Local + + + Formato de Tempo: + + + Nenhum arquivo JSON selecionado + + + Acesso insuficiente. OAuth deve ser necessário. + + + Provedor do Emoji: + + + Google + + + Twitter + + + Nenhum + + + Você selecionou gerar uma máscara com um plano de fundo opaco. Reduza a cor alfa do plano de fundo ou desabilite o gerar máscara. + + + Escala de Cobertura: + + + Formatações crop_start_custom, crop_end_custom, e length_custom são baseados no + + + Strings de Formato TimeSpan padrão do C# + + + Um erro desconhecido ocorreu + + + O trabalgo não pôde ser removido + + + Por favor cancele o trabalho ou espere-o terminar antes de removê-lo + + + Incapaz de baixar o FFmpeg + + + Incapaz de baixar o FFmpeg. Por favor baixe-o manualmenmte do {0} e coloque o arquivo no {1} + + + Cor do Plano de Fundo Alternativo: + + + Planos de Fundo Alternativos Deixe um espaço no final + + + Alterna as cores do plano de fundo de cada mensagem do chat para ajudar a diferenciá-los. + + + Metadados de Codificação: + + + Erro + + + Incapaz de iniciar o aplicativo de leitor de temas do Windows. Sincronização de tema em tempo-real do Windows foi desabilitado. Código de erro: {0} + + + Vídeos por página: + + + Baixando FFmpeg {0}% + + + Copiar ID pra área de transferência + + + Copiar URL pra área de transferência + + + Abrir no navegador + + + Tem certeza que queres restaurar todas as configurações para seus padrões? + + + Confirmação de Restauracão de Configurações + + + O aplicativo deve ser reiniciado para que as mudanças tenham efeito. + + + Por favor reinicie {0}{0} é o nome do aplicativo. + + + Restaurar Padrões + + + Salvar + + + Cancelar + + + Remover + + + Abrir pasta + + + Qualidade Preferida: + + + Selecione caches para deletar + + + Tamanho Total: + + + Deletar + + + Diretório + + + Idade + + + Tamanho + + + {0:N0} dias + + \ No newline at end of file From 8e648627bfc27871542ae7b30625ab433d8b235f Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Sat, 24 Feb 2024 18:46:11 -0500 Subject: [PATCH 3/8] Enable Brazilian Portuguese --- TwitchDownloaderWPF/Services/AvailableCultures.cs | 1 + .../Translations/{Strings.ptbr.resx => Strings.pt-br.resx} | 0 TwitchDownloaderWPF/TwitchDownloaderWPF.csproj | 3 +++ 3 files changed, 4 insertions(+) rename TwitchDownloaderWPF/Translations/{Strings.ptbr.resx => Strings.pt-br.resx} (100%) diff --git a/TwitchDownloaderWPF/Services/AvailableCultures.cs b/TwitchDownloaderWPF/Services/AvailableCultures.cs index 846ca23b..5673c868 100644 --- a/TwitchDownloaderWPF/Services/AvailableCultures.cs +++ b/TwitchDownloaderWPF/Services/AvailableCultures.cs @@ -40,6 +40,7 @@ static AvailableCultures() French = new Culture("fr-FR", "Français"), Italian = new Culture("it-it", "Italiano"), Polish = new Culture("pl-PL", "Polski"), + Polish = new Culture("pt-BR", "Português (Brasil)"), Russian = new Culture("ru-RU", "Русский"), Turkish = new Culture("tr-TR", "Türkçe"), Ukrainian = new Culture("uk-ua", "Українська"), diff --git a/TwitchDownloaderWPF/Translations/Strings.ptbr.resx b/TwitchDownloaderWPF/Translations/Strings.pt-br.resx similarity index 100% rename from TwitchDownloaderWPF/Translations/Strings.ptbr.resx rename to TwitchDownloaderWPF/Translations/Strings.pt-br.resx diff --git a/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj b/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj index 516a06fd..f7845c09 100644 --- a/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj +++ b/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj @@ -50,6 +50,9 @@ Always + + Strings.resx + From 2e63734cb377c324ddd64b04e890e532123d7515 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Sat, 24 Feb 2024 18:50:45 -0500 Subject: [PATCH 4/8] Grow the settings window to fit its content --- TwitchDownloaderWPF/WindowQueueOptions.xaml | 4 ++-- TwitchDownloaderWPF/WindowSettings.xaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/TwitchDownloaderWPF/WindowQueueOptions.xaml b/TwitchDownloaderWPF/WindowQueueOptions.xaml index a42902a9..4c8680e5 100644 --- a/TwitchDownloaderWPF/WindowQueueOptions.xaml +++ b/TwitchDownloaderWPF/WindowQueueOptions.xaml @@ -10,14 +10,14 @@ lex:ResxLocalizationProvider.DefaultAssembly="TwitchDownloaderWPF" lex:ResxLocalizationProvider.DefaultDictionary="Strings" mc:Ignorable="d" - Title="Queue Options" MinHeight="280" Height="280" MinWidth="500" Width="500" Loaded="Window_loaded"> + Title="Queue Options" MinHeight="280" Height="280" MinWidth="500" Width="500" SizeToContent="WidthAndHeight" Loaded="Window_loaded" Background="{DynamicResource AppBackground}"> - + diff --git a/TwitchDownloaderWPF/WindowSettings.xaml b/TwitchDownloaderWPF/WindowSettings.xaml index 67b9c24a..611f8456 100644 --- a/TwitchDownloaderWPF/WindowSettings.xaml +++ b/TwitchDownloaderWPF/WindowSettings.xaml @@ -12,14 +12,14 @@ xmlns:hc="https://handyorg.github.io/handycontrol" xmlns:fa="http://schemas.fontawesome.com/icons/" mc:Ignorable="d" - Title="Global Settings" MinWidth="400" MinHeight="500" Width="500" Height="592" Initialized="Window_Initialized" Closing="Window_Closing" Loaded="Window_Loaded"> + Title="Global Settings" MinWidth="400" MinHeight="500" Width="500" Height="592" SizeToContent="Height" Initialized="Window_Initialized" Closing="Window_Closing" Loaded="Window_Loaded" Background="{DynamicResource AppBackground}"> - + From e3e545bfeda82d9892bc41c41da4924e11a7e7f0 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Sun, 25 Feb 2024 14:43:37 -0500 Subject: [PATCH 5/8] Bump nuget packages --- .../TwitchDownloaderCore.Tests.csproj | 8 ++++---- TwitchDownloaderCore/TwitchDownloaderCore.csproj | 2 +- TwitchDownloaderWPF/TwitchDownloaderWPF.csproj | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/TwitchDownloaderCore.Tests/TwitchDownloaderCore.Tests.csproj b/TwitchDownloaderCore.Tests/TwitchDownloaderCore.Tests.csproj index f40b648e..fb3f9312 100644 --- a/TwitchDownloaderCore.Tests/TwitchDownloaderCore.Tests.csproj +++ b/TwitchDownloaderCore.Tests/TwitchDownloaderCore.Tests.csproj @@ -11,13 +11,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/TwitchDownloaderCore/TwitchDownloaderCore.csproj b/TwitchDownloaderCore/TwitchDownloaderCore.csproj index 9c024fe3..4aba8314 100644 --- a/TwitchDownloaderCore/TwitchDownloaderCore.csproj +++ b/TwitchDownloaderCore/TwitchDownloaderCore.csproj @@ -30,7 +30,7 @@ - + diff --git a/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj b/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj index f7845c09..069f590b 100644 --- a/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj +++ b/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj @@ -60,13 +60,13 @@ - + - + From 03ef16d97973419d50b13cf34b2b5a198ec5c0ec Mon Sep 17 00:00:00 2001 From: superbonaci Date: Sun, 25 Feb 2024 19:57:01 +0000 Subject: [PATCH 6/8] Fixes #848 add CLI mode to manually concatenate ts parts (#888) * #tsmerge Update README.md * #tsmerge Update Program.cs * #tsmerge Add MergeTS.cs * #tsmerge Add TsMergeArgs.cs * #tsmerge Add TsMerger.cs * #tsmerge Add TsMergeOptions.cs * Update Program.cs Try to fix weird GitHub errors. * #tsmerge Update README.md * Program.cs Remove newline at the end * Delete TwitchDownloaderCLI/Program.cs * Try to upload again Program.cs * Delete TwitchDownloaderCLI/README.md * Add files via upload * Delete TwitchDownloaderCLI/Program.cs * Add files via upload * Delete TwitchDownloaderCore/TsMerger.cs * Add files via upload * Delete TwitchDownloaderCLI/Modes/Arguments/TsMergeArgs.cs * Add files via upload * Delete TwitchDownloaderCLI/Modes/Arguments/TsMergeArgs.cs * Add files via upload * Delete TwitchDownloaderCore/TsMerger.cs * Add files via upload * Delete TwitchDownloaderCLI/Modes/Arguments/TsMergeArgs.cs * Add files via upload * Delete TwitchDownloaderCore/TsMergeArgs.cs * Add files via upload * Delete TwitchDownloaderCLI/README.md * Add files via upload * Cleanup code and fix Readme entry * Cleanup --------- Co-authored-by: ScrubN <72096833+ScrubN@users.noreply.github.com> --- .../Modes/Arguments/TsMergeArgs.cs | 17 +++ TwitchDownloaderCLI/Modes/MergeTs.cs | 35 +++++ TwitchDownloaderCLI/Program.cs | 5 +- TwitchDownloaderCLI/README.md | 21 +++ .../Options/TsMergeOptions.cs | 8 + TwitchDownloaderCore/TsMerger.cs | 142 ++++++++++++++++++ 6 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 TwitchDownloaderCLI/Modes/Arguments/TsMergeArgs.cs create mode 100644 TwitchDownloaderCLI/Modes/MergeTs.cs create mode 100644 TwitchDownloaderCore/Options/TsMergeOptions.cs create mode 100644 TwitchDownloaderCore/TsMerger.cs diff --git a/TwitchDownloaderCLI/Modes/Arguments/TsMergeArgs.cs b/TwitchDownloaderCLI/Modes/Arguments/TsMergeArgs.cs new file mode 100644 index 00000000..1b7fffbe --- /dev/null +++ b/TwitchDownloaderCLI/Modes/Arguments/TsMergeArgs.cs @@ -0,0 +1,17 @@ +using CommandLine; + +namespace TwitchDownloaderCLI.Modes.Arguments +{ + [Verb("tsmerge", HelpText = "Concatenates multiple .ts/.tsv/.tsa/.m2t/.m2ts (MPEG Transport Stream) files into a single file")] + public class TsMergeArgs : ITwitchDownloaderArgs + { + [Option('i', "input", Required = true, HelpText = "Path a text file containing the absolute paths of the files to concatenate, separated by newlines. M3U/M3U8 is also supported.")] + public string InputList { get; set; } + + [Option('o', "output", Required = true, HelpText = "Path to output file.")] + public string OutputFile { get; set; } + + [Option("banner", Default = true, HelpText = "Displays a banner containing version and copyright information.")] + public bool? ShowBanner { get; set; } + } +} diff --git a/TwitchDownloaderCLI/Modes/MergeTs.cs b/TwitchDownloaderCLI/Modes/MergeTs.cs new file mode 100644 index 00000000..13c41c65 --- /dev/null +++ b/TwitchDownloaderCLI/Modes/MergeTs.cs @@ -0,0 +1,35 @@ +using System; +using System.Threading; +using TwitchDownloaderCLI.Modes.Arguments; +using TwitchDownloaderCLI.Tools; +using TwitchDownloaderCore; +using TwitchDownloaderCore.Options; + +namespace TwitchDownloaderCLI.Modes +{ + internal static class MergeTs + { + internal static void Merge(TsMergeArgs inputOptions) + { + Console.WriteLine("[INFO] The TS merger is experimental and is subject to change without notice in future releases."); + + Progress progress = new(); + progress.ProgressChanged += ProgressHandler.Progress_ProgressChanged; + + var mergeOptions = GetMergeOptions(inputOptions); + TsMerger tsMerger = new(mergeOptions, progress); + tsMerger.MergeAsync(new CancellationToken()).Wait(); + } + + private static TsMergeOptions GetMergeOptions(TsMergeArgs inputOptions) + { + TsMergeOptions mergeOptions = new() + { + OutputFile = inputOptions.OutputFile, + InputFile = inputOptions.InputList + }; + + return mergeOptions; + } + } +} diff --git a/TwitchDownloaderCLI/Program.cs b/TwitchDownloaderCLI/Program.cs index 23121d65..4e40a757 100644 --- a/TwitchDownloaderCLI/Program.cs +++ b/TwitchDownloaderCLI/Program.cs @@ -24,7 +24,7 @@ private static void Main(string[] args) config.HelpWriter = null; // Use null instead of TextWriter.Null due to how CommandLine works internally }); - var parserResult = parser.ParseArguments(preParsedArgs); + var parserResult = parser.ParseArguments(preParsedArgs); parserResult.WithNotParsed(errors => WriteHelpText(errors, parserResult, parser.Settings)); CoreLicensor.EnsureFilesExist(AppContext.BaseDirectory); @@ -37,7 +37,8 @@ private static void Main(string[] args) .WithParsed(UpdateChat.Update) .WithParsed(RenderChat.Render) .WithParsed(FfmpegHandler.ParseArgs) - .WithParsed(CacheHandler.ParseArgs); + .WithParsed(CacheHandler.ParseArgs) + .WithParsed(MergeTs.Merge); } private static void WriteHelpText(IEnumerable errors, ParserResult parserResult, ParserSettings parserSettings) diff --git a/TwitchDownloaderCLI/README.md b/TwitchDownloaderCLI/README.md index 2a23c703..5d4b5ebe 100644 --- a/TwitchDownloaderCLI/README.md +++ b/TwitchDownloaderCLI/README.md @@ -1,5 +1,6 @@ # TwitchDownloaderCLI A cross platform command line tool that can do the main functions of the GUI program, which can download VODs/Clips/Chats and render chats. +Also can concatenate/combine/merge Transport Stream files, either those parts downloaded with the CLI itself or from another source. - [TwitchDownloaderCLI](#twitchdownloadercli) - [Arguments for mode videodownload](#arguments-for-mode-videodownload) @@ -9,6 +10,7 @@ A cross platform command line tool that can do the main functions of the GUI pro - [Arguments for mode chatrender](#arguments-for-mode-chatrender) - [Arguments for mode ffmpeg](#arguments-for-mode-ffmpeg) - [Arguments for mode cache](#arguments-for-mode-cache) + - [Arguments for mode tsmerge](#arguments-for-mode-tsmerge) - [Example Commands](#example-commands) - [Additional Notes](#additional-notes) @@ -343,6 +345,18 @@ Other = `1`, Broadcaster = `2`, Moderator = `4`, VIP = `8`, Subscriber = `16`, P **--banner** (Default: `true`) Displays a banner containing version and copyright information. +## Arguments for mode tsmerge +#### Concatenates multiple .ts/.tsv/.tsa/.m2t/.m2ts (MPEG Transport Stream) files into a single file + +**-i / --input (REQUIRED)** +Path a text file containing the absolute paths of the files to concatenate, separated by newlines. M3U/M3U8 is also supported. + +**-o / --output (REQUIRED)** +File the program will output to. + +**--banner** +(Default: `true`) Displays a banner containing version and copyright information. + --- ## Example Commands @@ -394,6 +408,10 @@ Clear the default TwitchDownloader cache folder ./TwitchDownloaderCLI cache --clear +Concatenate several ts files into a single output file + + TwitchDownloaderCLI tsmerge -i list.txt -o output.ts + Print the available operations ./TwitchDownloaderCLI help @@ -415,3 +433,6 @@ Default true boolean flags must be assigned: `--default-true-flag=false`. Defaul For Linux users, ensure both `fontconfig` and `libfontconfig1` are installed. `apt-get install fontconfig libfontconfig1` on Ubuntu. Some distros, like Linux Alpine, lack fonts for some languages (Arabic, Persian, Thai, etc.) If this is the case for you, install additional fonts families such as [Noto](https://fonts.google.com/noto/specimen/Noto+Sans) or check your distro's wiki page on fonts as it may have an install command for this specific scenario, such as the [Linux Alpine](https://wiki.alpinelinux.org/wiki/Fonts) font page. + +The list file for `tsmerge` may contain relative or absolute paths, with one path per line. +Alternatively, the list file may also be an M3U8 playlist file. \ No newline at end of file diff --git a/TwitchDownloaderCore/Options/TsMergeOptions.cs b/TwitchDownloaderCore/Options/TsMergeOptions.cs new file mode 100644 index 00000000..8dd41e29 --- /dev/null +++ b/TwitchDownloaderCore/Options/TsMergeOptions.cs @@ -0,0 +1,8 @@ +namespace TwitchDownloaderCore.Options +{ + public class TsMergeOptions + { + public string OutputFile { get; set; } + public string InputFile { get; set; } + } +} diff --git a/TwitchDownloaderCore/TsMerger.cs b/TwitchDownloaderCore/TsMerger.cs new file mode 100644 index 00000000..e3e54128 --- /dev/null +++ b/TwitchDownloaderCore/TsMerger.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; + +namespace TwitchDownloaderCore +{ + public sealed class TsMerger + { + private readonly TsMergeOptions mergeOptions; + private readonly IProgress _progress; + + public TsMerger(TsMergeOptions tsMergeOptions, IProgress progress) + { + mergeOptions = tsMergeOptions; + _progress = progress; + } + + public async Task MergeAsync(CancellationToken cancellationToken) + { + if (!File.Exists(mergeOptions.InputFile)) + { + throw new FileNotFoundException("Input file does not exist"); + } + + var isM3U8 = false; + var fileList = new List(); + await using (var fs = File.Open(mergeOptions.InputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + using var sr = new StreamReader(fs); + while (await sr.ReadLineAsync() is { } line) + { + if (string.IsNullOrWhiteSpace(line)) continue; + + if (isM3U8) + { + if (line.StartsWith('#')) continue; + } + else + { + if (line.StartsWith("#EXTM3U")) isM3U8 = true; + } + + fileList.Add(line); + } + } + + _progress.Report(new ProgressReport(ReportType.SameLineStatus, "Verifying Parts 0% [1/2]")); + + await VerifyVideoParts(fileList, cancellationToken); + + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Combining Parts 0% [2/2]" }); + + await CombineVideoParts(fileList, cancellationToken); + + _progress.Report(new ProgressReport(100)); + } + + private async Task VerifyVideoParts(IReadOnlyCollection fileList, CancellationToken cancellationToken) + { + var failedParts = new List(); + var partCount = fileList.Count; + var doneCount = 0; + + foreach (var part in fileList) + { + var isValidTs = await VerifyVideoPart(part); + if (!isValidTs) + { + failedParts.Add(part); + } + + doneCount++; + var percent = (int)(doneCount / (double)partCount * 100); + _progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Verifying Parts {percent}% [1/2]")); + _progress.Report(new ProgressReport(percent)); + + cancellationToken.ThrowIfCancellationRequested(); + } + + if (failedParts.Count != 0) + { + if (failedParts.Count == fileList.Count) + { + // Every video part returned corrupted, probably a false positive. + return; + } + + _progress.Report(new ProgressReport(ReportType.Log, $"The following TS files are invalid or corrupted: {string.Join(", ", failedParts)}")); + } + } + + private static async Task VerifyVideoPart(string filePath) + { + const int TS_PACKET_LENGTH = 188; // MPEG TS packets are made of a header and a body: [ 4B ][ 184B ] - https://tsduck.io/download/docs/mpegts-introduction.pdf + + if (!File.Exists(filePath)) + { + return false; + } + + await using var fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); + var fileLength = fs.Length; + if (fileLength == 0 || fileLength % TS_PACKET_LENGTH != 0) + { + return false; + } + + return true; + } + + private async Task CombineVideoParts(IReadOnlyCollection fileList, CancellationToken cancellationToken) + { + DriveInfo outputDrive = DriveHelper.GetOutputDrive(mergeOptions.OutputFile); + string outputFile = mergeOptions.OutputFile; + + int partCount = fileList.Count; + int doneCount = 0; + + await using var outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.Read); + foreach (var partFile in fileList) + { + await DriveHelper.WaitForDrive(outputDrive, _progress, cancellationToken); + + await using (var fs = File.Open(partFile, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + await fs.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false); + } + + doneCount++; + int percent = (int)(doneCount / (double)partCount * 100); + _progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Combining Parts {percent}% [2/2]")); + _progress.Report(new ProgressReport(percent)); + + cancellationToken.ThrowIfCancellationRequested(); + } + } + } +} From 5e08193a94ac4b6fadaa1f168128e13cb8402033 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Sun, 25 Feb 2024 15:01:16 -0500 Subject: [PATCH 7/8] Update readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 89bbb469..7cd24950 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ This document is also available in: - [**Spanish / Español**](README_es.md) - [**Italian / Italiano**](README_it.md) +- [**Portuguese (Brazil) / Português (Brasil)**](README_ptbr.md) - [**Turkish / Türkçe**](README_tr.md) ## Chat Render Example From 1afcc3ce2166ab128cb6ca0463fae46acc2e59b5 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Sun, 25 Feb 2024 15:02:29 -0500 Subject: [PATCH 8/8] Bump version --- TwitchDownloaderCLI/TwitchDownloaderCLI.csproj | 2 +- TwitchDownloaderWPF/MainWindow.xaml.cs | 2 +- TwitchDownloaderWPF/Services/ThumbnailService.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj b/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj index 1515eb60..7cb7e691 100644 --- a/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj +++ b/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj @@ -2,7 +2,7 @@ Exe - 1.54.0 + 1.54.1 Copyright © lay295 and contributors Download and render Twitch VODs, clips, and chats MIT diff --git a/TwitchDownloaderWPF/MainWindow.xaml.cs b/TwitchDownloaderWPF/MainWindow.xaml.cs index f23f4cc3..603581bb 100644 --- a/TwitchDownloaderWPF/MainWindow.xaml.cs +++ b/TwitchDownloaderWPF/MainWindow.xaml.cs @@ -78,7 +78,7 @@ private async void Window_Loaded(object sender, RoutedEventArgs e) // it will sometimes start behind other windows, usually (but not always) due to the user's actions. FlashTaskbarIconIfNotForeground(TimeSpan.FromSeconds(3)); - var currentVersion = Version.Parse("1.54.0"); + var currentVersion = Version.Parse("1.54.1"); Title = $"Twitch Downloader v{currentVersion}"; // TODO: extract FFmpeg handling to a dedicated service diff --git a/TwitchDownloaderWPF/Services/ThumbnailService.cs b/TwitchDownloaderWPF/Services/ThumbnailService.cs index 60670be5..76c131c2 100644 --- a/TwitchDownloaderWPF/Services/ThumbnailService.cs +++ b/TwitchDownloaderWPF/Services/ThumbnailService.cs @@ -6,7 +6,7 @@ namespace TwitchDownloaderWPF.Services { public static class ThumbnailService { - public const string THUMBNAIL_MISSING_URL = @"https://vod-secure.twitch.tv/_404/404_processing_320x180.png"; + internal const string THUMBNAIL_MISSING_URL = @"https://vod-secure.twitch.tv/_404/404_processing_320x180.png"; /// The was public static BitmapImage GetThumb(string thumbUrl, BitmapCacheOption cacheOption = BitmapCacheOption.OnLoad)