aboutsummaryrefslogtreecommitdiffstats
path: root/packaging/win/fetch-ffmpeg.ps1
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/win/fetch-ffmpeg.ps1')
-rw-r--r--packaging/win/fetch-ffmpeg.ps1131
1 files changed, 131 insertions, 0 deletions
diff --git a/packaging/win/fetch-ffmpeg.ps1 b/packaging/win/fetch-ffmpeg.ps1
new file mode 100644
index 0000000..5f6123d
--- /dev/null
+++ b/packaging/win/fetch-ffmpeg.ps1
@@ -0,0 +1,131 @@
+<#
+.SYNOPSIS
+ Download, verify and stage the ffmpeg/ffprobe MeshBay bundles by default.
+
+.DESCRIPTION
+ MeshBay transcodes browser-incompatible video to H.264 (webrtc_server.py,
+ `-c:v libx264`) -- a real encode, not just remux/probe -- so only a GPL
+ ffmpeg build works here; libx264 is GPL, no LGPL-only build includes it.
+ Asking an end user to separately install ffmpeg (`winget install ffmpeg`)
+ is not viable for a non-technical install: it needs network access and
+ winget/App Installer present at that exact moment, and fails silently
+ (streaming just does not work, with nothing pointing back at ffmpeg).
+ So this bundles it, verified, by default.
+
+ Source: BtbN/FFmpeg-Builds (github.com/BtbN/FFmpeg-Builds), the "gpl-shared"
+ Windows x86_64 preset -- ffmpeg.exe/ffprobe.exe plus the shared DLLs they
+ both link against, rather than two independent static binaries (which is
+ what very nearly doubled this: the "full" static build many devs already
+ have via winget is ~220 MB *per executable*). ffplay.exe is dropped: it is
+ an SDL2 video player, not something the daemon ever invokes.
+
+ Pinned to one dated release tag (autobuild-YYYY-MM-DD-HH-MM) rather than
+ the "latest" alias, which BtbN repoints to a new build on every run --
+ fine for a person fetching ffmpeg today, wrong for a build script that
+ must produce the same output next month. Checksum verified against the
+ release's own checksums.sha256, and the hash is pinned here too, so a
+ compromised or altered mirror is a hard failure, not a silent swap.
+
+ LICENSE-ffmpeg.txt is copied alongside ffmpeg.exe in the output -- ffmpeg
+ is unmodified, but it is still a GPLv3 binary MeshBay redistributes, and
+ that binary must carry its own license notice into the package.
+
+.PARAMETER OutDir
+ Where to place ffmpeg.exe, ffprobe.exe, the DLLs and the license notice.
+ Typically packages/meshbay-client/node-runtime/ (default build-node-
+ runtime.ps1 target), so they end up wherever the daemon already looks --
+ that directory is on PATH once installed (W3/W4), so no code needs to name
+ ffmpeg's path explicitly.
+
+.PARAMETER SkipCache
+ Re-download even if a verified copy already sits in the cache dir. Off by
+ default so repeated builds do not refetch 73 MB every time.
+#>
+[CmdletBinding()]
+param(
+ [Parameter(Mandatory = $true)]
+ [string]$OutDir,
+
+ [switch]$SkipCache
+)
+
+$ErrorActionPreference = "Stop"
+
+# Pinned: one dated release, one asset, one hash. Re-pin deliberately (a new
+# tag from https://github.com/BtbN/FFmpeg-Builds/releases, the exact asset
+# name for that release -- it embeds ffmpeg's own git-describe, so it changes
+# every time -- and the hash from that release's checksums.sha256) when
+# ffmpeg needs an update. Never move this to the "latest" alias: it is
+# reassigned on every BtbN auto-build and would make this script produce a
+# different binary tomorrow with no change to this file.
+$FFMPEG_TAG = "autobuild-2026-09-04-14-01"
+$FFMPEG_ASSET = "ffmpeg-N-126404-g818e5d965b-win64-gpl-shared.zip"
+$FFMPEG_SHA256 = "8575193e6a8d661a650e776f97b1379c14f6513d8fb1d650013e40916b758609"
+$FFMPEG_URL = "https://github.com/BtbN/FFmpeg-Builds/releases/download/$FFMPEG_TAG/$FFMPEG_ASSET"
+
+# What actually ships. Every DLL ffmpeg.exe/ffprobe.exe in this build link
+# against, plus the two executables. ffplay.exe (an SDL2 player, ~17 MB) is
+# deliberately left out -- collect_all-style "take everything" is right for
+# the PyInstaller spec's Python deps, wrong here where the vendor zip bundles
+# a whole extra program MeshBay never runs.
+$KEEP_FILES = @(
+ "ffmpeg.exe", "ffprobe.exe",
+ "avcodec-63.dll", "avdevice-63.dll", "avfilter-12.dll", "avformat-63.dll",
+ "avutil-61.dll", "swresample-7.dll", "swscale-10.dll"
+)
+
+function Step($msg) { Write-Host "==> $msg" -ForegroundColor Cyan }
+
+$cacheDir = Join-Path $env:LOCALAPPDATA "meshbay-build-cache"
+New-Item -ItemType Directory -Force -Path $cacheDir | Out-Null
+$zipPath = Join-Path $cacheDir $FFMPEG_ASSET
+
+if ($SkipCache -or -not (Test-Path $zipPath) -or
+ (Get-FileHash $zipPath -Algorithm SHA256).Hash.ToLower() -ne $FFMPEG_SHA256) {
+ Step "downloading $FFMPEG_ASSET ($FFMPEG_TAG)"
+ $ua = "meshbay-build-script (+https://meshbay.org)"
+ Invoke-WebRequest -Uri $FFMPEG_URL -OutFile $zipPath -UseBasicParsing -UserAgent $ua
+}
+else {
+ Step "using cached $FFMPEG_ASSET"
+}
+
+$actual = (Get-FileHash $zipPath -Algorithm SHA256).Hash.ToLower()
+if ($actual -ne $FFMPEG_SHA256) {
+ Remove-Item $zipPath -Force -ErrorAction SilentlyContinue
+ throw "ffmpeg download checksum mismatch: got $actual, expected $FFMPEG_SHA256 -- refusing to use it"
+}
+Step "checksum verified"
+
+$extractDir = Join-Path $cacheDir "extracted"
+Remove-Item $extractDir -Recurse -Force -ErrorAction SilentlyContinue
+Expand-Archive -Path $zipPath -DestinationPath $extractDir
+$binDir = Join-Path (Get-ChildItem $extractDir -Directory | Select-Object -First 1).FullName "bin"
+if (-not (Test-Path $binDir)) { throw "expected bin\ under the extracted archive, found none" }
+
+New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
+foreach ($name in $KEEP_FILES) {
+ $src = Join-Path $binDir $name
+ if (-not (Test-Path $src)) { throw "expected file missing from the ffmpeg build: $name" }
+ Copy-Item $src (Join-Path $OutDir $name) -Force
+}
+
+$noticeSrc = Join-Path $PSScriptRoot "LICENSE-ffmpeg.txt"
+Copy-Item $noticeSrc (Join-Path $OutDir "LICENSE-ffmpeg.txt") -Force
+
+Step "smoke test: encode + probe"
+$smokeOut = Join-Path $env:TEMP "meshbay-ffmpeg-smoke.mp4"
+Remove-Item $smokeOut -ErrorAction SilentlyContinue
+& (Join-Path $OutDir "ffmpeg.exe") -hide_banner -loglevel error `
+ -f lavfi -i "testsrc=duration=1:size=320x240:rate=10" `
+ -c:v libx264 -pix_fmt yuv420p -y $smokeOut
+if ($LASTEXITCODE -ne 0 -or -not (Test-Path $smokeOut)) {
+ throw "bundled ffmpeg failed to encode a test clip with libx264"
+}
+$codec = & (Join-Path $OutDir "ffprobe.exe") -hide_banner -v error `
+ -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 $smokeOut
+if ($codec.Trim() -ne "h264") { throw "expected h264, ffprobe reported '$codec'" }
+Remove-Item $smokeOut -ErrorAction SilentlyContinue
+
+$mb = "{0:N0} MB" -f ((Get-ChildItem $OutDir -File | Measure-Object Length -Sum).Sum / 1MB)
+Write-Host "OK ffmpeg bundled to $OutDir ($mb)" -ForegroundColor Green