feat: Windows-Packaging mit PyInstaller (ZIP ohne Python-Installation)
Fügt Build-Infrastruktur hinzu, mit der whisper-local als selbständiges Windows-ZIP-Paket ohne Python-Installation bereitgestellt werden kann. - whisper_local.spec: PyInstaller onedir-Konfiguration für Windows 64-bit mit allen nativen DLLs (ctranslate2/CUDA, pywin32, PortAudio, onnxruntime, av/FFmpeg) und Hidden Imports für platform-bedingte Backends - build.ps1: Build-Skript das versioniertes ZIP erstellt (.\build.ps1 -Clean) - transcriber.py: portabler Modell-Cache neben der EXE im gebündelten Modus - pyproject.toml: pyinstaller>=6.0 als [build]-Abhängigkeitsgruppe, v1.0.0 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
#Requires -Version 5.1
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Baut whisper-local mit PyInstaller und erstellt ein versioniertes ZIP.
|
||||
.DESCRIPTION
|
||||
Liest die Version aus pyproject.toml, führt PyInstaller aus und packt
|
||||
das dist-Verzeichnis als whisper-local-v{version}-win64.zip.
|
||||
.EXAMPLE
|
||||
.\build.ps1
|
||||
.\build.ps1 -Clean # löscht dist/ und build/ vor dem Build
|
||||
.\build.ps1 -SkipBuild # nur ZIP aus bestehendem dist/ erstellen
|
||||
#>
|
||||
param(
|
||||
[switch]$Clean,
|
||||
[switch]$SkipBuild
|
||||
)
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# ── Versionsnummer aus pyproject.toml lesen ───────────────────────────────────
|
||||
$pyproject = Get-Content "pyproject.toml" -Raw
|
||||
if ($pyproject -match 'version\s*=\s*"([^"]+)"') {
|
||||
$version = $Matches[1]
|
||||
} else {
|
||||
Write-Error "Konnte Version nicht aus pyproject.toml lesen."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$zipName = "whisper-local-v$version-win64.zip"
|
||||
$distDir = "dist\whisper-local"
|
||||
|
||||
Write-Host "=== whisper-local Build v$version ===" -ForegroundColor Cyan
|
||||
|
||||
# ── Optional: Bereinigen ──────────────────────────────────────────────────────
|
||||
if ($Clean) {
|
||||
Write-Host "Bereinige build/ und dist/ ..." -ForegroundColor Yellow
|
||||
if (Test-Path "build") { Remove-Item -Recurse -Force "build" }
|
||||
if (Test-Path "dist") { Remove-Item -Recurse -Force "dist" }
|
||||
if (Test-Path $zipName) { Remove-Item -Force $zipName }
|
||||
}
|
||||
|
||||
# ── PyInstaller ausführen ────────────────────────────────────────────────────
|
||||
if (-not $SkipBuild) {
|
||||
Write-Host "Synchronisiere Build-Abhängigkeiten ..." -ForegroundColor Yellow
|
||||
uv sync --group build
|
||||
|
||||
Write-Host "Starte PyInstaller ..." -ForegroundColor Yellow
|
||||
uv run --group build python -m PyInstaller whisper_local.spec --noconfirm
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "PyInstaller fehlgeschlagen (Exit-Code $LASTEXITCODE)"
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
}
|
||||
|
||||
# ── Prüfen ob dist-Ordner vorhanden ──────────────────────────────────────────
|
||||
if (-not (Test-Path $distDir)) {
|
||||
Write-Error "Ordner '$distDir' nicht gefunden — Build fehlgeschlagen?"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# ── ZIP erstellen ─────────────────────────────────────────────────────────────
|
||||
if (Test-Path $zipName) { Remove-Item -Force $zipName }
|
||||
|
||||
Write-Host "Erstelle $zipName ..." -ForegroundColor Yellow
|
||||
Compress-Archive -Path $distDir -DestinationPath $zipName -CompressionLevel Optimal
|
||||
|
||||
$sizeMB = [math]::Round((Get-Item $zipName).Length / 1MB, 1)
|
||||
Write-Host ""
|
||||
Write-Host "Fertig: $zipName ($sizeMB MB)" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "Testen:" -ForegroundColor Cyan
|
||||
Write-Host " Expand-Archive $zipName -DestinationPath test-release"
|
||||
Write-Host " .\test-release\whisper-local\whisper-local.exe"
|
||||
Reference in New Issue
Block a user