mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2025-12-14 18:15:44 +00:00
Refactor for conciseness
This commit is contained in:
parent
d7fec62d2e
commit
ad27076c1f
4 changed files with 68 additions and 123 deletions
|
|
@ -1,53 +1,86 @@
|
||||||
using FFMpegCore.Extensions.Downloader.Enums;
|
using System.IO.Compression;
|
||||||
|
using System.Text.Json;
|
||||||
|
using FFMpegCore.Extensions.Downloader.Enums;
|
||||||
using FFMpegCore.Extensions.Downloader.Exceptions;
|
using FFMpegCore.Extensions.Downloader.Exceptions;
|
||||||
using FFMpegCore.Extensions.Downloader.Services;
|
using FFMpegCore.Extensions.Downloader.Extensions;
|
||||||
|
using FFMpegCore.Extensions.Downloader.Models;
|
||||||
|
|
||||||
namespace FFMpegCore.Extensions.Downloader;
|
namespace FFMpegCore.Extensions.Downloader;
|
||||||
|
|
||||||
public class FFMpegDownloader
|
public static class FFMpegDownloader
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Download the latest FFMpeg suite binaries for current platform
|
/// Download the latest FFMpeg suite binaries for current platform
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="version">used to explicitly state the version of binary you want to download</param>
|
/// <param name="version">used to explicitly state the version of binary you want to download</param>
|
||||||
/// <param name="binaries">used to explicitly state the binaries you want to download (ffmpeg, ffprobe, ffplay)</param>
|
/// <param name="binaries">used to explicitly state the binaries you want to download (ffmpeg, ffprobe, ffplay)</param>
|
||||||
|
/// <param name="options">used for specifying binary folder to download binaries into. If not provided, GlobalFFOptions are used</param>
|
||||||
/// <param name="platformOverride">used to explicitly state the os and architecture you want to download</param>
|
/// <param name="platformOverride">used to explicitly state the os and architecture you want to download</param>
|
||||||
/// <returns>a list of the binaries that have been successfully downloaded</returns>
|
/// <returns>a list of the binaries that have been successfully downloaded</returns>
|
||||||
public static async Task<List<string>> DownloadFFMpegSuite(
|
public static async Task<List<string>> DownloadFFMpegSuite(
|
||||||
FFMpegVersions version = FFMpegVersions.Latest,
|
FFMpegVersions version = FFMpegVersions.Latest,
|
||||||
FFMpegBinaries binaries = FFMpegBinaries.FFMpeg | FFMpegBinaries.FFProbe,
|
FFMpegBinaries binaries = FFMpegBinaries.FFMpeg | FFMpegBinaries.FFProbe,
|
||||||
|
FFOptions? options = null,
|
||||||
SupportedPlatforms? platformOverride = null)
|
SupportedPlatforms? platformOverride = null)
|
||||||
{
|
{
|
||||||
// get all available versions
|
using var httpClient = new HttpClient();
|
||||||
var versionInfo = await FFbinariesService.GetVersionInfo(version);
|
|
||||||
|
|
||||||
// get the download info for the current platform
|
var versionInfo = await httpClient.GetVersionInfo(version);
|
||||||
var downloadInfo = versionInfo.BinaryInfo?.GetCompatibleDownloadInfo(platformOverride) ??
|
var binariesDictionary = versionInfo.BinaryInfo?.GetCompatibleDownloadInfo(platformOverride) ??
|
||||||
throw new FFMpegDownloaderException("Failed to get compatible download info");
|
throw new FFMpegDownloaderException("Failed to get compatible download info");
|
||||||
|
|
||||||
var successList = new List<string>();
|
var successList = new List<string>();
|
||||||
|
var relevantOptions = options ?? GlobalFFOptions.Current;
|
||||||
// download ffmpeg if selected
|
if (string.IsNullOrEmpty(relevantOptions.BinaryFolder))
|
||||||
if (binaries.HasFlag(FFMpegBinaries.FFMpeg) && downloadInfo.FFMpeg is not null)
|
|
||||||
{
|
{
|
||||||
await using var zipStream = await FFbinariesService.DownloadFileAsStream(new Uri(downloadInfo.FFMpeg));
|
throw new FFMpegDownloaderException("Binary folder not specified");
|
||||||
successList.AddRange(FFbinariesService.ExtractZipAndSave(zipStream));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// download ffprobe if selected
|
var binaryFlags = binaries.GetFlags();
|
||||||
if (binaries.HasFlag(FFMpegBinaries.FFProbe) && downloadInfo.FFProbe is not null)
|
foreach (var binaryFlag in binaryFlags)
|
||||||
{
|
{
|
||||||
await using var zipStream = await FFbinariesService.DownloadFileAsStream(new Uri(downloadInfo.FFProbe));
|
if (binariesDictionary.TryGetValue(binaryFlag.ToString().ToLowerInvariant(), out var binaryUrl))
|
||||||
successList.AddRange(FFbinariesService.ExtractZipAndSave(zipStream));
|
{
|
||||||
|
await using var zipStream = await httpClient.GetStreamAsync(new Uri(binaryUrl));
|
||||||
|
var extracted = ExtractZipAndSave(zipStream, relevantOptions.BinaryFolder);
|
||||||
|
successList.AddRange(extracted);
|
||||||
}
|
}
|
||||||
|
|
||||||
// download ffplay if selected
|
|
||||||
if (binaries.HasFlag(FFMpegBinaries.FFPlay) && downloadInfo.FFPlay is not null)
|
|
||||||
{
|
|
||||||
await using var zipStream = await FFbinariesService.DownloadFileAsStream(new Uri(downloadInfo.FFPlay));
|
|
||||||
successList.AddRange(FFbinariesService.ExtractZipAndSave(zipStream));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return successList;
|
return successList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task<VersionInfo> GetVersionInfo(this HttpClient client, FFMpegVersions version)
|
||||||
|
{
|
||||||
|
var versionUri = version.GetDescription();
|
||||||
|
|
||||||
|
var response = await client.GetAsync(versionUri);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
throw new FFMpegDownloaderException($"Failed to get version info from {versionUri}", "network error");
|
||||||
|
}
|
||||||
|
|
||||||
|
var jsonString = await response.Content.ReadAsStringAsync();
|
||||||
|
var versionInfo = JsonSerializer.Deserialize<VersionInfo>(jsonString);
|
||||||
|
|
||||||
|
return versionInfo ??
|
||||||
|
throw new FFMpegDownloaderException($"Failed to deserialize version info from {versionUri}", jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<string> ExtractZipAndSave(Stream zipStream, string binaryFolder)
|
||||||
|
{
|
||||||
|
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Read);
|
||||||
|
List<string> files = new();
|
||||||
|
foreach (var entry in archive.Entries)
|
||||||
|
{
|
||||||
|
if (entry.Name is "ffmpeg" or "ffmpeg.exe" or "ffprobe.exe" or "ffprobe" or "ffplay.exe" or "ffplay")
|
||||||
|
{
|
||||||
|
var filePath = Path.Combine(binaryFolder, entry.Name);
|
||||||
|
entry.ExtractToFile(filePath, true);
|
||||||
|
files.Add(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,23 +4,23 @@ using FFMpegCore.Extensions.Downloader.Enums;
|
||||||
|
|
||||||
namespace FFMpegCore.Extensions.Downloader.Models;
|
namespace FFMpegCore.Extensions.Downloader.Models;
|
||||||
|
|
||||||
internal record BinaryInfo
|
internal class BinaryInfo
|
||||||
{
|
{
|
||||||
[JsonPropertyName("windows-64")] public DownloadInfo? Windows64 { get; set; }
|
[JsonPropertyName("windows-64")] public Dictionary<string, string>? Windows64 { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("windows-32")] public DownloadInfo? Windows32 { get; set; }
|
[JsonPropertyName("windows-32")] public Dictionary<string, string>? Windows32 { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("linux-32")] public DownloadInfo? Linux32 { get; set; }
|
[JsonPropertyName("linux-32")] public Dictionary<string, string>? Linux32 { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("linux-64")] public DownloadInfo? Linux64 { get; set; }
|
[JsonPropertyName("linux-64")] public Dictionary<string, string>? Linux64 { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("linux-armhf")] public DownloadInfo? LinuxArmhf { get; set; }
|
[JsonPropertyName("linux-armhf")] public Dictionary<string, string>? LinuxArmhf { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("linux-armel")] public DownloadInfo? LinuxArmel { get; set; }
|
[JsonPropertyName("linux-armel")] public Dictionary<string, string>? LinuxArmel { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("linux-arm64")] public DownloadInfo? LinuxArm64 { get; set; }
|
[JsonPropertyName("linux-arm64")] public Dictionary<string, string>? LinuxArm64 { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("osx-64")] public DownloadInfo? Osx64 { get; set; }
|
[JsonPropertyName("osx-64")] public Dictionary<string, string>? Osx64 { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Automatically get the compatible download info for current os and architecture
|
/// Automatically get the compatible download info for current os and architecture
|
||||||
|
|
@ -29,7 +29,7 @@ internal record BinaryInfo
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
/// <exception cref="PlatformNotSupportedException"></exception>
|
/// <exception cref="PlatformNotSupportedException"></exception>
|
||||||
public DownloadInfo? GetCompatibleDownloadInfo(SupportedPlatforms? platformOverride = null)
|
public Dictionary<string, string>? GetCompatibleDownloadInfo(SupportedPlatforms? platformOverride = null)
|
||||||
{
|
{
|
||||||
if (platformOverride is not null)
|
if (platformOverride is not null)
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +64,7 @@ internal record BinaryInfo
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && RuntimeInformation.OSArchitecture == Architecture.X64)
|
||||||
{
|
{
|
||||||
return Osx64;
|
return Osx64;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace FFMpegCore.Extensions.Downloader.Models;
|
|
||||||
|
|
||||||
internal record DownloadInfo
|
|
||||||
{
|
|
||||||
[JsonPropertyName("ffmpeg")] public string? FFMpeg { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("ffprobe")] public string? FFProbe { get; set; }
|
|
||||||
|
|
||||||
[JsonPropertyName("ffplay")] public string? FFPlay { get; set; }
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Text.Json;
|
|
||||||
using FFMpegCore.Extensions.Downloader.Enums;
|
|
||||||
using FFMpegCore.Extensions.Downloader.Exceptions;
|
|
||||||
using FFMpegCore.Extensions.Downloader.Extensions;
|
|
||||||
using FFMpegCore.Extensions.Downloader.Models;
|
|
||||||
|
|
||||||
namespace FFMpegCore.Extensions.Downloader.Services;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Service to interact with ffbinaries.com API
|
|
||||||
/// </summary>
|
|
||||||
internal class FFbinariesService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Get version info from ffbinaries.com
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="version">use to explicitly state the version of ffmpeg you want</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="FFMpegDownloaderException"></exception>
|
|
||||||
internal static async Task<VersionInfo> GetVersionInfo(FFMpegVersions version)
|
|
||||||
{
|
|
||||||
var versionUri = version.GetDescription();
|
|
||||||
|
|
||||||
HttpClient client = new();
|
|
||||||
var response = await client.GetAsync(versionUri);
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
throw new FFMpegDownloaderException($"Failed to get version info from {versionUri}", "network error");
|
|
||||||
}
|
|
||||||
|
|
||||||
var jsonString = await response.Content.ReadAsStringAsync();
|
|
||||||
var versionInfo = JsonSerializer.Deserialize<VersionInfo>(jsonString);
|
|
||||||
|
|
||||||
return versionInfo ??
|
|
||||||
throw new FFMpegDownloaderException($"Failed to deserialize version info from {versionUri}", jsonString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Download file from uri
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="address">uri of the file</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static async Task<Stream> DownloadFileAsStream(Uri address)
|
|
||||||
{
|
|
||||||
var client = new HttpClient();
|
|
||||||
return await client.GetStreamAsync(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extracts the binaries from the zip stream and saves them to the current binary folder
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="zipStream">steam of the zip file</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
internal static IEnumerable<string> ExtractZipAndSave(Stream zipStream)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(GlobalFFOptions.Current.BinaryFolder))
|
|
||||||
{
|
|
||||||
throw new FFMpegDownloaderException("Binary folder not specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Read);
|
|
||||||
List<string> files = new();
|
|
||||||
foreach (var entry in archive.Entries)
|
|
||||||
{
|
|
||||||
if (entry.Name is "ffmpeg" or "ffmpeg.exe" or "ffprobe.exe" or "ffprobe" or "ffplay.exe" or "ffplay")
|
|
||||||
{
|
|
||||||
entry.ExtractToFile(Path.Combine(GlobalFFOptions.Current.BinaryFolder, entry.Name), true);
|
|
||||||
files.Add(Path.Combine(GlobalFFOptions.Current.BinaryFolder, entry.Name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue