Skip to content

Commit 72ac00b

Browse files
committed
feat: replace whisper-server with ctranslate2-server and update build scripts
- Added new script to build ctranslate2-server binaries for various platforms. - Removed the old whisper-server build script and its associated PowerShell script. - Updated end-to-end smoke test to use ctranslate2-server instead of whisper-server. - Added tar package dependency in package.json and package-lock.json. - Cleaned up unnecessary dev dependencies in package-lock.json.
1 parent e6e1d6f commit 72ac00b

34 files changed

Lines changed: 2456 additions & 1236 deletions
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
name: Build ctranslate2-server binaries
2+
3+
# Builds the bundled `ctranslate2-server` variants — CUDA (NVIDIA) and CPU
4+
# fallback — then uploads them as GitHub artifacts so `build.yml` can attach
5+
# them to installer builds.
6+
#
7+
# Triggered:
8+
# * manually via workflow_dispatch (release-blocking binary refresh)
9+
# * automatically when the build script or its companion files change
10+
#
11+
# ponytail: single-host CPU builds are cheap; the CUDA variant requires a
12+
# self-hosted runner with the matching SDK. Linux matrix entries probe for
13+
# nvcc + exit 0 with a hint when the toolchain is missing rather than
14+
# failing CI outright — useful smoke-test signal.
15+
#
16+
# Replaces `build-whisper-binaries.yml`. See
17+
# docs/engineering/stt-ctranslate2-migration.md for the full decision.
18+
19+
on:
20+
workflow_dispatch:
21+
inputs:
22+
ref:
23+
description: "CTranslate2 ref to checkout (default v4.4.0 — pinned in CMakeLists.txt)"
24+
required: false
25+
default: "v4.4.0"
26+
type: string
27+
enable_cuda:
28+
description: "Build the CUDA variant when the host has an nvcc toolchain"
29+
required: false
30+
default: "true"
31+
type: choice
32+
options:
33+
- "true"
34+
- "false"
35+
push:
36+
paths:
37+
- "scripts/build-ctranslate2-server.sh"
38+
- "electron/native/ctranslate2-server/**"
39+
- ".github/workflows/build-ctranslate2-server.yml"
40+
41+
permissions:
42+
contents: read
43+
44+
jobs:
45+
build:
46+
name: ${{ matrix.label }}
47+
strategy:
48+
fail-fast: false
49+
matrix:
50+
include:
51+
- os: macos-latest
52+
arch: arm64
53+
label: macOS arm64 (CPU via Apple Accelerate)
54+
variants: "cpu"
55+
- os: ubuntu-latest
56+
arch: x64
57+
label: Linux x64 (CUDA + CPU fallback)
58+
variants: "cuda cpu"
59+
- os: windows-latest
60+
arch: x64
61+
label: Windows x64 (CPU fallback only — CUDA on self-hosted GPU runners)"
62+
variants: "cpu"
63+
runs-on: ${{ matrix.os }}
64+
steps:
65+
- name: Checkout
66+
uses: actions/checkout@v4
67+
68+
- name: Setup Node.js
69+
uses: ./.github/actions/setup
70+
71+
- name: Setup CMake / Ninja
72+
if: matrix.os != 'windows-latest'
73+
run: |
74+
sudo apt-get update
75+
sudo apt-get install -y ninja-build build-essential
76+
- name: Setup CMake / Ninja (Windows)
77+
if: matrix.os == 'windows-latest'
78+
uses: ilammy/msvc-cmake-build@v1
79+
with:
80+
cmake-path: "C:\\Program Files\\CMake\\bin"
81+
82+
- name: Run ctranslate2-server build script
83+
env:
84+
ENABLE_CUDA: ${{ github.event.inputs.enable_cuda || 'true' }}
85+
run: bash scripts/build-ctranslate2-server.sh
86+
87+
- name: Stage binaries for upload
88+
shell: bash
89+
run: |
90+
set -euo pipefail
91+
BAG="ctranslate2-server-${{ matrix.os }}-${{ matrix.arch }}"
92+
mkdir -p "$BAG"
93+
# Ship every variant that resolved, even when the host could only
94+
# build CPU — `gpuDetector` falls back to CPU when no better match
95+
# is present.
96+
find electron/native/bin -type f -name 'ctranslate2-server-*' \
97+
-exec cp -v {} "$BAG/" \;
98+
tar -czf "${BAG}.tar.gz" "$BAG"
99+
echo "Staged ${BAG}.tar.gz"
100+
101+
- name: Upload binaries
102+
uses: actions/upload-artifact@v4
103+
with:
104+
name: ctranslate2-server-${{ matrix.os }}-${{ matrix.arch }}
105+
path: ctranslate2-server-${{ matrix.os }}-${{ matrix.arch }}.tar.gz
106+
if-no-files-found: error
107+
retention-days: 30
108+
109+
- name: Workflow summary
110+
if: always()
111+
run: |
112+
{
113+
echo "## ctranslate2-server build"
114+
echo ""
115+
echo "- Matrix: \`${{ matrix.label }}\`"
116+
echo "- Result: ${{ job.status }}"
117+
} >> "$GITHUB_STEP_SUMMARY"

‎.github/workflows/build-whisper-binaries.yml‎

Lines changed: 0 additions & 108 deletions
This file was deleted.

‎.github/workflows/build.yml‎

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,11 @@ jobs:
4444
path: caption-assets
4545
key: caption-assets-${{ runner.os }}-${{ hashFiles('scripts/fetch-caption-model.mjs') }}
4646

47-
# ponytail: bundled Silero VAD model is required at runtime — whisper.cpp
48-
# is started with `--vad --vad-model <path>`, no fallback. The file must
49-
# be on disk *before* electron-builder packages the installer (extraResources
50-
# copies `electron/native/models/` wholesale). Skipping this step makes the
51-
# installer ship without the model and the app fails to transcribe at
52-
# first use with a loud error. The script is idempotent (skips when
53-
# already present) so re-running on cache hits is free.
54-
- name: Fetch Silero VAD model
55-
shell: bash
56-
run: bash scripts/fetch-vad-model.sh
47+
# ponytail: no VAD fetch here — the CTranslate2 server provides word
48+
# timestamps via its built-in `.align()` (real DTW over Whisper's
49+
# cross-attention weights), so the bundled Silero VAD model used by
50+
# whisper.cpp is gone. See docs/engineering/stt-ctranslate2-migration.md
51+
# § "What gets removed".
5752

5853
- name: Build Windows app
5954
run: npm run build:win -- --publish never
@@ -96,13 +91,7 @@ jobs:
9691
path: caption-assets
9792
key: caption-assets-${{ runner.os }}-${{ hashFiles('scripts/fetch-caption-model.mjs') }}
9893

99-
# ponytail: bundled Silero VAD model — required at runtime for accurate
100-
# word-level timestamps (see build-windows comment). extraResources in
101-
# electron-builder.json5 copies `electron/native/models/` wholesale, so
102-
# this fetch must complete before the package step.
103-
- name: Fetch Silero VAD model
104-
run: bash scripts/fetch-vad-model.sh
105-
94+
# ponytail: no VAD fetch here either (see build-windows comment).
10695
- name: Resolve macOS signing
10796
id: signing
10897
env:
@@ -266,13 +255,7 @@ jobs:
266255
path: caption-assets
267256
key: caption-assets-${{ runner.os }}-${{ hashFiles('scripts/fetch-caption-model.mjs') }}
268257

269-
# ponytail: bundled Silero VAD model — required at runtime for accurate
270-
# word-level timestamps (see build-windows comment). extraResources in
271-
# electron-builder.json5 copies `electron/native/models/` wholesale, so
272-
# this fetch must complete before the package step.
273-
- name: Fetch Silero VAD model
274-
run: bash scripts/fetch-vad-model.sh
275-
258+
# ponytail: no VAD fetch here either (see build-windows comment).
276259
- name: Build Linux app
277260
run: npm run build:linux -- --publish never
278261

‎electron-builder.json5‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,15 @@
3131
],
3232
// Asset layout contract: "wallpapers/" and "cursors/" under resourcesPath must
3333
// align with assetBaseDir in electron/preload.ts (packaged branch).
34-
// Native capture helpers + whisper-server binaries live under
34+
// Native capture helpers + ctranslate2-server binaries live under
3535
// `electron/native/bin/<platform>-<arch>/` and the per-platform sections
3636
// below limit them to the matching arch in each installer.
37+
//
38+
// ponytail: bundled model files (used by whisper.cpp's Silero VAD) used to
39+
// ship under `electron/native/models/`. CTranslate2's runtime downloads
40+
// its own model into the userData cache on first use — see
41+
// electron/stt/modelManager.ts — so the build-time model directory is
42+
// gone too.
3743
"extraResources": [
3844
{
3945
"from": "public/wallpapers",
@@ -42,10 +48,6 @@
4248
{
4349
"from": "public/cursors",
4450
"to": "cursors"
45-
},
46-
{
47-
"from": "electron/native/models",
48-
"to": "models"
4951
}
5052
],
5153

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
3+
project(openscreen-ctranslate2-server LANGUAGES CXX)
4+
5+
set(CMAKE_CXX_STANDARD 20)
6+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
7+
set(CMAKE_CXX_EXTENSIONS OFF)
8+
9+
# ponytail: CTranslate2's C++ library is built standalone (the Python wheel is a
10+
# separate, optional step). Pin the upstream ref in one place so a release
11+
# maintainer only edits here — see docs/engineering/stt-ctranslate2-migration.md
12+
# § Decision. CUDA support is opt-in via -DENABLE_CUDA=ON; the goal-pursue
13+
# baseline (this commit) builds CPU-only because that's the mat that actually
14+
# compiles on a stock Windows / Linux host without a CUDA SDK.
15+
set(CTRANS2_REPO "https://github.com/OpenNMT/CTranslate2.git" CACHE STRING "CTranslate2 git URL")
16+
set(CTRANS2_REF "v4.4.0" CACHE STRING "CTranslate2 ref/tag/branch")
17+
set(ENABLE_CUDA OFF CACHE BOOL "Build CTranslate2 + server with CUDA")
18+
option(WITH_MKL "Use Intel MKL backend (Linux/macOS only; OFF on Windows)" OFF)
19+
option(WITH_OPENBLAS "Use OpenBLAS backend" ON)
20+
# ponytail: CTranslate2 pulls a fair amount of binary under FetchContent
21+
# (Intel MKL/oneDNN, Intel MKL-DNN is ~80 MB alone). Disable it. On Windows we
22+
# drop BLAS entirely — CTranslate2 still runs without an external BLAS, just
23+
# slower; the goal-pursue build here is "compiles and answers the test",
24+
# benchmarks come later.
25+
if(WIN32)
26+
set(WITH_BLAS_DEFAULT OFF)
27+
else()
28+
set(WITH_BLAS_DEFAULT ON)
29+
endif()
30+
option(WITH_BLAS "Build CTranslate2 with a BLAS backend (oneDNN/MKL/OpenBLAS)" ${WITH_BLAS_DEFAULT})
31+
32+
include(FetchContent)
33+
set(FETCHCONTENT_QUIET OFF)
34+
FetchContent_Declare(
35+
ctranslate2
36+
GIT_REPOSITORY ${CTRANS2_REPO}
37+
GIT_TAG ${CTRANS2_REF}
38+
GIT_SHALLOW TRUE
39+
GIT_SUBMODULES_RECURSE TRUE
40+
)
41+
FetchContent_Declare(
42+
httplib
43+
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
44+
GIT_TAG v0.18.1
45+
GIT_SHALLOW TRUE
46+
)
47+
FetchContent_Declare(
48+
json
49+
GIT_REPOSITORY https://github.com/nlohmann/json.git
50+
GIT_TAG v3.11.3
51+
GIT_SHALLOW TRUE
52+
)
53+
54+
set(CTRANS2_BUILD_TESTS OFF CACHE BOOL "" FORCE)
55+
set(CTRANS2_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
56+
set(CTRANS2_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
57+
set(CTRANS2_BUILD_PYTHON OFF CACHE BOOL "" FORCE)
58+
set(CTRANS2_CPU_ONLY OFF CACHE BOOL "" FORCE)
59+
set(CTRANS2_INSTALL OFF CACHE BOOL "" FORCE)
60+
set(CTRANS2_SHARED_LIB OFF CACHE BOOL "" FORCE)
61+
set(CTRANS2_STATIC_LIB ON CACHE BOOL "" FORCE)
62+
set(CTRANS2_WITH_MKL ${WITH_MKL} CACHE BOOL "" FORCE)
63+
set(CTRANS2_WITH_OPENBLAS ${WITH_OPENBLAS} CACHE BOOL "" FORCE)
64+
set(CTRANS2_WITH_BLAS ${WITH_BLAS} CACHE BOOL "" FORCE)
65+
set(CTRANS2_WITH_CUDA ${ENABLE_CUDA} CACHE BOOL "" FORCE)
66+
set(CTRANS2_WITH_TENSOR_PARALLEL OFF CACHE BOOL "" FORCE)
67+
set(CTRANS2_WITH_RUY OFF CACHE BOOL "" FORCE)
68+
FetchContent_MakeAvailable(ctranslate2 httplib json)
69+
70+
add_executable(ctranslate2-server
71+
src/main.cpp
72+
)
73+
target_include_directories(ctranslate2-server PRIVATE include)
74+
target_link_libraries(ctranslate2-server PRIVATE
75+
ctranslate2::ctranslate2
76+
httplib::httplib
77+
nlohmann_json::nlohmann_json
78+
)
79+
80+
if(WIN32)
81+
target_compile_definitions(ctranslate2-server PRIVATE
82+
NOMINMAX WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0A00
83+
)
84+
set_target_properties(ctranslate2-server PROPERTIES WIN32_EXECUTABLE OFF)
85+
endif()

0 commit comments

Comments
 (0)