Files
Live-streaming/vendor/mpv/installer/updater.ps1
2026-08-15 14:43:56 +08:00

797 lines
26 KiB
PowerShell

$fallback7z = Join-Path (Get-Location) "\7z\7zr.exe";
$useragent = "mpv-win-updater"
function Get-7z {
$7z_command = Get-Command -CommandType Application -ErrorAction Ignore 7z.exe | Select-Object -Last 1
if ($7z_command) {
return $7z_command.Source
}
$7zdir = Get-ItemPropertyValue -ErrorAction Ignore "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip" "InstallLocation"
if ($7zdir -and (Test-Path (Join-Path $7zdir "7z.exe"))) {
return Join-Path $7zdir "7z.exe"
}
if (Test-Path $fallback7z) {
return $fallback7z
}
return $null
}
function Check-7z {
if (-not (Get-7z))
{
$null = New-Item -ItemType Directory -Force (Split-Path $fallback7z)
$download_file = $fallback7z
Write-Host "Downloading 7zr.exe" -ForegroundColor Green
Invoke-WebRequest -Uri "https://www.7-zip.org/a/7zr.exe" -UserAgent $useragent -OutFile $download_file
}
else
{
Write-Host "7z already exist. Skipped download" -ForegroundColor Green
}
}
function Check-PowershellVersion {
$version = $PSVersionTable.PSVersion.Major
Write-Host "Checking Windows PowerShell version -- $version" -ForegroundColor Green
if ($version -le 2)
{
Write-Host "Using Windows PowerShell $version is unsupported. Upgrade your Windows PowerShell." -ForegroundColor Red
throw
}
}
function Check-Ytplugin {
$ytdlp = Get-ChildItem "yt-dlp*.exe" -ErrorAction Ignore
$youtubedl = Get-ChildItem "youtube-dl.exe" -ErrorAction Ignore
if ($ytdlp) {
return $ytdlp.ToString()
}
elseif ($youtubedl) {
return $youtubedl.ToString()
}
else {
return $null
}
}
function Check-Ytplugin-In-System {
$ytp = Get-Command -CommandType Application -ErrorAction Ignore yt-dlp.exe | Select-Object -Last 1
if (-not $ytp) {
$ytp = Get-Command -CommandType Application -ErrorAction Ignore youtube-dl.exe | Select-Object -Last 1
}
return [bool]($ytp -and ((Split-Path $ytp.Source) -ne (Get-Location)))
}
function Check-Mpv {
$mpv = (Get-Location).Path + "\mpv.exe"
$is_exist = Test-Path $mpv
return $is_exist
}
function Download-Archive ($filename, $link) {
Write-Host "Downloading" $filename -ForegroundColor Green
Invoke-WebRequest -Uri $link -UserAgent $useragent -OutFile $filename
}
function Get-GitHubToken {
$file = "settings.xml"
if (Test-Path $file) {
$filePath = (Resolve-Path $file).Path
[xml]$doc = Get-Content $filePath
$settings = $doc.SelectSingleNode("/settings")
if ($settings) {
$githubtoken = $settings.SelectSingleNode("githubtoken")
}
if ($settings -and ($null -eq $githubtoken)) {
$newNode = $doc.CreateElement("githubtoken")
$newNode.AppendChild($doc.CreateTextNode("unset")) | out-null
$settings.AppendChild($newNode) | out-null
$doc.Save($filePath)
$githubtoken = $newNode
}
if ($settings -and ($null -ne $githubtoken)) {
$token = ([string]$githubtoken.InnerText).Trim()
if (-not [string]::IsNullOrWhiteSpace($token) -and (-not [string]::Equals($token, "unset", [System.StringComparison]::OrdinalIgnoreCase))) {
return $token
}
}
}
$token = ([string]$env:GH_TOKEN).Trim()
if (-not [string]::IsNullOrWhiteSpace($token)) {
return $token
}
$token = ([string]$env:GITHUB_TOKEN).Trim()
if (-not [string]::IsNullOrWhiteSpace($token)) {
return $token
}
return $null
}
function Invoke-GitHubApi($Uri) {
$params = @{
Uri = $Uri
MaximumRedirection = 0
ErrorAction = "Ignore"
UseBasicParsing = $true
UserAgent = $useragent
}
$token = Get-GitHubToken
if (-not [string]::IsNullOrWhiteSpace($token)) {
$params.Headers = @{
Authorization = "Bearer $token"
}
}
Invoke-WebRequest @params
}
function Download-Ytplugin ($plugin, $version) {
$link = ""
$plugin_exe = ""
switch -wildcard ($plugin) {
"yt-dlp*" {
Write-Host "Downloading $plugin ($version)" -ForegroundColor Green
$32bit = ""
if (-Not (Test-Path (Join-Path $env:windir "SysWow64"))) {
$32bit = "_x86"
}
$ytdlp_channel = Check-Ytdlp-Channel
if ($ytdlp_channel -eq 'stable') {
$repo = "https://github.com/yt-dlp/yt-dlp"
}
elseif ($ytdlp_channel -eq 'nightly') {
$repo = "https://github.com/yt-dlp/yt-dlp-nightly-builds"
}
elseif ($ytdlp_channel -eq 'master') {
$repo = "https://github.com/yt-dlp/yt-dlp-master-builds"
}
$link = -join($repo, "/releases/download/", $version, "/", $plugin, $32bit, ".exe")
$plugin_exe = -join($plugin, $32bit, ".exe")
}
"youtube-dl" {
Write-Host "Downloading $plugin ($version)" -ForegroundColor Green
$link = -join("https://yt-dl.org/downloads/", $version, "/youtube-dl.exe")
$plugin_exe = "youtube-dl.exe"
}
}
Invoke-WebRequest -Uri $link -UserAgent $useragent -OutFile $plugin_exe
}
function Extract-Archive ($file) {
$7z = Get-7z
Write-Host "Extracting" $file -ForegroundColor Green
& $7z x -y $file
}
function Get-Latest-Mpv($Arch) {
$filename = ""
$download_link = ""
$api_gh = "https://api.github.com/repos/zhongfly/mpv-winbuild/releases/latest"
$json = Invoke-GitHubApi $api_gh | ConvertFrom-Json
$filename = $json.assets | where { $_.name -Match "mpv-$Arch-[0-9]{8}" } | Select-Object -ExpandProperty name
$download_link = $json.assets | where { $_.name -Match "mpv-$Arch-[0-9]{8}" } | Select-Object -ExpandProperty browser_download_url
if ($filename -is [array]) {
return $filename[0], $download_link[0]
}
else {
return $filename, $download_link
}
}
function Get-Latest-Ytplugin ($plugin) {
switch -wildcard ($plugin) {
"yt-dlp*" {
$ytdlp_channel = Check-Ytdlp-Channel
if ($ytdlp_channel -eq 'stable') {
$repo = "https://github.com/yt-dlp/yt-dlp"
}
elseif ($ytdlp_channel -eq 'nightly') {
$repo = "https://github.com/yt-dlp/yt-dlp-nightly-builds"
}
elseif ($ytdlp_channel -eq 'master') {
$repo = "https://github.com/yt-dlp/yt-dlp-master-builds"
}
$link = -join($repo, "/releases.atom")
Write-Host "Fetching RSS feed for yt-dlp $ytdlp_channel" -ForegroundColor Green
$resp = [xml](Invoke-WebRequest $link -MaximumRedirection 0 -ErrorAction Ignore -UseBasicParsing).Content
$link = $resp.feed.entry[0].link.href
$version = $link.split("/")[-1]
return $version
}
"youtube-dl" {
$link = "https://yt-dl.org/downloads/latest/youtube-dl.exe"
Write-Host "Fetching RSS feed for youtube-dl" -ForegroundColor Green
$resp = Invoke-WebRequest $link -MaximumRedirection 0 -ErrorAction Ignore -UseBasicParsing
$redirect_link = $resp.Headers.Location
$version = $redirect_link.split("/")[4]
return $version
}
}
}
function Get-Latest-FFmpeg ($Arch) {
$api_gh = "https://api.github.com/repos/zhongfly/mpv-winbuild/releases/latest"
$json = Invoke-GitHubApi $api_gh | ConvertFrom-Json
$filename = $json.assets | where { $_.name -Match "ffmpeg-$Arch-git-" } | Select-Object -ExpandProperty name
$download_link = $json.assets | where { $_.name -Match "ffmpeg-$Arch-git-" } | Select-Object -ExpandProperty browser_download_url
if ($filename -is [array]) {
return $filename[0], $download_link[0]
}
else {
return $filename, $download_link
}
}
function Get-Arch {
# Reference: http://superuser.com/a/891443
$FilePath = [System.IO.Path]::Combine((Get-Location).Path, 'mpv.exe')
[int32]$MACHINE_OFFSET = 4
[int32]$PE_POINTER_OFFSET = 60
[byte[]]$data = New-Object -TypeName System.Byte[] -ArgumentList 4096
$stream = New-Object -TypeName System.IO.FileStream -ArgumentList ($FilePath, 'Open', 'Read')
$stream.Read($data, 0, 4096) | Out-Null
# DOS header is 64 bytes, last element, long (4 bytes) is the address of the PE header
[int32]$PE_HEADER_ADDR = [System.BitConverter]::ToInt32($data, $PE_POINTER_OFFSET)
[int32]$machineUint = [System.BitConverter]::ToUInt16($data, $PE_HEADER_ADDR + $MACHINE_OFFSET)
$result = "" | select FilePath, FileType
$result.FilePath = $FilePath
switch ($machineUint)
{
0 { $result.FileType = 'Native' }
0x014c { $result.FileType = 'i686' } # 32bit
0x0200 { $result.FileType = 'Itanium' }
0x8664 { $result.FileType = 'x86_64' } # 64bit
}
$stream.Close()
$result
}
function Get-RegexGroupValue($Text, [string[]]$Patterns, $GroupName) {
if ([string]::IsNullOrEmpty([string]$Text)) {
return $null
}
foreach ($pattern in $Patterns) {
$match = [regex]::Match([string]$Text, $pattern)
if ($match.Success) {
$group = $match.Groups[$GroupName]
if ($group -and -not [string]::IsNullOrEmpty($group.Value)) {
return $group.Value
}
}
}
return $null
}
function Test-CommitEquivalent($Left, $Right) {
if ([string]::IsNullOrEmpty($Left) -or [string]::IsNullOrEmpty($Right)) {
return $false
}
$shorter = [string]$Left
$longer = [string]$Right
if ($shorter.Length -gt $longer.Length) {
$shorter = [string]$Right
$longer = [string]$Left
}
return $longer.StartsWith($shorter, [System.StringComparison]::OrdinalIgnoreCase)
}
function ExtractGitFromFile {
$stripped = .\mpv --no-config | select-string "mpv" | select-object -First 1
$patterns = @(
"-g(?<commit>[0-9A-Fa-f]{7,40})(?=[^0-9A-Fa-f]|$)"
)
return Get-RegexGroupValue $stripped $patterns "commit"
}
function ExtractGitFromURL($filename) {
$patterns = @(
"-git-(?<commit>[0-9A-Fa-f]{7,40})(?=[^0-9A-Fa-f]|$)"
)
return Get-RegexGroupValue $filename $patterns "commit"
}
function ExtractDateFromFile {
$date = (Get-Item ./mpv.exe).LastWriteTimeUtc
$day = $date.Day.ToString("00")
$month = $date.Month.ToString("00")
$year = $date.Year.ToString("0000")
return "$year$month$day"
}
function ExtractDateFromURL($filename) {
$patterns = @(
"-(?<date>[0-9]{8})-git-[0-9A-Fa-f]{7,40}(?=[^0-9A-Fa-f]|$)"
)
return Get-RegexGroupValue $filename $patterns "date"
}
function Ensure-Deno([string]$Context = "update") {
$deno_exe = Join-Path (Get-Location) "deno.exe"
if (Test-Path $deno_exe) {
# Only fetch remote tag when Deno exists and we need to compare
$remote_name = (Invoke-WebRequest "https://dl.deno.land/release-latest.txt" -UseBasicParsing -UserAgent $useragent).Content.Trim()
try {
$current_version = (& $deno_exe --version | Select-String "deno" | Select-Object -First 1).ToString()
$pattern = "deno\s+(?<ver>[0-9a-zA-Z\.-]+)"
$m = [Regex]::Match($current_version, $pattern)
if ($m.Success) {
$current_tag = $m.Groups['ver'].Value
$latest_norm = $remote_name.TrimStart('v')
if ($current_tag -eq $latest_norm) {
Write-Host "You are already using latest Deno -- $remote_name" -ForegroundColor Green
return
}
else {
Write-Host "Newer Deno build available" -ForegroundColor Green
}
}
}
catch {
Write-Host "Error checking current Deno version: $($_.Exception.Message)" -ForegroundColor Yellow
}
$upgradePrompt = "Upgrade local Deno to latest stable now? [Y/n] (default=y)"
$upgradeResp = Read-KeyOrTimeout $upgradePrompt "Y"
Write-Host ""
if ($upgradeResp -eq 'Y') {
& $deno_exe upgrade
}
return
}
# No local deno: only offer install during initial yt-dlp install flow
if ($Context -ne 'install') {
return
}
# Deno provides only x86_64 builds for Windows. Skip on 32-bit systems.
if (-Not (Test-Path (Join-Path $env:windir "SysWow64"))) {
Write-Host "Deno isn't available for 32-bit Windows (x86). Skipping." -ForegroundColor Yellow
return
}
# Fetch remote tag only if we are going to download
Write-Host "Deno is optional, but recommended for yt-dlp." -ForegroundColor Yellow
Write-Host "yt-dlp uses external JS runtimes (EJS) to solve YouTube challenges; Deno is the default recommended runtime." -ForegroundColor Yellow
Write-Host "You may skip this and configure Node, Bun, or QuickJS later (see: https://github.com/yt-dlp/yt-dlp/wiki/EJS)." -ForegroundColor Yellow
Write-Host ""
Write-Host "Deno doesn't exist. " -ForegroundColor Green -NoNewline
$resp = Read-KeyOrTimeout "Proceed with downloading Deno now? [Y/n] (default=y)" "Y"
Write-Host ""
if ($resp -ne 'Y') { return }
$remote_name = (Invoke-WebRequest "https://dl.deno.land/release-latest.txt" -UseBasicParsing -UserAgent $useragent).Content.Trim()
$download_link = "https://dl.deno.land/release/$remote_name/deno-x86_64-pc-windows-msvc.zip"
$archive = "deno-x86_64-pc-windows-msvc.zip"
Write-Host "Downloading Deno (stable) $remote_name" -ForegroundColor Green
Download-Archive $archive $download_link
Check-7z
Extract-Archive $archive
Check-Autodelete $archive
}
function Test-Admin
{
$user = [Security.Principal.WindowsIdentity]::GetCurrent();
(New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
function Create-XML{
@"
<settings>
<arch>unset</arch>
<autodelete>unset</autodelete>
<getffmpeg>unset</getffmpeg>
<getytdl>unset</getytdl>
<ytdlpchannel>unset</ytdlpchannel>
<githubtoken>unset</githubtoken>
</settings>
"@ | Set-Content "settings.xml" -Encoding UTF8
}
function Check-Arch($arch) {
$get_arch = ""
$file = "settings.xml"
if (-not (Test-Path $file)) { Create-XML }
[xml]$doc = Get-Content $file
if ($doc.settings.arch -eq "unset") {
if ($arch -eq "i686") {
$get_arch = "i686"
}
else {
$result = Read-KeyOrTimeout "Choose variant for 64bit builds: x86_64 or x86_64-v3 (for cpu with AVX2 support) [1=x86_64 / 2=x86_64-v3 (default=1)" "D1"
Write-Host ""
if ($result -eq 'D1') {
$get_arch = "x86_64"
}
elseif ($result -eq 'D2') {
$get_arch = "x86_64-v3"
}
else {
throw "Please enter valid input key."
}
}
$doc.settings.arch = $get_arch
$doc.Save($file)
}
else {
$get_arch = $doc.settings.arch
}
return $get_arch
}
function Check-Autodelete($archive) {
$autodelete = ""
$file = "settings.xml"
if (-not (Test-Path $file)) { exit }
[xml]$doc = Get-Content $file
if ($doc.settings.autodelete -eq "unset") {
$result = Read-KeyOrTimeout "Delete archives after extract? [Y/n] (default=Y)" "Y"
Write-Host ""
if ($result -eq 'Y') {
$autodelete = "true"
}
elseif ($result -eq 'N') {
$autodelete = "false"
}
else {
throw "Please enter valid input key."
}
$doc.settings.autodelete = $autodelete
$doc.Save($file)
}
if ($doc.settings.autodelete -eq "true") {
if (Test-Path $archive)
{
Remove-Item -Force $archive
}
}
}
function Check-GetFFmpeg() {
$get_ffmpeg = ""
$file = "settings.xml"
if (-not (Test-Path $file)) { exit }
[xml]$doc = Get-Content $file
if ($doc.settings.getffmpeg -eq "unset") {
Write-Host "FFmpeg doesn't exist. " -ForegroundColor Green -NoNewline
$result = Read-KeyOrTimeout "Proceed with downloading? [Y/n] (default=n)" "N"
Write-Host ""
if ($result -eq 'Y') {
$get_ffmpeg = "true"
}
elseif ($result -eq 'N') {
$get_ffmpeg = "false"
}
else {
throw "Please enter valid input key."
}
$doc.settings.getffmpeg = $get_ffmpeg
$doc.Save($file)
}
else {
$get_ffmpeg = $doc.settings.getffmpeg
}
return $get_ffmpeg
}
function Check-GetYTDL() {
$get_ytdl = ""
$file = "settings.xml"
if (-not (Test-Path $file)) { exit }
[xml]$doc = Get-Content $file
if ($null -eq $doc.settings.getytdl) {
$yt = Check-Ytplugin
if ($yt -eq $null){
$get_ytdl = "unset"
}
elseif ((Get-Item $yt).BaseName -Match "yt-dlp*") {
$get_ytdl = "ytdlp"
}
else {
$get_ytdl = "youtubedl"
}
$newNode = $doc.CreateElement("getytdl")
$newNode.AppendChild($doc.CreateTextNode($get_ytdl)) | out-null
$doc.settings.appendchild($newNode) | out-null
$doc.Save($file)
}
else {
$get_ytdl = $doc.settings.getytdl
}
if ($get_ytdl -eq "unset") {
$result = Read-KeyOrTimeout "Download ytdlp or youtubedl? [1=ytdlp/2=youtubedl/N] (default=1)" "D1"
Write-Host ""
if ($result -eq 'D1') {
$get_ytdl = "ytdlp"
}
elseif ($result -eq 'D2') {
$get_ytdl = "youtubedl"
}
elseif ($result -eq 'N') {
$get_ytdl = "false"
}
else {
throw "Please enter valid input key."
}
$doc.settings.getytdl = $get_ytdl
$doc.Save($file)
}
return $get_ytdl
}
function Check-Ytdlp-Channel() {
$ytdlp_channel = ""
$file = "settings.xml"
if (-not (Test-Path $file)) { exit }
[xml]$doc = Get-Content $file
if ($null -eq $doc.settings.ytdlpchannel) {
$newNode = $doc.CreateElement("ytdlpchannel")
$newNode.AppendChild($doc.CreateTextNode("unset")) | out-null
$doc.settings.appendchild($newNode) | out-null
}
if ($doc.settings.ytdlpchannel -eq "unset") {
$result = Read-KeyOrTimeout "Which update channel to update yt-dlp to? [1=stable/2=nightly/3=master] (default=1)" "D1"
Write-Host ""
if ($result -eq 'D1') {
$ytdlp_channel = "stable"
}
elseif ($result -eq 'D2') {
$ytdlp_channel = "nightly"
}
elseif ($result -eq 'D3') {
$ytdlp_channel = "master"
}
else {
throw "Please enter valid input key."
}
$doc.settings.ytdlpchannel = $ytdlp_channel
$doc.Save($file)
}
else {
$ytdlp_channel = $doc.settings.ytdlpchannel
}
return $ytdlp_channel
}
function Upgrade-Mpv {
$need_download = $false
$remoteName = ""
$download_link = ""
$arch = ""
if (Check-Mpv) {
$file_arch = (Get-Arch).FileType
$arch = Check-Arch $file_arch
$remoteName, $download_link = Get-Latest-Mpv $arch
$localgit = ExtractGitFromFile
$localdate = ExtractDateFromFile
$remotegit = ExtractGitFromURL $remoteName
$remotedate = ExtractDateFromURL $remoteName
if ([string]::IsNullOrEmpty($localgit) -or [string]::IsNullOrEmpty($remotegit) -or [string]::IsNullOrEmpty($localdate) -or [string]::IsNullOrEmpty($remotedate)) {
Write-Host "Unable to compare local and remote mpv build metadata. Downloading latest build." -ForegroundColor Yellow
$need_download = $true
}
elseif (Test-CommitEquivalent $localgit $remotegit) {
if ($localdate -eq $remotedate) {
Write-Host "You are already using latest mpv build -- $remoteName" -ForegroundColor Green
$need_download = $false
}
else {
Write-Host "Newer mpv build available" -ForegroundColor Green
$need_download = $true
}
}
else {
Write-Host "Newer mpv build available" -ForegroundColor Green
$need_download = $true
}
}
else {
Write-Host "mpv doesn't exist. " -ForegroundColor Green -NoNewline
$result = Read-KeyOrTimeout "Proceed with downloading? [Y/n] (default=y)" "Y"
Write-Host ""
if ($result -eq 'Y') {
$need_download = $true
if (Test-Path (Join-Path $env:windir "SysWow64")) {
Write-Host "Detecting System Type is 64-bit" -ForegroundColor Green
$original_arch = "x86_64"
}
else {
Write-Host "Detecting System Type is 32-bit" -ForegroundColor Green
$original_arch = "i686"
}
$arch = Check-Arch $original_arch
$remoteName, $download_link = Get-Latest-Mpv $arch
}
elseif ($result -eq 'N') {
$need_download = $false
}
else {
throw "Please enter valid input key."
}
}
if ($need_download) {
Download-Archive $remoteName $download_link
Check-7z
Extract-Archive $remoteName
}
Check-Autodelete $remoteName
}
function Upgrade-Ytplugin {
if (Check-Ytplugin-In-System) {
Write-Host "yt-dlp.exe or youtube-dl.exe already exists in your system, skip the update check." -ForegroundColor Green
return
}
$yt = Check-Ytplugin
if ($yt) {
$latest_release = Get-Latest-Ytplugin((Get-Item $yt).BaseName)
if ((& $yt --version) -match ($latest_release)) {
Write-Host "You are already using latest" (Get-Item $yt).BaseName "-- $latest_release" -ForegroundColor Green
if ((Get-Item $yt).BaseName -Match "yt-dlp*") {
# Even if yt-dlp is up-to-date, ensure Deno runtime is updated
Ensure-Deno "update"
}
}
else {
Write-Host "Newer" (Get-Item $yt).BaseName "build available" -ForegroundColor Green
if ((Get-Item $yt).BaseName -Match "yt-dlp*") {
$ytdlp_channel = Check-Ytdlp-Channel
& $yt --update-to $ytdlp_channel
Ensure-Deno "update"
}
else {
& $yt --update
}
}
}
else {
Write-Host "ytdlp or youtube-dl doesn't exist. " -ForegroundColor Green -NoNewline
# Use persisted setting to decide which plugin to install
$ytdl = Check-GetYTDL
if ($ytdl -eq 'ytdlp') {
$latest_release = Get-Latest-Ytplugin "yt-dlp"
Download-Ytplugin "yt-dlp" $latest_release
Ensure-Deno "install"
}
elseif ($ytdl -eq 'youtubedl') {
$latest_release = Get-Latest-Ytplugin "youtube-dl"
Download-Ytplugin "youtube-dl" $latest_release
}
elseif ($ytdl -ne 'false') {
throw "Please enter valid input key."
}
}
}
function Upgrade-FFmpeg {
$get_ffmpeg = Check-GetFFmpeg
if ($get_ffmpeg -eq "false") {
return
}
if (Test-Path (Join-Path $env:windir "SysWow64")) {
$original_arch = "x86_64"
$arch = Check-Arch $original_arch
}
else {
$arch = "i686"
}
$need_download = $false
$remote_name, $download_link = Get-Latest-FFmpeg $arch
$ffmpeg = (Get-Location).Path + "\ffmpeg.exe"
$ffmpeg_exist = Test-Path $ffmpeg
if ($ffmpeg_exist) {
$ffmpeg_file = .\ffmpeg -version | select-string "ffmpeg" | select-object -First 1
$file_patterns = @(
"git-[0-9]{4}-[0-9]{2}-[0-9]{2}-(?<commit>[0-9A-Fa-f]{7,40})(?=[^0-9A-Fa-f]|$)",
"N-\d+-g(?<commit>[0-9A-Fa-f]{7,40})(?=[^0-9A-Fa-f]|$)"
)
$url_patterns = @(
"-git-(?<commit>[0-9A-Fa-f]{7,40})(?=[^0-9A-Fa-f]|$)"
)
$local_git = Get-RegexGroupValue $ffmpeg_file $file_patterns "commit"
$remote_git = Get-RegexGroupValue $remote_name $url_patterns "commit"
if ([string]::IsNullOrEmpty($local_git) -or [string]::IsNullOrEmpty($remote_git)) {
Write-Host "Unable to compare local and remote ffmpeg build metadata. Downloading latest build." -ForegroundColor Yellow
$need_download = $true
}
elseif (Test-CommitEquivalent $local_git $remote_git) {
Write-Host "You are already using latest ffmpeg build -- $remote_name" -ForegroundColor Green
$need_download = $false
}
else {
Write-Host "Newer ffmpeg build available" -ForegroundColor Green
$need_download = $true
}
}
else {
$need_download = $true
}
if ($need_download) {
Download-Archive $remote_name $download_link
Check-7z
Extract-Archive $remote_name
}
Check-Autodelete $remote_name
}
function Read-KeyOrTimeout ($prompt, $key){
$seconds = 9
$startTime = Get-Date
$timeOut = New-TimeSpan -Seconds $seconds
Write-Host "$prompt " -ForegroundColor Green
# Basic progress bar
[Console]::CursorLeft = 0
[Console]::Write("[")
[Console]::CursorLeft = $seconds + 2
[Console]::Write("]")
[Console]::CursorLeft = 1
while (-not [System.Console]::KeyAvailable) {
$currentTime = Get-Date
Start-Sleep -s 1
Write-Host "#" -ForegroundColor Green -NoNewline
if ($currentTime -gt $startTime + $timeOut) {
Break
}
}
if ([System.Console]::KeyAvailable) {
$response = [System.Console]::ReadKey($true).Key
}
else {
$response = $key
}
return $response.ToString()
}
#
# Main script entry point
#
if (Test-Admin) {
Write-Host "Running script with administrator privileges" -ForegroundColor Yellow
}
else {
Write-Host "Running script without administrator privileges" -ForegroundColor Red
}
try {
Check-PowershellVersion
# Sourceforge only support TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$global:progressPreference = 'silentlyContinue'
Upgrade-Mpv
Upgrade-Ytplugin
Upgrade-FFmpeg
Write-Host "Operation completed" -ForegroundColor Magenta
}
catch [System.Exception] {
Write-Host $_.Exception.Message -ForegroundColor Red
exit 1
}