forked from Tyrrrz/YoutubeDownloader
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0bfbd57
Showing
198 changed files
with
12,486 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# User-specific files | ||
.vs/ | ||
.idea/ | ||
*.suo | ||
*.user | ||
|
||
# Build results | ||
bin/ | ||
obj/ | ||
|
||
# Test results | ||
TestResults/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<Project> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0-windows</TargetFramework> | ||
<Version>2.38</Version> | ||
<Company>Reawoken</Company> | ||
<Copyright>Copyright (C) Reawoken</Copyright> | ||
<LangVersion>preview</LangVersion> | ||
<Nullable>enable</Nullable> | ||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
</PropertyGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<configuration> | ||
<packageSources> | ||
<clear /> | ||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> | ||
</packageSources> | ||
<config> | ||
<add key="defaultPushSource" value="https://api.nuget.org/v3/index.json" /> | ||
</config> | ||
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Денацифицированный YoutubeDownloader (RU) | ||
**YoutubeDownloaderRU** основан на данном репозитории: https://github.com/Tyrrrz/YoutubeDownloader | ||
|
||
# Как скачать | ||
Последняя версия: v2.38 | ||
<br />Дата: 13.01.2024 | ||
<br />Ссылка в **Releases** : [Нажмите, чтобы скачать](https://github.com/reawoken/YoutubeDownloaderRU/releases/download/v2.38/YoutubeDownloaderRU.v2.38.zip) | ||
|
||
# Почему я сделал YoutubeDownloaderRU | ||
Чтобы каждый мог им пользоваться, независимо от идеологии и местопложения. Автор данного приложения закоренелый нацист и русособ, который распространяет недопустимую пропаганду в приложении, вообще не имеющем отношения к политике, войнам и прочему. | ||
|
||
# Что было изменено | ||
Основано на версии оригинального репозитория 12.01.2024 | ||
- Полностью удалена проверка национальной принадлежности по локали системы, которая запрещала запуск приложения в России и Белоруссии. Приложение может запустить **кто угодно и где угодно**, будь то житель России, Украины, Белоруссии и любой другой страны. | ||
- Больше не опирается на внешние библиотеки автора через NuGet, теперь они часть проекта в репозитории. Также удалёна зависимость от омерзительной библиотеки автора с омерзительным названием **deorcify**, которая не делает ничего, кроме дискриминации по национальному признаку. | ||
- Вычищена подчистую вся политическая повестка (кроме скромной сноски в настройках), удалена вся агрессивная пропаганда и русофобия. | ||
- Интерфейс полностью переведён на русский | ||
- Убраны все упоминания авторства безумного пропагандиста, который изначально делал это приложение. | ||
- Отключены обновления (возможно временно, в будущем смогу добавить свою систему обновлений, не опираясь на изначальный модуль если буду вообще обновлять этот репозиторий) | ||
|
||
# Как собрать | ||
Просто скачать и открыть **YoutubeDownloader.sln** в Visual Studio 2022 последней версии с установленным .NET 8.0 и собрать. | ||
<br />Собранный проект появится в директории **YoutubeDownloaderRU\bin**. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.8.34408.163 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YoutubeDownloaderRU", "YoutubeDownloaderRU\YoutubeDownloaderRU.csproj", "{AF6D645E-DDDD-4034-B644-D5328CC893C1}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{131C2561-E5A1-43E8-BF38-40E2E23DB0A4}" | ||
ProjectSection(SolutionItems) = preProject | ||
Directory.Build.props = Directory.Build.props | ||
License.txt = License.txt | ||
Readme.md = Readme.md | ||
EndProjectSection | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YoutubeDownloaderRU.Core", "YoutubeDownloaderRU.Core\YoutubeDownloaderRU.Core.csproj", "{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YoutubeExplode", "YoutubeExplode\YoutubeExplode\YoutubeExplode.csproj", "{B4A40CD2-DB77-4074-9F3D-F60F86B57891}" | ||
EndProject | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YoutubeExplode.Converter", "YoutubeExplode\YoutubeExplode.Converter\YoutubeExplode.Converter.csproj", "{77476989-6DD0-49E4-BAB6-8468F8C82734}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{AF6D645E-DDDD-4034-B644-D5328CC893C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{AF6D645E-DDDD-4034-B644-D5328CC893C1}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{AF6D645E-DDDD-4034-B644-D5328CC893C1}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{AF6D645E-DDDD-4034-B644-D5328CC893C1}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{5122A9DE-232C-4DA8-AD76-8B72AA377D5E}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{B4A40CD2-DB77-4074-9F3D-F60F86B57891}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{B4A40CD2-DB77-4074-9F3D-F60F86B57891}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{B4A40CD2-DB77-4074-9F3D-F60F86B57891}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{B4A40CD2-DB77-4074-9F3D-F60F86B57891}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{77476989-6DD0-49E4-BAB6-8468F8C82734}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{77476989-6DD0-49E4-BAB6-8468F8C82734}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{77476989-6DD0-49E4-BAB6-8468F8C82734}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{77476989-6DD0-49E4-BAB6-8468F8C82734}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {1455235F-4357-4DB9-BCC1-41A5A8B10AC5} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using System; | ||
using YoutubeDownloaderRU.Core.Utils; | ||
using YoutubeExplode.Videos; | ||
using YoutubeExplode.Videos.Streams; | ||
|
||
namespace YoutubeDownloaderRU.Core.Downloading; | ||
|
||
public static class FileNameTemplate | ||
{ | ||
public static string Apply( | ||
string template, | ||
IVideo video, | ||
Container container, | ||
string? number = null | ||
) => | ||
PathEx.EscapeFileName( | ||
template | ||
.Replace("$numc", number ?? "", StringComparison.Ordinal) | ||
.Replace("$num", number is not null ? $"[{number}]" : "", StringComparison.Ordinal) | ||
.Replace("$id", video.Id, StringComparison.Ordinal) | ||
.Replace("$title", video.Title, StringComparison.Ordinal) | ||
.Replace("$author", video.Author.ChannelTitle, StringComparison.Ordinal) | ||
.Replace( | ||
"$uploadDate", | ||
(video as Video)?.UploadDate.ToString("yyyy-MM-dd") ?? "", | ||
StringComparison.Ordinal | ||
) | ||
.Trim() | ||
+ '.' | ||
+ container.Name | ||
); | ||
} |
119 changes: 119 additions & 0 deletions
119
YoutubeDownloaderRU.Core/Downloading/VideoDownloadOption.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Lazy; | ||
using YoutubeDownloaderRU.Core.Utils.Extensions; | ||
using YoutubeExplode.Videos.Streams; | ||
|
||
namespace YoutubeDownloaderRU.Core.Downloading; | ||
|
||
public partial record VideoDownloadOption( | ||
Container Container, | ||
bool IsAudioOnly, | ||
IReadOnlyList<IStreamInfo> StreamInfos | ||
) | ||
{ | ||
[Lazy] | ||
public VideoQuality? VideoQuality => | ||
StreamInfos.OfType<IVideoStreamInfo>().MaxBy(s => s.VideoQuality)?.VideoQuality; | ||
} | ||
|
||
public partial record VideoDownloadOption | ||
{ | ||
internal static IReadOnlyList<VideoDownloadOption> ResolveAll(StreamManifest manifest) | ||
{ | ||
IEnumerable<VideoDownloadOption> GetVideoAndAudioOptions() | ||
{ | ||
var videoStreamInfos = manifest | ||
.GetVideoStreams() | ||
.OrderByDescending(v => v.VideoQuality); | ||
|
||
foreach (var videoStreamInfo in videoStreamInfos) | ||
{ | ||
// Muxed stream | ||
if (videoStreamInfo is MuxedStreamInfo) | ||
{ | ||
yield return new VideoDownloadOption( | ||
videoStreamInfo.Container, | ||
false, | ||
[videoStreamInfo] | ||
); | ||
} | ||
// Separate audio + video stream | ||
else | ||
{ | ||
// Prefer audio stream with the same container | ||
var audioStreamInfo = manifest | ||
.GetAudioStreams() | ||
.OrderByDescending(s => s.Container == videoStreamInfo.Container) | ||
.ThenByDescending(s => s is AudioOnlyStreamInfo) | ||
.ThenByDescending(s => s.Bitrate) | ||
.FirstOrDefault(); | ||
|
||
if (audioStreamInfo is not null) | ||
{ | ||
yield return new VideoDownloadOption( | ||
videoStreamInfo.Container, | ||
false, | ||
new IStreamInfo[] { videoStreamInfo, audioStreamInfo } | ||
); | ||
} | ||
} | ||
} | ||
} | ||
|
||
IEnumerable<VideoDownloadOption> GetAudioOnlyOptions() | ||
{ | ||
// WebM-based audio-only containers | ||
{ | ||
var audioStreamInfo = manifest | ||
.GetAudioStreams() | ||
.OrderByDescending(s => s.Container == Container.WebM) | ||
.ThenByDescending(s => s is AudioOnlyStreamInfo) | ||
.ThenByDescending(s => s.Bitrate) | ||
.FirstOrDefault(); | ||
|
||
if (audioStreamInfo is not null) | ||
{ | ||
yield return new VideoDownloadOption(Container.WebM, true, [audioStreamInfo]); | ||
|
||
yield return new VideoDownloadOption(Container.Mp3, true, [audioStreamInfo]); | ||
|
||
yield return new VideoDownloadOption( | ||
new Container("ogg"), | ||
true, | ||
[audioStreamInfo] | ||
); | ||
} | ||
} | ||
|
||
// Mp4-based audio-only containers | ||
{ | ||
var audioStreamInfo = manifest | ||
.GetAudioStreams() | ||
.OrderByDescending(s => s.Container == Container.Mp4) | ||
.ThenByDescending(s => s is AudioOnlyStreamInfo) | ||
.ThenByDescending(s => s.Bitrate) | ||
.FirstOrDefault(); | ||
|
||
if (audioStreamInfo is not null) | ||
{ | ||
yield return new VideoDownloadOption(Container.Mp4, true, [audioStreamInfo]); | ||
} | ||
} | ||
} | ||
|
||
// Deduplicate download options by video quality and container | ||
var comparer = EqualityComparer<VideoDownloadOption>.Create( | ||
(x, y) => x?.VideoQuality == y?.VideoQuality && x?.Container == y?.Container, | ||
x => HashCode.Combine(x.VideoQuality, x.Container) | ||
); | ||
|
||
var options = new HashSet<VideoDownloadOption>(comparer); | ||
|
||
options.AddRange(GetVideoAndAudioOptions()); | ||
options.AddRange(GetAudioOnlyOptions()); | ||
|
||
return options.ToArray(); | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
YoutubeDownloaderRU.Core/Downloading/VideoDownloadPreference.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using YoutubeExplode.Videos.Streams; | ||
|
||
namespace YoutubeDownloaderRU.Core.Downloading; | ||
|
||
public record VideoDownloadPreference( | ||
Container PreferredContainer, | ||
VideoQualityPreference PreferredVideoQuality | ||
) | ||
{ | ||
public VideoDownloadOption? TryGetBestOption(IReadOnlyList<VideoDownloadOption> options) | ||
{ | ||
// Short-circuit for audio-only formats | ||
if (PreferredContainer.IsAudioOnly) | ||
return options.FirstOrDefault(o => o.Container == PreferredContainer); | ||
|
||
var orderedOptions = options.OrderBy(o => o.VideoQuality).ToArray(); | ||
|
||
var preferredOption = PreferredVideoQuality switch | ||
{ | ||
VideoQualityPreference.Highest | ||
=> orderedOptions.LastOrDefault(o => o.Container == PreferredContainer), | ||
|
||
VideoQualityPreference.UpTo1080p | ||
=> orderedOptions | ||
.Where(o => o.VideoQuality?.MaxHeight <= 1080) | ||
.LastOrDefault(o => o.Container == PreferredContainer), | ||
|
||
VideoQualityPreference.UpTo720p | ||
=> orderedOptions | ||
.Where(o => o.VideoQuality?.MaxHeight <= 720) | ||
.LastOrDefault(o => o.Container == PreferredContainer), | ||
|
||
VideoQualityPreference.UpTo480p | ||
=> orderedOptions | ||
.Where(o => o.VideoQuality?.MaxHeight <= 480) | ||
.LastOrDefault(o => o.Container == PreferredContainer), | ||
|
||
VideoQualityPreference.Lowest | ||
=> orderedOptions.LastOrDefault(o => o.Container == PreferredContainer), | ||
|
||
_ | ||
=> throw new InvalidOperationException( | ||
$"Unknown video quality preference '{PreferredVideoQuality}'." | ||
) | ||
}; | ||
|
||
return preferredOption | ||
?? orderedOptions.FirstOrDefault(o => o.Container == PreferredContainer); | ||
} | ||
} |
Oops, something went wrong.