vignette/scripts/start-local-whisper-stt.ps1
2026-08-09 18:22:03 +09:00

89 lines
3 KiB
PowerShell

param(
[int]$Port = 9882,
[ValidateSet('large-v3', 'large-v3-turbo', 'medium', 'small', 'base')]
[string]$Model = 'small',
[ValidateSet('auto', 'cuda', 'cpu')]
[string]$Device = 'cpu',
[int]$WaitReadySeconds = 180
)
# 노트북 상주 faster-whisper 스트리밍 STT 사이드카를 띄운다.
# 오디오는 호스트를 벗어나지 않고 외부 STT 키도 필요 없다.
$ErrorActionPreference = 'Stop'
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
$repoRoot = Split-Path -Parent $PSScriptRoot
$serverScript = Join-Path $PSScriptRoot 'local-whisper-stt-server.py'
$runtimeLogDir = Join-Path $env:TEMP 'Vignette\local-whisper-stt'
$stdoutLog = Join-Path $runtimeLogDir 'server.out.log'
$stderrLog = Join-Path $runtimeLogDir 'server.err.log'
if (!(Test-Path -LiteralPath $serverScript)) {
throw "로컬 whisper 서버 스크립트를 찾지 못했습니다: $serverScript"
}
# faster-whisper 가 설치된 인터프리터를 고른다.
$pyCandidates = @(
(Join-Path $env:LOCALAPPDATA 'Programs\Python\Python311\python.exe'),
(Join-Path $env:LOCALAPPDATA 'Programs\Python\Python312\python.exe'),
'python'
)
$python = $null
foreach ($candidate in $pyCandidates) {
try {
& $candidate -c 'import faster_whisper, websockets' 2>$null
if ($LASTEXITCODE -eq 0) { $python = $candidate; break }
} catch { }
}
if (-not $python) {
throw 'faster_whisper 와 websockets 가 설치된 python 을 찾지 못했습니다.'
}
Write-Output "python: $python"
$listener = Get-NetTCPConnection -State Listen -LocalPort $Port -ErrorAction SilentlyContinue
if ($null -ne $listener) {
Write-Output "포트 $Port 에 이미 리스너가 있습니다. 임의 종료하지 않았습니다."
return
}
New-Item -ItemType Directory -Path $runtimeLogDir -Force | Out-Null
$serverArgs = @(
'-X', 'utf8', $serverScript,
'--host', '127.0.0.1',
'--port', "$Port",
'--model', $Model,
'--device', $Device,
'--enable'
)
$process = Start-Process -WindowStyle Hidden -FilePath $python `
-ArgumentList $serverArgs `
-WorkingDirectory $repoRoot `
-RedirectStandardOutput $stdoutLog `
-RedirectStandardError $stderrLog `
-PassThru
Write-Output "로컬 whisper STT 로드를 시작했습니다. PID=$($process.Id) model=$Model device=$Device"
Write-Output "로그: $stdoutLog"
if ($WaitReadySeconds -le 0) {
return
}
$deadline = (Get-Date).AddSeconds($WaitReadySeconds)
while ((Get-Date) -lt $deadline) {
if ($process.HasExited) {
throw "로컬 whisper STT가 준비되기 전에 종료됐습니다. stderr=$stderrLog"
}
$ready = Get-NetTCPConnection -State Listen -LocalPort $Port -ErrorAction SilentlyContinue
if ($null -ne $ready) {
Write-Output "로컬 whisper STT 준비 완료: ws://127.0.0.1:$Port/v1/listen"
if (Test-Path -LiteralPath $stdoutLog) {
Get-Content -LiteralPath $stdoutLog -Tail 1
}
return
}
Start-Sleep -Seconds 2
}
throw "로컬 whisper STT 준비 시간이 ${WaitReadySeconds}초를 넘었습니다. 로그: $stdoutLog"