Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge YoutubeExplode.Converter inside the core repo
- Loading branch information
Showing
25 changed files
with
995 additions
and
27 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
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
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
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
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
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,81 @@ | ||
using System; | ||
using System.IO; | ||
using System.IO.Compression; | ||
using System.Net.Http; | ||
using System.Runtime.InteropServices; | ||
using System.Threading.Tasks; | ||
using CliWrap; | ||
using Xunit; | ||
|
||
namespace YoutubeExplode.Converter.Tests.Fixtures | ||
{ | ||
public partial class FFmpegFixture : IAsyncLifetime | ||
{ | ||
public string FilePath => Path.Combine( | ||
Path.GetDirectoryName(typeof(FFmpegFixture).Assembly.Location) ?? Directory.GetCurrentDirectory(), | ||
GetFFmpegFileName() | ||
); | ||
|
||
private async ValueTask EnsureFFmpegHasExecutePermissionAsync() | ||
{ | ||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||
return; | ||
|
||
await Cli.Wrap("/bin/bash") | ||
.WithArguments(new[] {"-c", $"chmod +x {FilePath}"}) | ||
.ExecuteAsync(); | ||
} | ||
|
||
private async ValueTask DownloadFFmpegAsync() | ||
{ | ||
using var httpClient = new HttpClient(); | ||
|
||
await using var zipStream = await httpClient.GetStreamAsync(GetFFmpegDownloadUrl()); | ||
using var zip = new ZipArchive(zipStream, ZipArchiveMode.Read); | ||
|
||
var entry = zip.GetEntry(GetFFmpegFileName()); | ||
|
||
if (entry is null) | ||
throw new FileNotFoundException("Downloaded archive doesn't contain FFmpeg."); | ||
|
||
await using var entryStream = entry.Open(); | ||
await using var fileStream = File.Create(FilePath); | ||
await entryStream.CopyToAsync(fileStream); | ||
|
||
await EnsureFFmpegHasExecutePermissionAsync(); | ||
} | ||
|
||
public async Task InitializeAsync() | ||
{ | ||
// Don't re-download FFmpeg from last time | ||
if (File.Exists(FilePath)) | ||
return; | ||
|
||
await DownloadFFmpegAsync(); | ||
} | ||
|
||
public Task DisposeAsync() => Task.CompletedTask; | ||
} | ||
|
||
public partial class FFmpegFixture | ||
{ | ||
private static string GetFFmpegFileName() => | ||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) | ||
? "ffmpeg.exe" | ||
: "ffmpeg"; | ||
|
||
private static string GetFFmpegDownloadUrl() | ||
{ | ||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||
return "https://github.com/vot/ffbinaries-prebuilt/releases/download/v4.2.1/ffmpeg-4.2.1-win-64.zip"; | ||
|
||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) | ||
return "https://github.com/vot/ffbinaries-prebuilt/releases/download/v4.2.1/ffmpeg-4.2.1-linux-64.zip"; | ||
|
||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | ||
return "https://github.com/vot/ffbinaries-prebuilt/releases/download/v4.2.1/ffmpeg-4.2.1-osx-64.zip"; | ||
|
||
throw new InvalidOperationException("Unknown OS."); | ||
} | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
YoutubeExplode.Converter.Tests/Fixtures/TempOutputFixture.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,25 @@ | ||
using System; | ||
using System.IO; | ||
|
||
namespace YoutubeExplode.Converter.Tests.Fixtures | ||
{ | ||
public class TempOutputFixture : IDisposable | ||
{ | ||
public string DirPath => Path.Combine( | ||
Path.GetDirectoryName(typeof(TempOutputFixture).Assembly.Location) ?? Directory.GetCurrentDirectory(), | ||
"Temp" | ||
); | ||
|
||
public TempOutputFixture() => Directory.CreateDirectory(DirPath); | ||
|
||
public string GetTempFilePath(string fileName) => Path.Combine(DirPath, fileName); | ||
|
||
public string GetTempFilePath() => GetTempFilePath(Guid.NewGuid().ToString()); | ||
|
||
public void Dispose() | ||
{ | ||
if (Directory.Exists(DirPath)) | ||
Directory.Delete(DirPath, true); | ||
} | ||
} | ||
} |
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,141 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
using FluentAssertions; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
using YoutubeExplode.Converter.Tests.Fixtures; | ||
|
||
namespace YoutubeExplode.Converter.Tests | ||
{ | ||
public class GeneralSpecs : IClassFixture<TempOutputFixture>, IClassFixture<FFmpegFixture> | ||
{ | ||
private readonly ITestOutputHelper _testOutput; | ||
private readonly TempOutputFixture _tempOutputFixture; | ||
private readonly FFmpegFixture _ffmpegFixture; | ||
|
||
public GeneralSpecs( | ||
ITestOutputHelper testOutput, | ||
TempOutputFixture tempOutputFixture, | ||
FFmpegFixture ffmpegFixture) | ||
{ | ||
_testOutput = testOutput; | ||
_tempOutputFixture = tempOutputFixture; | ||
_ffmpegFixture = ffmpegFixture; | ||
} | ||
|
||
[Fact] | ||
public async Task User_can_download_a_video_by_merging_best_streams_into_a_single_mp4_file() | ||
{ | ||
// Arrange | ||
var youtube = new YoutubeClient(); | ||
var outputFilePath = Path.ChangeExtension(_tempOutputFixture.GetTempFilePath(), "mp4"); | ||
|
||
// Act | ||
await youtube.Videos.DownloadAsync("AI7ULzgf8RU", outputFilePath); | ||
|
||
var fileInfo = new FileInfo(outputFilePath); | ||
|
||
// Assert | ||
fileInfo.Exists.Should().BeTrue(); | ||
fileInfo.Length.Should().BeGreaterThan(0); | ||
} | ||
|
||
[Fact] | ||
public async Task User_can_download_a_video_by_merging_best_streams_into_a_single_webm_file() | ||
{ | ||
// Arrange | ||
var youtube = new YoutubeClient(); | ||
var outputFilePath = Path.ChangeExtension(_tempOutputFixture.GetTempFilePath(), "webm"); | ||
|
||
// Act | ||
await youtube.Videos.DownloadAsync("FkklG9MA0vM", outputFilePath); | ||
|
||
var fileInfo = new FileInfo(outputFilePath); | ||
|
||
// Assert | ||
fileInfo.Exists.Should().BeTrue(); | ||
fileInfo.Length.Should().BeGreaterThan(0); | ||
} | ||
|
||
[Fact] | ||
public async Task User_can_download_a_video_by_merging_best_streams_into_a_single_mp3_file() | ||
{ | ||
// Arrange | ||
var youtube = new YoutubeClient(); | ||
var outputFilePath = Path.ChangeExtension(_tempOutputFixture.GetTempFilePath(), "mp3"); | ||
|
||
// Act | ||
await youtube.Videos.DownloadAsync("AI7ULzgf8RU", outputFilePath); | ||
|
||
var fileInfo = new FileInfo(outputFilePath); | ||
|
||
// Assert | ||
fileInfo.Exists.Should().BeTrue(); | ||
fileInfo.Length.Should().BeGreaterThan(0); | ||
} | ||
|
||
[Fact] | ||
public async Task User_can_download_a_video_by_merging_best_streams_into_a_single_ogg_file() | ||
{ | ||
// Arrange | ||
var youtube = new YoutubeClient(); | ||
var outputFilePath = Path.ChangeExtension(_tempOutputFixture.GetTempFilePath(), "ogg"); | ||
|
||
// Act | ||
await youtube.Videos.DownloadAsync("AI7ULzgf8RU", outputFilePath); | ||
|
||
var fileInfo = new FileInfo(outputFilePath); | ||
|
||
// Assert | ||
fileInfo.Exists.Should().BeTrue(); | ||
fileInfo.Length.Should().BeGreaterThan(0); | ||
} | ||
|
||
[Fact] | ||
public async Task User_can_download_a_video_with_custom_conversion_settings() | ||
{ | ||
// Arrange | ||
var youtube = new YoutubeClient(); | ||
var outputFilePath = _tempOutputFixture.GetTempFilePath(); | ||
|
||
// Act | ||
await youtube.Videos.DownloadAsync( | ||
"AI7ULzgf8RU", outputFilePath, | ||
o => o | ||
.SetFFmpegPath(_ffmpegFixture.FilePath) | ||
.SetFormat("mp4") | ||
.SetPreset(ConversionPreset.UltraFast) | ||
); | ||
|
||
var fileInfo = new FileInfo(outputFilePath); | ||
|
||
// Assert | ||
fileInfo.Exists.Should().BeTrue(); | ||
fileInfo.Length.Should().BeGreaterThan(0); | ||
} | ||
|
||
[Fact] | ||
public async Task User_can_download_a_video_and_track_the_progress_of_the_operation() | ||
{ | ||
// Arrange | ||
var progressReports = new List<double>(); | ||
var progress = new Progress<double>(p => | ||
{ | ||
_testOutput.WriteLine($"Progress: {p:P2}"); | ||
progressReports.Add(p); | ||
}); | ||
|
||
var youtube = new YoutubeClient(); | ||
var outputFilePath = _tempOutputFixture.GetTempFilePath(); | ||
|
||
// Act | ||
await youtube.Videos.DownloadAsync("AI7ULzgf8RU", outputFilePath, progress); | ||
|
||
// Assert | ||
progressReports.Should().NotBeEmpty(); | ||
progressReports.Should().Contain(1.0); | ||
} | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
YoutubeExplode.Converter.Tests/YoutubeExplode.Converter.Tests.csproj
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,29 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net5.0</TargetFramework> | ||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
<CollectCoverage>true</CollectCoverage> | ||
<CoverletOutputFormat>opencover</CoverletOutputFormat> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="CliWrap" Version="3.3.2" /> | ||
<PackageReference Include="FluentAssertions" Version="5.10.3" /> | ||
<PackageReference Include="GitHubActionsTestLogger" Version="1.2.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" /> | ||
<PackageReference Include="xunit" Version="2.4.1" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" PrivateAssets="all" /> | ||
<PackageReference Include="coverlet.msbuild" Version="3.0.3" PrivateAssets="all" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\YoutubeExplode.Converter\YoutubeExplode.Converter.csproj" /> | ||
</ItemGroup> | ||
|
||
</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,5 @@ | ||
{ | ||
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", | ||
"methodDisplayOptions": "all", | ||
"methodDisplay": "method" | ||
} |
Oops, something went wrong.