fix(release): restore automatic updates by shipping the speech engine on demand
Some checks failed
deploy-site / deploy (push) Failing after 1m15s
Some checks failed
deploy-site / deploy (push) Failing after 1m15s
Auto-update could not work at all: the installer was 189 MB because it carried the local speech engine and ffmpeg, and the download feed rejects uploads over about 100 MiB, so update metadata could never be published. The installer now leaves those components out and the app fetches them the first time they are needed, verifying every part and the joined archive before installing. The installer is 90.6 MiB, the update feed is published again, and updates stay small because the engine is not re-sent on every release. The fetch is visible and recoverable: the download runs with progress, a failed install cleans up after itself, and Settings > STT shows the runtime status with a manual download action for when the automatic one cannot run.
This commit is contained in:
parent
0411f389d9
commit
0fbbbc1756
42 changed files with 1137 additions and 123 deletions
|
|
@ -11,6 +11,7 @@ import { join } from 'path'
|
|||
import { getLogger } from './LoggerService'
|
||||
import { configGet } from './ConfigService'
|
||||
import { getSidecarCommand, getSidecarBaseUrl, getWhisperModelsDir } from '../utils/paths'
|
||||
import { getRuntimeProvisioner } from './RuntimeProvisioner'
|
||||
import { D3ROError, ErrorCode } from '@d3ro/core/errors'
|
||||
import type {
|
||||
STTModel,
|
||||
|
|
@ -101,6 +102,15 @@ export interface LocalSTTEvents {
|
|||
'transcription-complete': { result: TranscriptionResult }
|
||||
'model-loaded': { model: STTModel; loadTimeMs: number }
|
||||
'download-progress': DownloadProgressEvent
|
||||
/** 런타임(엔진/ffmpeg) 내려받기 진행률 — 필요할 때 자동 설치 */
|
||||
'runtime-progress': {
|
||||
component: string
|
||||
phase: 'index' | 'downloading' | 'extracting' | 'done'
|
||||
percent: number
|
||||
downloadedBytes: number
|
||||
totalBytes: number
|
||||
bytesPerSecond: number
|
||||
}
|
||||
'error': { error: D3ROError }
|
||||
}
|
||||
|
||||
|
|
@ -183,6 +193,10 @@ class LocalSTTService extends EventEmitter {
|
|||
// (실측: sidecar crash 루프 중 ERR_UNHANDLED_ERROR). 기본 sink로 방지 —
|
||||
// 실제 로깅은 _emitError에서 수행.
|
||||
this.on('error', () => { /* default sink */ })
|
||||
// 런타임 내려받기 진행률을 그대로 중계한다 (IPC가 renderer로 전달)
|
||||
getRuntimeProvisioner().on('progress', (payload) => {
|
||||
this.emit('runtime-progress', payload)
|
||||
})
|
||||
}
|
||||
|
||||
private _state: STTState = STTState.Uninitialized
|
||||
|
|
@ -638,8 +652,8 @@ class LocalSTTService extends EventEmitter {
|
|||
// dev mode HMR/재시작으로 이전 sidecar가 orphan으로 남아있을 수 있음.
|
||||
this._port = await this._findFreePort(SIDECAR_PORT, 20)
|
||||
|
||||
// 번들/venv 경로가 깨졌으면 여기서 즉시 실패한다 (조용한 PATH 폴백 금지).
|
||||
const launch = getSidecarCommand()
|
||||
// 설치본에는 엔진이 없다 — 없으면 여기서 feed에서 내려받고 산다. dev는 venv/번들 경로를 쓴다.
|
||||
const launch = await this._resolveSidecarLaunch()
|
||||
const fullArgs = [
|
||||
...launch.args,
|
||||
'--port',
|
||||
|
|
@ -726,6 +740,31 @@ class LocalSTTService extends EventEmitter {
|
|||
consume(child.stderr, (message) => sidecarLogger.warn(message))
|
||||
}
|
||||
|
||||
/**
|
||||
* 사이드카 실행 방법을 결정한다.
|
||||
* 설치본에서 엔진이 아직 없으면 feed에서 내려받아 설치한 뒤 경로를 돌려준다.
|
||||
* 진행률은 runtime-progress 이벤트로 노출된다.
|
||||
*/
|
||||
private async _resolveSidecarLaunch(): Promise<{
|
||||
command: string
|
||||
args: string[]
|
||||
source: 'bundled' | 'provisioned' | 'venv' | 'python'
|
||||
}> {
|
||||
try {
|
||||
return getSidecarCommand()
|
||||
} catch (err) {
|
||||
const needsInstall =
|
||||
err instanceof D3ROError && err.code === ErrorCode.STTEngineNotInstalled
|
||||
if (!needsInstall) throw err
|
||||
}
|
||||
|
||||
logger.info('로컬 음성 엔진이 없습니다 — 자동 다운로드를 시작합니다')
|
||||
await getRuntimeProvisioner().ensure('sidecar')
|
||||
const launch = getSidecarCommand()
|
||||
logger.info(`런타임 설치 후 사이드카 경로: ${launch.command} (${launch.source})`)
|
||||
return launch
|
||||
}
|
||||
|
||||
/** sidecar 기동 실패 원인을 사용자가 조치할 수 있는 문구로 바꾼다. */
|
||||
private _spawnFailureError(
|
||||
err: Error,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue