hzeng412 Claude Fable 5 commited on
Commit
3c70498
·
1 Parent(s): a3bf559

Make Qwen3-ASR the default on main; bump to 1.2.0

Browse files

- pyproject/uv.lock: add qwen-asr, transformers 4.57.6, fastapi 0.136.3
(torch stays 2.3.1) so a fresh clone + uv sync just works
- TTS weights: auto-convert .bin -> safetensors on first launch
(required by transformers >= 4.56 on torch < 2.6)
- ASR manager falls back to funasr/whisper if qwen-asr is unavailable
- README: Qwen3-ASR description, first-launch download note, v1.2.0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

README.md CHANGED
@@ -26,7 +26,7 @@ library_name: transformers
26
  ![Python](https://img.shields.io/badge/Python-3.9+-blue.svg)
27
  ![License](https://img.shields.io/badge/License-MIT-green.svg)
28
  ![Platform](https://img.shields.io/badge/Platform-macOS-lightgrey.svg)
29
- ![Version](https://img.shields.io/badge/Version-1.1.0-orange.svg)
30
 
31
  一个集成了语音识别(ASR)、大语言模型(LLM)和文本转语音(TTS)的实时语音对话系统
32
 
@@ -39,7 +39,7 @@ library_name: transformers
39
  VoiceDialogue 是一个基于 Python 的完整语音对话系统,实现了端到端的语音交互体验。系统采用模块化设计,具备实时、高精度、多角色的特点。
40
 
41
  - 🖥️ **图形界面**: 内置 Web 图形界面,浏览器即可使用(选音色、切语言、看实时字幕)
42
- - 🎤 **实时语音识别**: 高精度中英文语音转录
43
  - 🤖 **智能对话生成**: 集成 Qwen3 等大语言模型
44
  - 🔊 **高质量语音合成**: 支持多角色、多风格的语音输出
45
  - 🌐 **Web API 服务**: 提供 HTTP 接口,方便集成
@@ -89,7 +89,7 @@ python main.py --mode api
89
  - 点击右下角 **⚙️ 设置**,选择**麦克风、回音消除、识别语言、音色**,也可切换**中 / 英界面语言**;
90
  - 点击 **「开始对话」**,即可与 AI 实时语音对话,**字幕会实时显示**。
91
 
92
- > 首次启动需要数十秒加载模型(LLM / ASR / TTS),请稍候。
93
 
94
  ### 3. 命令行模式(CLI)
95
 
 
26
  ![Python](https://img.shields.io/badge/Python-3.9+-blue.svg)
27
  ![License](https://img.shields.io/badge/License-MIT-green.svg)
28
  ![Platform](https://img.shields.io/badge/Platform-macOS-lightgrey.svg)
29
+ ![Version](https://img.shields.io/badge/Version-1.2.0-orange.svg)
30
 
31
  一个集成了语音识别(ASR)、大语言模型(LLM)和文本转语音(TTS)的实时语音对话系统
32
 
 
39
  VoiceDialogue 是一个基于 Python 的完整语音对话系统,实现了端到端的语音交互体验。系统采用模块化设计,具备实时、高精度、多角色的特点。
40
 
41
  - 🖥️ **图形界面**: 内置 Web 图形界面,浏览器即可使用(选音色、切语言、看实时字幕)
42
+ - 🎤 **实时语音识别**: 基于 Qwen3-ASR 的高精度中英文转录(自带标点,支持 52 种语言)
43
  - 🤖 **智能对话生成**: 集成 Qwen3 等大语言模型
44
  - 🔊 **高质量语音合成**: 支持多角色、多风格的语音输出
45
  - 🌐 **Web API 服务**: 提供 HTTP 接口,方便集成
 
89
  - 点击右下角 **⚙️ 设置**,选择**麦克风、回音消除、识别语言、音色**,也可切换**中 / 英界面语言**;
90
  - 点击 **「开始对话」**,即可与 AI 实时语音对话,**字幕会实时显示**。
91
 
92
+ > 首次启动会自动下 Qwen3-ASR 模型( 3.4GB)并转换 TTS 权重格式(约 1 分钟),之后每次启动只需数十秒,请稍候。
93
 
94
  ### 3. 命令行模式(CLI)
95
 
assets/www/assets/{index-CBWIB-ok.css → index-BPAUWo8W.css} RENAMED
@@ -1 +1 @@
1
- @charset "UTF-8";html,body{width:100%;height:100%}input::-ms-clear,input::-ms-reveal{display:none}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{margin:0}[tabindex="-1"]:focus{outline:none}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5em;font-weight:500}p{margin-top:0;margin-bottom:1em}abbr[title],abbr[data-original-title]{-webkit-text-decoration:underline dotted;text-decoration:underline;text-decoration:underline dotted;border-bottom:0;cursor:help}address{margin-bottom:1em;font-style:normal;line-height:inherit}input[type=text],input[type=password],input[type=number],textarea{-webkit-appearance:none}ol,ul,dl{margin-top:0;margin-bottom:1em}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:500}dd{margin-bottom:.5em;margin-left:0}blockquote{margin:0 0 1em}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}pre,code,kbd,samp{font-size:1em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}pre{margin-top:0;margin-bottom:1em;overflow:auto}figure{margin:0 0 1em}img{vertical-align:middle;border-style:none}a,area,button,[role=button],input:not([type=range]),label,select,summary,textarea{touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75em;padding-bottom:.3em;text-align:left;caption-side:bottom}input,button,select,optgroup,textarea{margin:0;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;margin:0;padding:0;border:0}legend{display:block;width:100%;max-width:100%;margin-bottom:.5em;padding:0;color:inherit;font-size:1.5em;line-height:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}mark{padding:.2em;background-color:#feffe6}:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;height:100%;min-height:auto;color:#333;background:#fff}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}.card{border-bottom:solid 2px lightgray;align-items:center;justify-content:center;margin-top:40px;display:flex;max-width:1024px;width:100%}.seg-title{margin:24px 0;font-size:20px;font-weight:500}.seg-co{width:1022px;text-align:left;border-left:solid 6px midnightblue;padding-left:8px;margin-left:2px;margin-top:36px;line-height:24px}#app{margin:0 auto;padding:0;text-align:center;width:100%;height:100%}.ant-btn{padding:4px 12px}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.ant-card{background:#f5f6fa;height:100%}.ant-card-body{padding:24px 36px 12px!important;border-radius:0 0 8px 8px}.ant-card .ant-card-actions{background-color:#e8e8f8cc!important}.ant-popover{max-width:800px!important}.ant-form-item{background:transparent;margin-bottom:40px!important}.ant-form-item .ant-form-item-explain-error{color:#ff4d4f;text-align:left!important}.ant-form-item-label label{font-size:18px!important;color:#1a1a1a!important;font-weight:500!important}.ant-tooltip{max-width:1022px!important}.ant-page-header-heading{width:1022px!important}.highlight{background:#f8f8ff}.ant-layout-sider-collapsed{width:0!important;min-width:0!important;overflow:hidden}.ant-layout-sider-collapsed .ant-menu-item,.ant-layout-sider-collapsed .ant-menu-submenu-title{display:none}.ant-modal .ant-modal-content{background:#ffffff9e!important;backdrop-filter:blur(28px) saturate(140%);-webkit-backdrop-filter:blur(28px) saturate(140%);border:1px solid rgba(255,255,255,.6);border-radius:22px!important;box-shadow:0 16px 48px #1f26872e}.ant-modal .ant-modal-header{background:transparent!important}.ant-modal-mask{background:#14161e1f!important;backdrop-filter:blur(14px) saturate(120%);-webkit-backdrop-filter:blur(14px) saturate(120%)}.ant-select .ant-select-selector,.ant-input,textarea.ant-input,.ant-input-affix-wrapper{background:#ffffff73!important;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.7)!important}.ant-btn:not(.ant-btn-text):not(.ant-btn-link){box-shadow:0 2px 10px #1f26871a}.ant-btn-default{background:#ffffff80!important;border:1px solid rgba(255,255,255,.75)!important;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.ant-btn-text{box-shadow:none!important;background:transparent!important}.ant-radio-group-solid .ant-radio-button-wrapper:first-child{border-top-left-radius:12px;border-bottom-left-radius:12px}.ant-radio-group-solid .ant-radio-button-wrapper:last-child{border-top-right-radius:12px;border-bottom-right-radius:12px}.header-nav[data-v-07594418]{display:flex;align-items:flex-start;justify-content:space-between;width:100vw;height:40px;align-items:center;position:absolute;top:0;left:0;z-index:99;-webkit-app-region:drag;cursor:move}.header-nav .window-controls[data-v-07594418],.header-nav button[data-v-07594418],.header-nav .ant-input-search[data-v-07594418],.header-nav img[data-v-07594418],.header-nav .anticon[data-v-07594418]{-webkit-app-region:no-drag;cursor:pointer}.header-nav .window-controls[data-v-07594418]{top:0;right:0;display:flex;z-index:1000;margin-left:12px}.header-nav .window-controls .window-control-btn[data-v-07594418]{width:46px;height:32px;border:none;background:transparent;color:#666;font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background-color .2s}.header-nav .window-controls .window-control-btn[data-v-07594418]:hover{background-color:#0000001a}.header-nav .window-controls .window-control-btn.close[data-v-07594418]:hover{background-color:#e81123;color:#fff}.header-nav .window-controls .close-icon.focus[data-v-07594418]{display:none}.header-nav .window-controls:hover .close-icon.default[data-v-07594418],.header-nav .window-controls:focus-within .close-icon.default[data-v-07594418]{display:none}.header-nav .window-controls:hover .close-icon.focus[data-v-07594418],.header-nav .window-controls:focus-within .close-icon.focus[data-v-07594418]{display:inline}.content[data-v-b8a456cb]{background-color:#fff;margin:0 auto;display:flex;flex-direction:column;align-items:center;justify-content:space-between}.not-found-wrapper[data-v-aef52a59]{height:calc(100vh - 104px)}.tab-body[data-v-9cd2a8bd]{height:360px;overflow-y:auto;padding:4px 8px 4px 2px}.setting-row[data-v-9cd2a8bd]{margin-bottom:20px}.setting-row>label[data-v-9cd2a8bd]{display:block;font-size:15px;font-weight:500;margin-bottom:8px}.setting-row>label .label-icon[data-v-9cd2a8bd]{margin-right:6px;color:#1890ff}.setting-row .hint[data-v-9cd2a8bd]{font-size:12px;color:#999;margin:8px 0 0}.setting-row .row-inline[data-v-9cd2a8bd]{display:flex;align-items:center;justify-content:space-between}.voice-group[data-v-9cd2a8bd]{display:flex;flex-direction:column;margin-top:8px}.about .about-head[data-v-9cd2a8bd]{text-align:center;margin-bottom:24px}.about .about-head .about-name[data-v-9cd2a8bd]{font-size:20px;font-weight:600}.about .about-head .about-ver[data-v-9cd2a8bd]{font-size:13px;color:#888;margin-top:2px}.about .about-head .about-tagline[data-v-9cd2a8bd]{font-size:12px;color:#999;margin-top:4px}.about .about-section[data-v-9cd2a8bd]{margin-bottom:20px}.about .about-section .about-section-title[data-v-9cd2a8bd]{font-size:13px;font-weight:600;color:#666;margin-bottom:10px}.about .about-item[data-v-9cd2a8bd]{margin-bottom:12px}.about .about-item .about-item-label[data-v-9cd2a8bd]{font-size:14px;font-weight:500}.about .about-item .about-item-desc[data-v-9cd2a8bd]{font-size:12px;color:#777;margin-top:2px;line-height:1.6}.about .about-item .about-item-desc a[data-v-9cd2a8bd]{margin-left:6px}.about a[data-v-9cd2a8bd]{color:#1677ff;text-decoration:none}.about a[data-v-9cd2a8bd]:hover{text-decoration:underline}.about .about-link[data-v-9cd2a8bd]{font-size:13px;word-break:break-all}.about .about-copyright[data-v-9cd2a8bd]{margin-top:16px;font-size:11px;color:#aaa;text-align:center}.voice-radio[data-v-9cd2a8bd]{display:flex;align-items:center;height:40px;line-height:40px}.voice-radio .voice-name[data-v-9cd2a8bd]{margin-right:8px}.audio-play-btn[data-v-9cd2a8bd]{padding:0 6px;border-radius:4px}.audio-play-btn.playing[data-v-9cd2a8bd]{background-color:#f6ffed}.asr-chip[data-v-ca2e1f17]{display:flex;align-items:center;gap:8px;height:38px;padding:0 18px;margin-right:16px;border-radius:19px;color:#000000a6;font-size:13px;background:#ffffff80;border:1px solid rgba(255,255,255,.7);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 4px 16px #1f26871f}.settings-btn[data-v-ca2e1f17]{width:60px;height:60px;margin-right:24px;border-radius:50%!important;background:#ffffff80!important;border:1px solid rgba(255,255,255,.7)!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 4px 16px #1f26871f;display:flex;align-items:center;justify-content:center}.welcome-wrapper[data-v-ca2e1f17]{width:100%;height:100%;background-image:url(./bg-BmnA8p_e.png);background-repeat:no-repeat;background-attachment:fixed;background-size:cover;background-position:center;display:flex;flex-direction:column;align-items:center;justify-content:space-between;color:#fff}.welcome-wrapper .content[data-v-ca2e1f17]{width:100%;height:80vh;display:flex;flex-direction:column;justify-content:space-around;margin-top:64px}.welcome-wrapper .content .inner-content[data-v-ca2e1f17]{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:20px}.welcome-wrapper .content .inner-content .text-box[data-v-ca2e1f17]{color:#000;margin-bottom:36px}.welcome-wrapper .content .inner-content .text-box .title[data-v-ca2e1f17]{font-size:24px;font-weight:600;margin-bottom:24px}.welcome-wrapper .content .inner-content .text-box .sub-title[data-v-ca2e1f17]{font-size:15px;margin-top:10px}.welcome-wrapper .content .inner-content .btn-box[data-v-ca2e1f17]{width:224px;height:80px}.welcome-wrapper .actions[data-v-ca2e1f17]{width:100%;height:100px;margin-bottom:32px;display:flex;align-items:center;justify-content:flex-end}.ball-wrapper[data-v-34c8e583]{width:100%;height:calc(100vh - 100px);display:flex;flex-direction:column;align-items:center;justify-content:space-around}.talk-wrapper[data-v-05da84ae]{width:auto;width:100%;max-width:1000px;margin:0 auto;box-sizing:border-box;height:calc(100vh - 150px);overflow-y:auto;padding:20px 32px 0;display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start}.talk-wrapper .cont-left[data-v-05da84ae]{width:100%;margin:24px 0;display:flex;justify-content:flex-start;align-items:flex-start}.talk-wrapper .cont-left .text-left[data-v-05da84ae]{max-width:88%;color:#222;font-size:16px;font-weight:400;text-align:left;line-height:1.8;margin-left:12px;margin-top:6px;word-break:break-word}.talk-wrapper .cont-right[data-v-05da84ae]{width:100%;margin:24px 0;display:flex;justify-content:flex-end;align-items:flex-start}.talk-wrapper .cont-right .text-right[data-v-05da84ae]{max-width:80%;color:#444;font-size:16px;font-weight:400;text-align:start;line-height:1.8;margin-right:12px;background:#ccc;border-radius:8px 0 8px 8px;padding:8px 12px;word-break:break-word}.chat-wrapper[data-v-8b035bf4]{width:100%;height:100%;background-image:url(./bg-BmnA8p_e.png);background-repeat:no-repeat;background-attachment:fixed;background-size:cover;background-position:center;display:flex;flex-direction:column;align-items:center;justify-content:space-between;color:#fff}.chat-wrapper .content[data-v-8b035bf4]{width:100%;height:auto;display:flex;flex-direction:column;justify-content:space-around}.chat-wrapper .content .inner-content[data-v-8b035bf4]{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:20px}.chat-wrapper .content .inner-content .text-box[data-v-8b035bf4]{color:#000;margin-bottom:36px}.chat-wrapper .content .inner-content .text-box .title[data-v-8b035bf4]{font-size:24px;font-weight:600;margin-bottom:24px}.chat-wrapper .content .inner-content .text-box .sub-title[data-v-8b035bf4]{font-size:15px;margin-top:10px}.chat-wrapper .content .inner-content .btn-box[data-v-8b035bf4]{width:224px;height:80px}.chat-wrapper .actions[data-v-8b035bf4]{width:100%;height:100px;margin-bottom:32px;display:flex;justify-content:space-between;align-items:center}.chat-wrapper .actions .holder[data-v-8b035bf4]{width:64px;height:48px}.chat-wrapper .actions .btns[data-v-8b035bf4]{width:450px;height:96px;display:flex;justify-content:space-around;align-items:center}.chat-wrapper .actions .btns[data-v-8b035bf4] .ant-btn{border-radius:50%!important;background:#ffffff80!important;border:1px solid rgba(255,255,255,.7)!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 4px 16px #1f26871f}.chat-wrapper .actions .download-wrapper[data-v-8b035bf4]{width:64px;height:64px;display:flex;justify-content:flex-start;align-items:center;margin-right:0}.chat-wrapper .actions .download-wrapper img[data-v-8b035bf4]{width:24px;height:24px}.content-wrapper[data-v-d41c9ce7]{text-align:left;max-width:800px;min-width:320px;margin-bottom:64px;min-height:calc(100vh - 438px)}.content-wrapper .content-box[data-v-d41c9ce7]{padding:24px;height:240px;background-color:#e8e8e8;border-radius:16px;width:50%;margin:48px auto;min-width:300px}.content-wrapper .video-box[data-v-d41c9ce7]{max-width:800px;min-width:320px;width:90vw;height:auto}
 
1
+ @charset "UTF-8";html,body{width:100%;height:100%}input::-ms-clear,input::-ms-reveal{display:none}*,*:before,*:after{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{margin:0}[tabindex="-1"]:focus{outline:none}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5em;font-weight:500}p{margin-top:0;margin-bottom:1em}abbr[title],abbr[data-original-title]{-webkit-text-decoration:underline dotted;text-decoration:underline;text-decoration:underline dotted;border-bottom:0;cursor:help}address{margin-bottom:1em;font-style:normal;line-height:inherit}input[type=text],input[type=password],input[type=number],textarea{-webkit-appearance:none}ol,ul,dl{margin-top:0;margin-bottom:1em}ol ol,ul ul,ol ul,ul ol{margin-bottom:0}dt{font-weight:500}dd{margin-bottom:.5em;margin-left:0}blockquote{margin:0 0 1em}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}pre,code,kbd,samp{font-size:1em;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace}pre{margin-top:0;margin-bottom:1em;overflow:auto}figure{margin:0 0 1em}img{vertical-align:middle;border-style:none}a,area,button,[role=button],input:not([type=range]),label,select,summary,textarea{touch-action:manipulation}table{border-collapse:collapse}caption{padding-top:.75em;padding-bottom:.3em;text-align:left;caption-side:bottom}input,button,select,optgroup,textarea{margin:0;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{padding:0;border-style:none}input[type=radio],input[type=checkbox]{box-sizing:border-box;padding:0}input[type=date],input[type=time],input[type=datetime-local],input[type=month]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;margin:0;padding:0;border:0}legend{display:block;width:100%;max-width:100%;margin-bottom:.5em;padding:0;color:inherit;font-size:1.5em;line-height:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item}template{display:none}[hidden]{display:none!important}mark{padding:.2em;background-color:#feffe6}:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;height:100%;min-height:auto;color:#333;background:#fff}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}.card{border-bottom:solid 2px lightgray;align-items:center;justify-content:center;margin-top:40px;display:flex;max-width:1024px;width:100%}.seg-title{margin:24px 0;font-size:20px;font-weight:500}.seg-co{width:1022px;text-align:left;border-left:solid 6px midnightblue;padding-left:8px;margin-left:2px;margin-top:36px;line-height:24px}#app{margin:0 auto;padding:0;text-align:center;width:100%;height:100%}.ant-btn{padding:4px 12px}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.ant-card{background:#f5f6fa;height:100%}.ant-card-body{padding:24px 36px 12px!important;border-radius:0 0 8px 8px}.ant-card .ant-card-actions{background-color:#e8e8f8cc!important}.ant-popover{max-width:800px!important}.ant-form-item{background:transparent;margin-bottom:40px!important}.ant-form-item .ant-form-item-explain-error{color:#ff4d4f;text-align:left!important}.ant-form-item-label label{font-size:18px!important;color:#1a1a1a!important;font-weight:500!important}.ant-tooltip{max-width:1022px!important}.ant-page-header-heading{width:1022px!important}.highlight{background:#f8f8ff}.ant-layout-sider-collapsed{width:0!important;min-width:0!important;overflow:hidden}.ant-layout-sider-collapsed .ant-menu-item,.ant-layout-sider-collapsed .ant-menu-submenu-title{display:none}.ant-modal .ant-modal-content{background:#ffffff9e!important;backdrop-filter:blur(28px) saturate(140%);-webkit-backdrop-filter:blur(28px) saturate(140%);border:1px solid rgba(255,255,255,.6);border-radius:22px!important;box-shadow:0 16px 48px #1f26872e}.ant-modal .ant-modal-header{background:transparent!important}.ant-modal-mask{background:#14161e1f!important;backdrop-filter:blur(14px) saturate(120%);-webkit-backdrop-filter:blur(14px) saturate(120%)}.ant-select .ant-select-selector,.ant-input,textarea.ant-input,.ant-input-affix-wrapper{background:#ffffff73!important;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border:1px solid rgba(255,255,255,.7)!important}.ant-btn:not(.ant-btn-text):not(.ant-btn-link){box-shadow:0 2px 10px #1f26871a}.ant-btn-default{background:#ffffff80!important;border:1px solid rgba(255,255,255,.75)!important;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.ant-btn-text{box-shadow:none!important;background:transparent!important}.ant-radio-group-solid .ant-radio-button-wrapper:first-child{border-top-left-radius:12px;border-bottom-left-radius:12px}.ant-radio-group-solid .ant-radio-button-wrapper:last-child{border-top-right-radius:12px;border-bottom-right-radius:12px}.header-nav[data-v-07594418]{display:flex;align-items:flex-start;justify-content:space-between;width:100vw;height:40px;align-items:center;position:absolute;top:0;left:0;z-index:99;-webkit-app-region:drag;cursor:move}.header-nav .window-controls[data-v-07594418],.header-nav button[data-v-07594418],.header-nav .ant-input-search[data-v-07594418],.header-nav img[data-v-07594418],.header-nav .anticon[data-v-07594418]{-webkit-app-region:no-drag;cursor:pointer}.header-nav .window-controls[data-v-07594418]{top:0;right:0;display:flex;z-index:1000;margin-left:12px}.header-nav .window-controls .window-control-btn[data-v-07594418]{width:46px;height:32px;border:none;background:transparent;color:#666;font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background-color .2s}.header-nav .window-controls .window-control-btn[data-v-07594418]:hover{background-color:#0000001a}.header-nav .window-controls .window-control-btn.close[data-v-07594418]:hover{background-color:#e81123;color:#fff}.header-nav .window-controls .close-icon.focus[data-v-07594418]{display:none}.header-nav .window-controls:hover .close-icon.default[data-v-07594418],.header-nav .window-controls:focus-within .close-icon.default[data-v-07594418]{display:none}.header-nav .window-controls:hover .close-icon.focus[data-v-07594418],.header-nav .window-controls:focus-within .close-icon.focus[data-v-07594418]{display:inline}.content[data-v-b8a456cb]{background-color:#fff;margin:0 auto;display:flex;flex-direction:column;align-items:center;justify-content:space-between}.not-found-wrapper[data-v-aef52a59]{height:calc(100vh - 104px)}.tab-body[data-v-a48e843b]{height:360px;overflow-y:auto;padding:4px 8px 4px 2px}.setting-row[data-v-a48e843b]{margin-bottom:20px}.setting-row>label[data-v-a48e843b]{display:block;font-size:15px;font-weight:500;margin-bottom:8px}.setting-row>label .label-icon[data-v-a48e843b]{margin-right:6px;color:#1890ff}.setting-row .hint[data-v-a48e843b]{font-size:12px;color:#999;margin:8px 0 0}.setting-row .row-inline[data-v-a48e843b]{display:flex;align-items:center;justify-content:space-between}.voice-group[data-v-a48e843b]{display:flex;flex-direction:column;margin-top:8px}.about .about-head[data-v-a48e843b]{text-align:center;margin-bottom:24px}.about .about-head .about-name[data-v-a48e843b]{font-size:20px;font-weight:600}.about .about-head .about-ver[data-v-a48e843b]{font-size:13px;color:#888;margin-top:2px}.about .about-head .about-tagline[data-v-a48e843b]{font-size:12px;color:#999;margin-top:4px}.about .about-section[data-v-a48e843b]{margin-bottom:20px}.about .about-section .about-section-title[data-v-a48e843b]{font-size:13px;font-weight:600;color:#666;margin-bottom:10px}.about .about-item[data-v-a48e843b]{margin-bottom:12px}.about .about-item .about-item-label[data-v-a48e843b]{font-size:14px;font-weight:500}.about .about-item .about-item-desc[data-v-a48e843b]{font-size:12px;color:#777;margin-top:2px;line-height:1.6}.about .about-item .about-item-desc a[data-v-a48e843b]{margin-left:6px}.about a[data-v-a48e843b]{color:#1677ff;text-decoration:none}.about a[data-v-a48e843b]:hover{text-decoration:underline}.about .about-link[data-v-a48e843b]{font-size:13px;word-break:break-all}.about .about-copyright[data-v-a48e843b]{margin-top:16px;font-size:11px;color:#aaa;text-align:center}.voice-radio[data-v-a48e843b]{display:flex;align-items:center;height:40px;line-height:40px}.voice-radio .voice-name[data-v-a48e843b]{margin-right:8px}.audio-play-btn[data-v-a48e843b]{padding:0 6px;border-radius:4px}.audio-play-btn.playing[data-v-a48e843b]{background-color:#f6ffed}.asr-chip[data-v-ca2e1f17]{display:flex;align-items:center;gap:8px;height:38px;padding:0 18px;margin-right:16px;border-radius:19px;color:#000000a6;font-size:13px;background:#ffffff80;border:1px solid rgba(255,255,255,.7);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 4px 16px #1f26871f}.settings-btn[data-v-ca2e1f17]{width:60px;height:60px;margin-right:24px;border-radius:50%!important;background:#ffffff80!important;border:1px solid rgba(255,255,255,.7)!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 4px 16px #1f26871f;display:flex;align-items:center;justify-content:center}.welcome-wrapper[data-v-ca2e1f17]{width:100%;height:100%;background-image:url(./bg-BmnA8p_e.png);background-repeat:no-repeat;background-attachment:fixed;background-size:cover;background-position:center;display:flex;flex-direction:column;align-items:center;justify-content:space-between;color:#fff}.welcome-wrapper .content[data-v-ca2e1f17]{width:100%;height:80vh;display:flex;flex-direction:column;justify-content:space-around;margin-top:64px}.welcome-wrapper .content .inner-content[data-v-ca2e1f17]{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:20px}.welcome-wrapper .content .inner-content .text-box[data-v-ca2e1f17]{color:#000;margin-bottom:36px}.welcome-wrapper .content .inner-content .text-box .title[data-v-ca2e1f17]{font-size:24px;font-weight:600;margin-bottom:24px}.welcome-wrapper .content .inner-content .text-box .sub-title[data-v-ca2e1f17]{font-size:15px;margin-top:10px}.welcome-wrapper .content .inner-content .btn-box[data-v-ca2e1f17]{width:224px;height:80px}.welcome-wrapper .actions[data-v-ca2e1f17]{width:100%;height:100px;margin-bottom:32px;display:flex;align-items:center;justify-content:flex-end}.ball-wrapper[data-v-34c8e583]{width:100%;height:calc(100vh - 100px);display:flex;flex-direction:column;align-items:center;justify-content:space-around}.talk-wrapper[data-v-05da84ae]{width:auto;width:100%;max-width:1000px;margin:0 auto;box-sizing:border-box;height:calc(100vh - 150px);overflow-y:auto;padding:20px 32px 0;display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start}.talk-wrapper .cont-left[data-v-05da84ae]{width:100%;margin:24px 0;display:flex;justify-content:flex-start;align-items:flex-start}.talk-wrapper .cont-left .text-left[data-v-05da84ae]{max-width:88%;color:#222;font-size:16px;font-weight:400;text-align:left;line-height:1.8;margin-left:12px;margin-top:6px;word-break:break-word}.talk-wrapper .cont-right[data-v-05da84ae]{width:100%;margin:24px 0;display:flex;justify-content:flex-end;align-items:flex-start}.talk-wrapper .cont-right .text-right[data-v-05da84ae]{max-width:80%;color:#444;font-size:16px;font-weight:400;text-align:start;line-height:1.8;margin-right:12px;background:#ccc;border-radius:8px 0 8px 8px;padding:8px 12px;word-break:break-word}.chat-wrapper[data-v-8b035bf4]{width:100%;height:100%;background-image:url(./bg-BmnA8p_e.png);background-repeat:no-repeat;background-attachment:fixed;background-size:cover;background-position:center;display:flex;flex-direction:column;align-items:center;justify-content:space-between;color:#fff}.chat-wrapper .content[data-v-8b035bf4]{width:100%;height:auto;display:flex;flex-direction:column;justify-content:space-around}.chat-wrapper .content .inner-content[data-v-8b035bf4]{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:20px}.chat-wrapper .content .inner-content .text-box[data-v-8b035bf4]{color:#000;margin-bottom:36px}.chat-wrapper .content .inner-content .text-box .title[data-v-8b035bf4]{font-size:24px;font-weight:600;margin-bottom:24px}.chat-wrapper .content .inner-content .text-box .sub-title[data-v-8b035bf4]{font-size:15px;margin-top:10px}.chat-wrapper .content .inner-content .btn-box[data-v-8b035bf4]{width:224px;height:80px}.chat-wrapper .actions[data-v-8b035bf4]{width:100%;height:100px;margin-bottom:32px;display:flex;justify-content:space-between;align-items:center}.chat-wrapper .actions .holder[data-v-8b035bf4]{width:64px;height:48px}.chat-wrapper .actions .btns[data-v-8b035bf4]{width:450px;height:96px;display:flex;justify-content:space-around;align-items:center}.chat-wrapper .actions .btns[data-v-8b035bf4] .ant-btn{border-radius:50%!important;background:#ffffff80!important;border:1px solid rgba(255,255,255,.7)!important;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);box-shadow:0 4px 16px #1f26871f}.chat-wrapper .actions .download-wrapper[data-v-8b035bf4]{width:64px;height:64px;display:flex;justify-content:flex-start;align-items:center;margin-right:0}.chat-wrapper .actions .download-wrapper img[data-v-8b035bf4]{width:24px;height:24px}.content-wrapper[data-v-d41c9ce7]{text-align:left;max-width:800px;min-width:320px;margin-bottom:64px;min-height:calc(100vh - 438px)}.content-wrapper .content-box[data-v-d41c9ce7]{padding:24px;height:240px;background-color:#e8e8e8;border-radius:16px;width:50%;margin:48px auto;min-width:300px}.content-wrapper .video-box[data-v-d41c9ce7]{max-width:800px;min-width:320px;width:90vw;height:auto}
assets/www/assets/{index-I4LwLHV-.js → index-CGlMbARk.js} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:7f59527d7ccdc62e1062e71f82e79c06f9622c9deed46b36299e449e5a942700
3
  size 2307855
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2cccc544e9f2c32632c81cf9a5e8ed3cc9c5b0476ec8e595a180deb6fde095c8
3
  size 2307855
assets/www/index.html CHANGED
@@ -5,8 +5,8 @@
5
  <link rel="icon" type="image/svg+xml" href="./favicon.ico" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>VoiceDialogue</title>
8
- <script type="module" crossorigin src="./assets/index-I4LwLHV-.js"></script>
9
- <link rel="stylesheet" crossorigin href="./assets/index-CBWIB-ok.css">
10
  </head>
11
  <body>
12
  <div id="app"></div>
 
5
  <link rel="icon" type="image/svg+xml" href="./favicon.ico" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
  <title>VoiceDialogue</title>
8
+ <script type="module" crossorigin src="./assets/index-CGlMbARk.js"></script>
9
+ <link rel="stylesheet" crossorigin href="./assets/index-BPAUWo8W.css">
10
  </head>
11
  <body>
12
  <div id="app"></div>
frontend/src/views/Welcome/Components/SettingsModal.vue CHANGED
@@ -18,7 +18,7 @@ const settingsStore = useSettingsStore();
18
 
19
  const activeTab = ref<string>("main");
20
  const loading = ref<boolean>(false);
21
- const appVersion = "1.1.0";
22
 
23
  // ---- 各项设置的本地状态(打开时从 store / 后端同步)----
24
  const uiLanguage = ref<UiLocale>((settingsStore.$state.uiLanguage as UiLocale) ?? "en");
 
18
 
19
  const activeTab = ref<string>("main");
20
  const loading = ref<boolean>(false);
21
+ const appVersion = "1.2.0";
22
 
23
  // ---- 各项设置的本地状态(打开时从 store / 后端同步)----
24
  const uiLanguage = ref<UiLocale>((settingsStore.$state.uiLanguage as UiLocale) ?? "en");
pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
  [project]
2
  name = "voice_dialogue"
3
- version = "1.0.0"
4
  description = "一个基于AI的智能语音对话系统,支持实时语音识别、自然语言处理和语音合成"
5
  readme = "README.md"
6
  requires-python = ">=3.11"
@@ -8,11 +8,11 @@ dependencies = [
8
  "cn2an>=0.5.23",
9
  "einops>=0.8.1",
10
  "en-core-web-sm",
11
- "fastapi==0.115.12",
12
  "ffmpeg-python>=0.2.0",
13
  "funasr-onnx==0.4.1",
14
  "g2p-en>=2.1.0",
15
- "huggingface-hub==0.32.4",
16
  "jieba>=0.42.1",
17
  "jieba-fast>=0.53",
18
  "langchain==0.2.17",
@@ -29,10 +29,11 @@ dependencies = [
29
  "pypinyin>=0.54.0",
30
  "pytorch-lightning==2.3.1",
31
  "pywhispercpp",
 
32
  "silero-vad==5.1.2",
33
  "soundfile==0.13.1",
34
  "torch==2.3.1",
35
- "transformers==4.41.2",
36
  "uvicorn==0.34.3",
37
  "websockets>=15.0.1",
38
  "wordsegment>=1.3.1",
 
1
  [project]
2
  name = "voice_dialogue"
3
+ version = "1.2.0"
4
  description = "一个基于AI的智能语音对话系统,支持实时语音识别、自然语言处理和语音合成"
5
  readme = "README.md"
6
  requires-python = ">=3.11"
 
8
  "cn2an>=0.5.23",
9
  "einops>=0.8.1",
10
  "en-core-web-sm",
11
+ "fastapi==0.136.3",
12
  "ffmpeg-python>=0.2.0",
13
  "funasr-onnx==0.4.1",
14
  "g2p-en>=2.1.0",
15
+ "huggingface-hub==0.36.2",
16
  "jieba>=0.42.1",
17
  "jieba-fast>=0.53",
18
  "langchain==0.2.17",
 
29
  "pypinyin>=0.54.0",
30
  "pytorch-lightning==2.3.1",
31
  "pywhispercpp",
32
+ "qwen-asr>=0.0.6",
33
  "silero-vad==5.1.2",
34
  "soundfile==0.13.1",
35
  "torch==2.3.1",
36
+ "transformers==4.57.6",
37
  "uvicorn==0.34.3",
38
  "websockets>=15.0.1",
39
  "wordsegment>=1.3.1",
src/voice_dialogue/asr/manager.py CHANGED
@@ -93,7 +93,7 @@ class ASRManager:
93
 
94
  def __init__(self):
95
  self._asr_instances: Dict[str, ASRInterface] = {}
96
- # 本分支默认使用 Qwen3-ASR;设置 VOICE_DIALOGUE_ASR=legacy 可切回原引擎做 A/B 对比
97
  if os.environ.get('VOICE_DIALOGUE_ASR', 'qwen') == 'legacy':
98
  self._language_to_asr_mapping = {
99
  'zh': 'funasr', # 中文优先使用FunASR
@@ -105,6 +105,15 @@ class ASRManager:
105
  'en': 'qwen',
106
  }
107
 
 
 
 
 
 
 
 
 
 
108
  def create_asr(self, language: Literal['auto', 'zh', 'en']) -> ASRInterface:
109
  """
110
  根据语言配置创建ASR实例
@@ -122,6 +131,9 @@ class ASRManager:
122
  # 根据语言选择合适的ASR引擎
123
  asr_type = self._get_asr_type_for_language(language)
124
 
 
 
 
125
  if asr_type not in asr_tables.asr_classes:
126
  raise ValueError(f"ASR类型 '{asr_type}' 未注册")
127
 
 
93
 
94
  def __init__(self):
95
  self._asr_instances: Dict[str, ASRInterface] = {}
96
+ # 默认使用 Qwen3-ASR;设置 VOICE_DIALOGUE_ASR=legacy 可切回原引擎做 A/B 对比
97
  if os.environ.get('VOICE_DIALOGUE_ASR', 'qwen') == 'legacy':
98
  self._language_to_asr_mapping = {
99
  'zh': 'funasr', # 中文优先使用FunASR
 
105
  'en': 'qwen',
106
  }
107
 
108
+ def _resolve_unregistered(self, language: str, asr_type: str) -> str:
109
+ """所选引擎未注册时(如 qwen-asr 未安装)回退到传统引擎。"""
110
+ fallback = {'zh': 'funasr', 'en': 'whisper'}.get(language)
111
+ if fallback and fallback in asr_tables.asr_classes:
112
+ logger.warning(f"ASR引擎 '{asr_type}' 未注册,回退到 '{fallback}'")
113
+ self._language_to_asr_mapping[language] = fallback
114
+ return fallback
115
+ return asr_type
116
+
117
  def create_asr(self, language: Literal['auto', 'zh', 'en']) -> ASRInterface:
118
  """
119
  根据语言配置创建ASR实例
 
131
  # 根据语言选择合适的ASR引擎
132
  asr_type = self._get_asr_type_for_language(language)
133
 
134
+ if asr_type not in asr_tables.asr_classes:
135
+ asr_type = self._resolve_unregistered(language, asr_type)
136
+
137
  if asr_type not in asr_tables.asr_classes:
138
  raise ValueError(f"ASR类型 '{asr_type}' 未注册")
139
 
src/voice_dialogue/tts/runtime/moyoyo.py CHANGED
@@ -34,6 +34,9 @@ class MoYoYoTTS(TTSInterface):
34
 
35
  def setup(self, **kwargs) -> None:
36
  """设置TTS模块"""
 
 
 
37
  tts_config = TTS_Config(self.config.get_runtime_config())
38
  self.tts_module = TTSModule(tts_config)
39
  self.tts_module.setup_inference_params(
 
34
 
35
  def setup(self, **kwargs) -> None:
36
  """设置TTS模块"""
37
+ from voice_dialogue.tts.weights_migration import ensure_safetensors_weights
38
+ ensure_safetensors_weights()
39
+
40
  tts_config = TTS_Config(self.config.get_runtime_config())
41
  self.tts_module = TTSModule(tts_config)
42
  self.tts_module.setup_inference_params(
src/voice_dialogue/tts/weights_migration.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """TTS 预训练权重 safetensors 迁移。
2
+
3
+ transformers >= 4.56 的安全策略 (CVE-2025-32434) 拒绝在 torch < 2.6 上加载
4
+ pytorch_model.bin。transformers 加载时优先使用 model.safetensors,因此首次
5
+ 启动时把 .bin 转换一次即可,无需升级 torch。
6
+ """
7
+ from pathlib import Path
8
+
9
+ from voice_dialogue.config import paths
10
+ from voice_dialogue.utils.logger import logger
11
+
12
+ PRETRAINED_DIRS = [
13
+ "chinese-roberta-wwm-ext-large",
14
+ "chinese-hubert-base",
15
+ ]
16
+
17
+
18
+ def ensure_safetensors_weights() -> None:
19
+ """确保 MoYoYo TTS 的预训练权重存在 safetensors 版本,缺失时从 .bin 转换。"""
20
+ moyoyo_path = Path(paths.TTS_MODELS_PATH) / "moyoyo"
21
+
22
+ for dirname in PRETRAINED_DIRS:
23
+ model_dir = moyoyo_path / dirname
24
+ bin_path = model_dir / "pytorch_model.bin"
25
+ st_path = model_dir / "model.safetensors"
26
+
27
+ if st_path.exists() or not bin_path.exists():
28
+ continue
29
+
30
+ logger.info(f"[INFO] 首次启动:转换 {dirname} 权重为 safetensors...")
31
+ try:
32
+ import torch
33
+ from safetensors.torch import save_file
34
+
35
+ state_dict = torch.load(bin_path, map_location="cpu", weights_only=True)
36
+ # clone 断开共享内存,safetensors 不允许张量间共享存储
37
+ state_dict = {
38
+ key: value.clone().contiguous()
39
+ for key, value in state_dict.items()
40
+ if hasattr(value, "clone")
41
+ }
42
+ save_file(state_dict, st_path, metadata={"format": "pt"})
43
+ logger.info(f"[INFO] {dirname} 转换完成: {st_path.stat().st_size // 1024 ** 2} MB")
44
+ except Exception as e:
45
+ logger.error(f"[ERROR] 转换 {dirname} 权重失败: {e}")
uv.lock CHANGED
The diff for this file is too large to render. See raw diff