From a56f273c45f9febcc9c4ab976836e095dd496e6a Mon Sep 17 00:00:00 2001 From: impressionyang Date: Wed, 13 May 2026 17:36:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Windows=20Qt5.12=20?= =?UTF-8?q?MinGW=20=E7=BC=96=E8=AF=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - std::unordered_map 替换为 QHash(旧版 GCC 7.3.0 不支持 QString 的 std::hash) - 涉及文件: whisper_tokenizer.h/cpp, sense_voice_tokenizer.h/cpp - STTEngine::Impl 的 loadInWorker 和 mutex 移出 HAVE_ONNXRUNTIME 条件编译块 - loadModelSync/loadModelAsync 添加 HAVE_ONNXRUNTIME 保护 Co-Authored-By: Claude Opus 4.6 --- src/core/sense_voice_tokenizer.cpp | 4 ++-- src/core/sense_voice_tokenizer.h | 9 ++++----- src/core/stt_engine.cpp | 13 ++++++++++++- src/core/whisper_tokenizer.cpp | 10 +++++----- src/core/whisper_tokenizer.h | 11 +++++------ 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/core/sense_voice_tokenizer.cpp b/src/core/sense_voice_tokenizer.cpp index 971f43e..ce8a1cc 100644 --- a/src/core/sense_voice_tokenizer.cpp +++ b/src/core/sense_voice_tokenizer.cpp @@ -41,7 +41,7 @@ bool SenseVoiceTokenizer::load(const QString& tokensPath) { } LOG_INFO(kTag, QString("词表已加载: %1 个词条 (%2)").arg(lineCount).arg(tokensPath)); - return !tokenToString_.empty(); + return !tokenToString_.isEmpty(); } QString SenseVoiceTokenizer::decode(const std::vector& tokens) const { @@ -56,7 +56,7 @@ QString SenseVoiceTokenizer::decode(const std::vector& tokens) const { auto it = tokenToString_.find(token); if (it != tokenToString_.end()) { - QString decoded = decodeBPE(it->second); + QString decoded = decodeBPE(it.value()); // 过滤 SenseVoice 特殊标签: <|zh|>, <|speech|>, <|NEUTRAL|> 等 if (decoded.startsWith("<|") && decoded.endsWith("|>")) { continue; diff --git a/src/core/sense_voice_tokenizer.h b/src/core/sense_voice_tokenizer.h index a992fda..f3c5516 100644 --- a/src/core/sense_voice_tokenizer.h +++ b/src/core/sense_voice_tokenizer.h @@ -1,9 +1,8 @@ #pragma once #include -#include +#include #include -#include namespace impress { @@ -24,10 +23,10 @@ public: QString decode(const std::vector& tokens) const; /** @brief 是否已加载 */ - bool isLoaded() const { return !tokenToString_.empty(); } + bool isLoaded() const { return !tokenToString_.isEmpty(); } /** @brief 词表大小 */ - int vocabSize() const { return static_cast(tokenToString_.size()); } + int vocabSize() const { return tokenToString_.size(); } // 特殊 token static constexpr int kTokenBlank = 0; // CTC blank / @@ -35,7 +34,7 @@ public: static constexpr int kTokenEOS = 2; // private: - std::unordered_map tokenToString_; + QHash tokenToString_; QString decodeBPE(const QString& token) const; }; diff --git a/src/core/stt_engine.cpp b/src/core/stt_engine.cpp index 0fe97a2..d8fd787 100644 --- a/src/core/stt_engine.cpp +++ b/src/core/stt_engine.cpp @@ -116,9 +116,9 @@ struct STTEngine::Impl { return false; } } +#endif QMutex mutex; -#endif }; STTEngine::STTEngine(QObject* parent) @@ -139,6 +139,7 @@ bool STTEngine::loadModelSync(const QString& modelPath, unloadModel(); } +#ifdef HAVE_ONNXRUNTIME QString errorMsg; bool success = impl_->loadInWorker(modelPath, device, numThreads, errorMsg); loaded_ = success; @@ -150,6 +151,11 @@ bool STTEngine::loadModelSync(const QString& modelPath, emit error(errorMsg); } return success; +#else + (void)modelPath; (void)device; (void)numThreads; + LOG_ERROR(kTag, "ONNX Runtime 未编译启用"); + return false; +#endif } void STTEngine::loadModelAsync(const QString& modelPath, @@ -161,6 +167,7 @@ void STTEngine::loadModelAsync(const QString& modelPath, unloadModel(); } +#ifdef HAVE_ONNXRUNTIME LOG_INFO(kTag, QString("异步加载模型: %1").arg(modelPath)); QFuture future = QtConcurrent::run([this, modelPath, device, numThreads]() { @@ -177,6 +184,10 @@ void STTEngine::loadModelAsync(const QString& modelPath, } }, Qt::QueuedConnection); }); +#else + (void)modelPath; (void)device; (void)numThreads; + LOG_ERROR(kTag, "ONNX Runtime 未编译启用"); +#endif } void STTEngine::unloadModel() { diff --git a/src/core/whisper_tokenizer.cpp b/src/core/whisper_tokenizer.cpp index 0fa8d03..a0cb520 100644 --- a/src/core/whisper_tokenizer.cpp +++ b/src/core/whisper_tokenizer.cpp @@ -45,7 +45,7 @@ bool WhisperTokenizer::loadVocabulary(const QString& vocabPath) { } LOG_INFO(kTag, QString("词表已加载: %1 个词条 (文件: %2)").arg(lineCount).arg(vocabPath)); - return !tokenToString_.empty(); + return !tokenToString_.isEmpty(); } QString WhisperTokenizer::decode(const std::vector& tokens) const { @@ -55,7 +55,7 @@ QString WhisperTokenizer::decode(const std::vector& tokens) const { auto it = tokenToString_.find(token); if (it != tokenToString_.end()) { - QString decoded = decodeBytePair(it->second); + QString decoded = decodeBytePair(it.value()); result += decoded; } else { result += QString("<|token:%1|>").arg(token); @@ -71,7 +71,7 @@ std::vector WhisperTokenizer::encode(const QString& text) const { QString ch = text.mid(i, 1); auto it = stringToToken_.find(ch); if (it != stringToToken_.end()) { - tokens.push_back(it->second); + tokens.push_back(it.value()); } } return tokens; @@ -86,13 +86,13 @@ QString WhisperTokenizer::decodeBytePair(const QString& text) const { } int WhisperTokenizer::languageTokenId(const QString& langCode) { - static const std::unordered_map langMap = { + static const QHash langMap = { {"zh", 50260}, {"en", 50259}, {"ja", 50261}, {"ko", 50262}, {"fr", 50265}, {"de", 50266}, {"es", 50267}, {"ru", 50268}, {"pt", 50269}, {"it", 50270}, {"auto", 50359} }; auto it = langMap.find(langCode); - return it != langMap.end() ? it->second : 50259; // 默认英语 + return it != langMap.end() ? it.value() : 50259; // 默认英语 } bool WhisperTokenizer::isSpecialToken(int token) { diff --git a/src/core/whisper_tokenizer.h b/src/core/whisper_tokenizer.h index 8b05838..6132fab 100644 --- a/src/core/whisper_tokenizer.h +++ b/src/core/whisper_tokenizer.h @@ -1,9 +1,8 @@ #pragma once #include -#include +#include #include -#include #include namespace impress { @@ -28,10 +27,10 @@ public: std::vector encode(const QString& text) const; /** @brief 是否已加载词表 */ - bool isLoaded() const { return !tokenToString_.empty(); } + bool isLoaded() const { return !tokenToString_.isEmpty(); } /** @brief 词表大小 */ - int vocabSize() const { return static_cast(tokenToString_.size()); } + int vocabSize() const { return tokenToString_.size(); } // Whisper 特殊 token static constexpr int kTokenEndOfText = 50257; @@ -49,8 +48,8 @@ public: static bool isSpecialToken(int token); private: - std::unordered_map tokenToString_; - std::unordered_map stringToToken_; + QHash tokenToString_; + QHash stringToToken_; QString decodeBytePair(const QString& text) const; };