Skip to content

Commit

Permalink
Provide FFmpeg-less builds for convenience (#486)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyrrrz authored Aug 20, 2024
1 parent ff4f3ec commit 9762753
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 29 deletions.
30 changes: 25 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,17 @@ jobs:
- win-arm64
- win-x86
- win-x64
- linux-arm64
- linux-x64
- osx-arm64
- osx-x64
bundle-ffmpeg:
- true
- false
exclude:
# FFmpeg builds for these platforms are not easily available
- bundle-ffmpeg: true
rid: linux-arm64

runs-on: ${{ startsWith(matrix.rid, 'win-') && 'windows-latest' || startsWith(matrix.rid, 'osx-') && 'macos-latest' || 'ubuntu-latest' }}
timeout-minutes: 10
Expand All @@ -66,6 +74,10 @@ jobs:
with:
dotnet-version: 8.0.x

- name: Download FFmpeg
if: ${{ matrix.bundle-ffmpeg }}
run: dotnet build YoutubeDownloader -t:DownloadFFmpeg

- name: Publish app
run: >
dotnet publish YoutubeDownloader
Expand All @@ -79,7 +91,7 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
with:
name: YoutubeDownloader.${{ matrix.rid }}
name: ${{ matrix.bundle-ffmpeg && 'YoutubeDownloader' || 'YoutubeDownloader.Bare' }}.${{ matrix.rid }}
path: YoutubeDownloader/bin/publish
if-no-files-found: error

Expand Down Expand Up @@ -116,9 +128,17 @@ jobs:
- win-arm64
- win-x86
- win-x64
- linux-arm64
- linux-x64
- osx-arm64
- osx-x64
bundle-ffmpeg:
- true
- false
exclude:
# FFmpeg builds for these platforms are not easily available
- bundle-ffmpeg: true
rid: linux-arm64

runs-on: ubuntu-latest
timeout-minutes: 10
Expand All @@ -131,26 +151,26 @@ jobs:
- name: Download artifacts
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: YoutubeDownloader.${{ matrix.rid }}
name: ${{ matrix.bundle-ffmpeg && 'YoutubeDownloader' || 'YoutubeDownloader.Bare' }}.${{ matrix.rid }}
path: YoutubeDownloader/

- name: Set permissions
if: ${{ !startsWith(matrix.rid, 'win-') }}
run: |
chmod +x YoutubeDownloader/YoutubeDownloader
chmod +x YoutubeDownloader/ffmpeg
${{ matrix.bundle-ffmpeg && 'chmod +x YoutubeDownloader/ffmpeg' || '' }}
- name: Create package
# Change into the artifacts directory to avoid including the directory itself in the zip archive
working-directory: YoutubeDownloader/
run: zip -r ../YoutubeDownloader.${{ matrix.rid }}.zip .
run: zip -r ../${{ matrix.bundle-ffmpeg && 'YoutubeDownloader' || 'YoutubeDownloader.Bare' }}.${{ matrix.rid }}.zip .

- name: Upload release asset
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: >
gh release upload ${{ github.ref_name }}
YoutubeDownloader.${{ matrix.rid }}.zip
${{ matrix.bundle-ffmpeg && 'YoutubeDownloader' || 'YoutubeDownloader.Bare' }}.${{ matrix.rid }}.zip
--repo ${{ github.event.repository.full_name }}
notify:
Expand Down
4 changes: 4 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ To learn more about the war and how you can help, [click here](https://tyrrrz.me
> **Note**:
> If you're unsure which build is right for your system, consult with [this page](https://useragent.cc) to determine your OS and CPU architecture.
> **Note**:
> **YoutubeDownloader** comes bundled with [FFmpeg](https://ffmpeg.org) which is used for processing videos.
> You can also download a version of **YoutubeDownloader** that doesn't include FFmpeg (`YoutubeDownloader.Bare.*` builds) if you prefer to use your own installation.
## Features

- Cross-platform graphical user interface
Expand Down
20 changes: 12 additions & 8 deletions YoutubeDownloader.Core/Downloading/FFmpeg.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,30 @@ namespace YoutubeDownloader.Core.Downloading;

public static class FFmpeg
{
private static string CliFileName { get; } =
OperatingSystem.IsWindows() ? "ffmpeg.exe" : "ffmpeg";

public static string? TryGetCliFilePath()
{
static IEnumerable<string> GetProbeDirectoryPaths()
{
yield return AppContext.BaseDirectory;
yield return Directory.GetCurrentDirectory();

foreach (
var path in Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator)
?? Enumerable.Empty<string>()
)
if (Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator) is { } paths)
{
yield return path;
foreach (var path in paths)
yield return path;
}
}

return GetProbeDirectoryPaths()
.Select(dirPath =>
Path.Combine(dirPath, OperatingSystem.IsWindows() ? "ffmpeg.exe" : "ffmpeg")
)
.Select(dirPath => Path.Combine(dirPath, CliFileName))
.FirstOrDefault(File.Exists);
}

public static bool IsBundled() =>
File.Exists(Path.Combine(AppContext.BaseDirectory, CliFileName));

public static bool IsAvailable() => !string.IsNullOrWhiteSpace(TryGetCliFilePath());
}
9 changes: 3 additions & 6 deletions YoutubeDownloader/DownloadFFmpeg.ps1
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# This script is called from inside an MSBuild task to download FFmpeg binaries:
# dotnet build -t:DownloadFFmpeg

param (
[string]$platform,
[string]$outputPath
Expand All @@ -8,12 +11,6 @@ $ErrorActionPreference = "Stop"
# Normalize platform identifier
$platform = $platform.ToLower().Replace("win-", "windows-")

# Check if already exists
if (Test-Path $outputPath) {
Write-Host "Skipped downloading FFmpeg, file already exists."
exit
}

# Download the archive
Write-Host "Downloading FFmpeg..."
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Expand Down
7 changes: 6 additions & 1 deletion YoutubeDownloader/Services/UpdateService.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Onova;
using Onova.Exceptions;
using Onova.Services;
using YoutubeDownloader.Core.Downloading;

namespace YoutubeDownloader.Services;

Expand All @@ -18,7 +20,10 @@ public class UpdateService(SettingsService settingsService) : IDisposable
// YoutubeDownloader.win-arm64.zip
// YoutubeDownloader.win-x64.zip
// YoutubeDownloader.linux-x64.zip
$"YoutubeDownloader.{RuntimeInformation.RuntimeIdentifier}.zip"
// YoutubeDownloader.Bare.linux-x64.zip
FFmpeg.IsBundled()
? $"YoutubeDownloader.{RuntimeInformation.RuntimeIdentifier}.zip"
: $"YoutubeDownloader.Bare.{RuntimeInformation.RuntimeIdentifier}.zip"
),
new ZipPackageExtractor()
)
Expand Down
6 changes: 4 additions & 2 deletions YoutubeDownloader/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,17 @@ private async Task ShowDevelopmentBuildMessageAsync()

private async Task ShowFFmpegMessageAsync()
{
if (!string.IsNullOrWhiteSpace(FFmpeg.TryGetCliFilePath()))
if (FFmpeg.IsAvailable())
return;

var dialog = viewModelManager.CreateMessageBoxViewModel(
"FFmpeg is missing",
$"""
FFmpeg is required for {Program.Name} to work. Please download it and make it available in the application directory or on the system PATH.
Click DOWNLOAD to go to the FFmpeg download page. You can also install FFmpeg using a package manager instead.
Alternatively, you can also download a version of {Program.Name} that has FFmpeg bundled with it.
Click DOWNLOAD to go to the FFmpeg download page.
""",
"DOWNLOAD",
"CLOSE"
Expand Down
13 changes: 6 additions & 7 deletions YoutubeDownloader/YoutubeDownloader.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
<TrimmerRootAssembly Include="WebView.Core" />
</ItemGroup>

<!-- Download FFmpeg and copy it to the output directory-->
<!-- Task to download FFmpeg -->
<PropertyGroup>
<FFmpegPlatform>$(RuntimeIdentifier)</FFmpegPlatform>
<FFmpegPlatform Condition="'$(FFmpegPlatform)' == '' AND $([MSBuild]::IsOsPlatform('Windows')) AND '$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'Arm64'">win-arm64</FFmpegPlatform>
Expand All @@ -68,14 +68,13 @@
<FFmpegFileName Condition="'$(FFmpegFileName)' == ''">ffmpeg</FFmpegFileName>
</PropertyGroup>

<Target Name="Download FFmpeg before build" BeforeTargets="PreBuildEvent">
<Target Name="DownloadFFmpeg">
<Exec Command="pwsh -ExecutionPolicy Bypass -File &quot;$(ProjectDir)/DownloadFFmpeg.ps1&quot; -Platform $(FFmpegPlatform) -OutputPath &quot;$(ProjectDir)/$(FFmpegFileName)&quot;" LogStandardErrorAsError="true" />
<Copy SourceFiles="$(ProjectDir)/$(FFmpegFileName)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" />
</Target>

<Target Name="Download FFmpeg before publish" BeforeTargets="PrepareForPublish">
<Exec Command="pwsh -ExecutionPolicy Bypass -File &quot;$(ProjectDir)/DownloadFFmpeg.ps1&quot; -Platform $(FFmpegPlatform) -OutputPath &quot;$(ProjectDir)/$(FFmpegFileName)&quot;" LogStandardErrorAsError="true" />
<Copy SourceFiles="$(ProjectDir)/$(FFmpegFileName)" DestinationFolder="$(PublishDir)" SkipUnchangedFiles="true" />
</Target>
<ItemGroup>
<None Include="ffmpeg.exe" CopyToOutputDirectory="PreserveNewest" Condition="Exists('ffmpeg.exe')" />
<None Include="ffmpeg" CopyToOutputDirectory="PreserveNewest" Condition="Exists('ffmpeg')" />
</ItemGroup>

</Project>

0 comments on commit 9762753

Please sign in to comment.