The GUI no longer needs command line arguments: on first run it opens a settings dialog that lists the registry, downloads models in-app (mirror base, HTTP proxy, resume), and picks the active model. The caption window gains a tray icon (show/hide, settings, quit); its close button hides to the tray so the window can always be brought back, and the language pill opens the settings. Appearance (font, opacity, line counts, position) is persisted. CLI flags remain for automated testing and override settings. GUI 不再依赖命令行参数:首次启动打开设置对话框,可在应用内下载模型 (下载源/代理/断点续传)、选择当前模型与识别语言;字幕窗增加托盘(显示 隐藏/设置/退出),关闭按钮改为隐藏到托盘以免关掉后无法再打开,语言标签 点击进设置;字号/透明度/行数/位置都会持久化。命令行参数保留作自动化测试。
161 lines
6.5 KiB
CMake
161 lines
6.5 KiB
CMake
cmake_minimum_required(VERSION 3.24)
|
||
project(live-caption LANGUAGES CXX)
|
||
|
||
set(CMAKE_CXX_STANDARD 17)
|
||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||
set(CMAKE_AUTOMOC ON)
|
||
if(NOT CMAKE_BUILD_TYPE)
|
||
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
|
||
endif()
|
||
|
||
option(LC_BUILD_TESTS "构建单元测试" ON)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# llama.cpp / libmtmd 的搜索路径
|
||
#
|
||
# Debian/Deepin 把 llama 的 CMake config 放在非标准目录 cmake-private/,
|
||
# 而 pkg-config 的 llama.pc 又漏了 -lmtmd。所以这里把两个路径都塞进搜索前缀,
|
||
# 并单独用 find_library 找 mtmd。
|
||
# ---------------------------------------------------------------------------
|
||
foreach(_p
|
||
/usr/lib/x86_64-linux-gnu/llama
|
||
/usr/lib/x86_64-linux-gnu/llama/cmake-private
|
||
/usr/lib/x86_64-linux-gnu/llama/pkgconfig)
|
||
if(EXISTS "${_p}")
|
||
list(APPEND CMAKE_PREFIX_PATH "${_p}")
|
||
set(ENV{PKG_CONFIG_PATH} "${_p}:$ENV{PKG_CONFIG_PATH}")
|
||
endif()
|
||
endforeach()
|
||
|
||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets Network)
|
||
find_package(PkgConfig REQUIRED)
|
||
find_package(Threads REQUIRED)
|
||
|
||
pkg_check_modules(SAMPLERATE REQUIRED IMPORTED_TARGET samplerate)
|
||
pkg_check_modules(PULSE REQUIRED IMPORTED_TARGET libpulse)
|
||
|
||
# --- llama:优先系统 pkg-config,其次 CMake config,最后 FetchContent 兜底 ---
|
||
pkg_check_modules(LLAMA QUIET IMPORTED_TARGET llama)
|
||
if(LLAMA_FOUND)
|
||
set(LC_LLAMA_TARGET PkgConfig::LLAMA)
|
||
message(STATUS "llama: 使用系统 pkg-config (${LLAMA_VERSION})")
|
||
else()
|
||
message(STATUS "llama: 系统未找到,改用 FetchContent 拉取固定版本")
|
||
include(FetchContent)
|
||
set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE ALWAYS) # 先 find_package,失败再拉源码
|
||
FetchContent_Declare(llama
|
||
GIT_REPOSITORY https://github.com/ggml-org/llama.cpp.git
|
||
GIT_TAG b9951
|
||
FIND_PACKAGE_ARGS NAMES llama CONFIG)
|
||
set(LLAMA_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||
set(LLAMA_BUILD_SERVER OFF CACHE BOOL "" FORCE)
|
||
set(LLAMA_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||
FetchContent_MakeAvailable(llama)
|
||
set(LC_LLAMA_TARGET llama)
|
||
endif()
|
||
|
||
# --- mtmd:llama.pc 里没有,单独找 ---
|
||
find_library(LC_MTMD_LIB NAMES mtmd HINTS /usr/lib/x86_64-linux-gnu/llama)
|
||
if(NOT LC_MTMD_LIB)
|
||
message(FATAL_ERROR "找不到 libmtmd(应随 libllama0 一起安装)")
|
||
endif()
|
||
message(STATUS "mtmd: ${LC_MTMD_LIB}")
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# sherpa-onnx(X-ASR / zipformer / Nemotron 等流式 ONNX 模型)
|
||
#
|
||
# 注意:官方预编译库是用旧 C++ ABI 编译的,所以只能用它的 C API。
|
||
# 安装:把官方的 sherpa-onnx-vX.Y.Z-linux-x64-shared.tar.bz2 解到某个目录,
|
||
# 用 -DSHERPA_ONNX_ROOT=<dir> 指定(默认见下)。
|
||
# ---------------------------------------------------------------------------
|
||
set(SHERPA_ONNX_ROOT "$ENV{HOME}/.local/opt/sherpa-onnx" CACHE PATH "sherpa-onnx 安装目录")
|
||
set(LC_HAS_SHERPA OFF)
|
||
if(EXISTS "${SHERPA_ONNX_ROOT}/include/sherpa-onnx/c-api/c-api.h")
|
||
find_library(LC_SHERPA_C_API NAMES sherpa-onnx-c-api
|
||
HINTS "${SHERPA_ONNX_ROOT}/lib" REQUIRED)
|
||
find_library(LC_SHERPA_ORT NAMES onnxruntime
|
||
HINTS "${SHERPA_ONNX_ROOT}/lib" REQUIRED)
|
||
set(LC_HAS_SHERPA ON)
|
||
message(STATUS "sherpa-onnx: ${SHERPA_ONNX_ROOT}")
|
||
else()
|
||
message(WARNING "未找到 sherpa-onnx(${SHERPA_ONNX_ROOT}),流式 ONNX 后端将不可用")
|
||
endif()
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# core:全部业务逻辑,刻意不依赖 Qt(方便测试与复用)
|
||
# ---------------------------------------------------------------------------
|
||
add_library(livecaption_core STATIC
|
||
src/core/transcript.cpp
|
||
src/core/audio.cpp
|
||
src/core/qwen3asr.cpp
|
||
src/core/streamingasr.cpp
|
||
src/core/livepipeline.cpp
|
||
)
|
||
if(LC_HAS_SHERPA)
|
||
target_sources(livecaption_core PRIVATE src/core/sherpaasr.cpp)
|
||
target_compile_definitions(livecaption_core PUBLIC LC_HAVE_SHERPA=1)
|
||
target_include_directories(livecaption_core PRIVATE "${SHERPA_ONNX_ROOT}/include")
|
||
target_link_libraries(livecaption_core PUBLIC ${LC_SHERPA_C_API} ${LC_SHERPA_ORT})
|
||
endif()
|
||
target_include_directories(livecaption_core PUBLIC src/core)
|
||
target_link_libraries(livecaption_core PUBLIC
|
||
Threads::Threads
|
||
PkgConfig::SAMPLERATE
|
||
PkgConfig::PULSE
|
||
${LC_LLAMA_TARGET}
|
||
${LC_MTMD_LIB}
|
||
)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# models:模型注册表与存储(Qt;注册表编译进二进制)
|
||
# ---------------------------------------------------------------------------
|
||
add_library(livecaption_models STATIC
|
||
src/models/modelstore.cpp
|
||
src/models/modeldownloader.cpp
|
||
)
|
||
target_include_directories(livecaption_models PUBLIC src/models)
|
||
target_link_libraries(livecaption_models PUBLIC Qt6::Core Qt6::Network)
|
||
qt_add_resources(livecaption_models "registry"
|
||
PREFIX "/"
|
||
BASE "${CMAKE_CURRENT_SOURCE_DIR}"
|
||
FILES data/models.json)
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# ui:悬浮窗与 Qt 适配层
|
||
# ---------------------------------------------------------------------------
|
||
add_library(livecaption_ui STATIC
|
||
src/ui/captionwindow.cpp
|
||
src/ui/livetranscriber.cpp
|
||
src/ui/appsettings.cpp
|
||
src/ui/settingsdialog.cpp
|
||
)
|
||
target_include_directories(livecaption_ui PUBLIC src/ui)
|
||
target_link_libraries(livecaption_ui PUBLIC livecaption_core livecaption_models Qt6::Widgets)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 可执行程序
|
||
# ---------------------------------------------------------------------------
|
||
# GUI:悬浮字幕窗
|
||
add_executable(live-caption apps/gui/main.cpp)
|
||
target_include_directories(live-caption PRIVATE apps/common)
|
||
target_link_libraries(live-caption PRIVATE livecaption_ui livecaption_models)
|
||
|
||
# CLI:文件 / 流式文件 / 命令行实时;不链接 Qt Widgets
|
||
add_executable(live-caption-cli apps/cli/main.cpp)
|
||
target_include_directories(live-caption-cli PRIVATE apps/common)
|
||
target_link_libraries(live-caption-cli PRIVATE livecaption_core livecaption_models)
|
||
|
||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||
foreach(_t livecaption_core livecaption_ui livecaption_models live-caption live-caption-cli)
|
||
target_compile_options(${_t} PRIVATE -Wall -Wextra -Wno-unused-parameter)
|
||
endforeach()
|
||
endif()
|
||
|
||
# ---------------------------------------------------------------------------
|
||
if(LC_BUILD_TESTS)
|
||
enable_testing()
|
||
add_subdirectory(tests)
|
||
endif()
|