@lobehub/chat 0.109.0 → 0.110.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +23 -3
- package/README.zh-CN.md +23 -3
- package/package.json +6 -6
- package/src/app/chat/features/Conversation/ChatList/Extras/TTS/FilePlayer.tsx +25 -0
- package/src/app/chat/features/Conversation/ChatList/Extras/TTS/InitPlayer.tsx +93 -0
- package/src/app/chat/features/Conversation/ChatList/Extras/TTS/Player.tsx +61 -0
- package/src/app/chat/features/Conversation/ChatList/Extras/TTS/index.tsx +31 -0
- package/src/features/AgentSetting/AgentPlugin/index.tsx +2 -2
- package/src/hooks/useTTS.ts +11 -15
- package/src/store/chat/actions/enhance.test.ts +139 -0
- package/src/store/chat/actions/enhance.ts +6 -3
- package/src/store/file/selectors.ts +4 -31
- package/src/store/file/slices/images/index.ts +1 -1
- package/src/store/file/slices/images/selectors.ts +34 -0
- package/src/store/file/slices/tts/action.test.ts +147 -0
- package/src/store/file/slices/tts/action.ts +60 -0
- package/src/store/file/slices/tts/index.ts +2 -0
- package/src/store/file/slices/tts/selectors.ts +3 -0
- package/src/store/file/store.ts +3 -1
- package/src/store/session/slices/agent/selectors.test.ts +228 -0
- package/src/store/session/slices/agent/selectors.ts +25 -0
- package/src/store/tool/helpers.ts +1 -1
- package/src/types/chatMessage.ts +3 -1
- package/vitest.config.ts +4 -0
- package/src/app/chat/features/Conversation/ChatList/Extras/TTS.tsx +0 -122
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 0.110.0](https://github.com/lobehub/lobe-chat/compare/v0.109.1...v0.110.0)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-12-07**</sup>
|
|
8
|
+
|
|
9
|
+
#### ✨ Features
|
|
10
|
+
|
|
11
|
+
- **misc**: Local TTS Player.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's improved
|
|
19
|
+
|
|
20
|
+
- **misc**: Local TTS Player, closes [#587](https://github.com/lobehub/lobe-chat/issues/587) ([87b51bd](https://github.com/lobehub/lobe-chat/commit/87b51bd))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 0.109.1](https://github.com/lobehub/lobe-chat/compare/v0.109.0...v0.109.1)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2023-12-07**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **misc**: Fix agent settings crash with old pluginManifest.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's fixed
|
|
44
|
+
|
|
45
|
+
- **misc**: Fix agent settings crash with old pluginManifest ([8b80dfd](https://github.com/lobehub/lobe-chat/commit/8b80dfd))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
## [Version 0.109.0](https://github.com/lobehub/lobe-chat/compare/v0.108.0...v0.109.0)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2023-12-06**</sup>
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Supports one-click free deployment of your private ChatGPT/LLM web application.
|
|
|
27
27
|
[![][github-stars-shield]][github-stars-link]
|
|
28
28
|
[![][github-issues-shield]][github-issues-link]
|
|
29
29
|
[![][github-license-shield]][github-license-link]<br>
|
|
30
|
-
[![]
|
|
30
|
+
[![][sponsor-shield]][sponsor-link]
|
|
31
31
|
|
|
32
32
|
**Share LobeChat Repository**
|
|
33
33
|
|
|
@@ -59,6 +59,7 @@ Supports one-click free deployment of your private ChatGPT/LLM web application.
|
|
|
59
59
|
- [🧩 Plugins](#-plugins)
|
|
60
60
|
- [⌨️ Local Development](#️-local-development)
|
|
61
61
|
- [🤝 Contributing](#-contributing)
|
|
62
|
+
- [🩷 Sponsor](#-sponsor)
|
|
62
63
|
- [🔗 More Products](#-more-products)
|
|
63
64
|
|
|
64
65
|
####
|
|
@@ -205,12 +206,12 @@ Our marketplace is not just a showcase platform but also a collaborative space.
|
|
|
205
206
|
|
|
206
207
|
| Recent Submits | Description |
|
|
207
208
|
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
209
|
+
| [Mr. Feynman](https://chat-preview.lobehub.com/market?agent=mrfeynman)<br/><sup>By **[jjy1000](https://github.com/jjy1000)** on **2023-12-04**</sup> | Explains complex knowledge concepts in a popular way to help you understand complex knowledge concepts. It can also explain knowledge types containing answers and questions.<br/>`general-teacher-assistant` |
|
|
208
210
|
| [Organic Chemistry Researcher](https://chat-preview.lobehub.com/market?agent=organic-chemistry-researcher)<br/><sup>By **[y22emc2](https://github.com/y22emc2)** on **2023-12-02**</sup> | Specializes in academic translation and writing in the field of organic chemistry<br/>`organic-chemistry` `research` `translation` `writing` `academic-articles` |
|
|
209
211
|
| [JS Code Quality Optimization](https://chat-preview.lobehub.com/market?agent=js-code-quality)<br/><sup>By **[canisminor1990](https://github.com/canisminor1990)** on **2023-11-22**</sup> | Dedicated to clean and elegant code refactoring<br/>`refactoring` `code-optimization` `code-quality` |
|
|
210
212
|
| [LobeChat Test Engineer](https://chat-preview.lobehub.com/market?agent=lobe-chat-unit-test-dev)<br/><sup>By **[arvinxx](https://github.com/arvinxx)** on **2023-11-22**</sup> | Proficient in writing frontend automation tests, especially comprehensive test coverage for TypeScript applications. Skilled in using the Vitest testing framework with a deep understanding of testing principles and strategies.<br/>`automation-testing` `testing` `lobe-chat` `frontend` |
|
|
211
|
-
| [Q\&A Document Conversion Expert](https://chat-preview.lobehub.com/market?agent=q-a-helper)<br/><sup>By **[barryWang12138](https://github.com/barryWang12138)** on **2023-11-22**</sup> | Please provide your document content, and I will segment and clean it according to your requirements, and provide answers in a standardized format.<br/>`q-a` `document` |
|
|
212
213
|
|
|
213
|
-
> 📊 Total agents: [<kbd>**
|
|
214
|
+
> 📊 Total agents: [<kbd>**54**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
|
|
214
215
|
|
|
215
216
|
<!-- AGENT LIST -->
|
|
216
217
|
|
|
@@ -512,6 +513,23 @@ Contributions of all types are more than welcome; if you are interested in contr
|
|
|
512
513
|
|
|
513
514
|
</div>
|
|
514
515
|
|
|
516
|
+
## 🩷 Sponsor
|
|
517
|
+
|
|
518
|
+
Every bit counts and your one-time donation sparkles in our galaxy of support! You're a shooting star, making a swift and bright impact on our journey. Thank you for believing in us – your generosity guides us toward our mission, one brilliant flash at a time.
|
|
519
|
+
|
|
520
|
+
<a href="https://opencollective.com/lobehub" target="_blank">
|
|
521
|
+
<picture>
|
|
522
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://readme-wizard.lobehub.com/api/sponsor?themeMode=dark">
|
|
523
|
+
<img src="https://readme-wizard.lobehub.com/api/sponsor">
|
|
524
|
+
</picture>
|
|
525
|
+
</a>
|
|
526
|
+
|
|
527
|
+
<div align="right">
|
|
528
|
+
|
|
529
|
+
[![][back-to-top]](#readme-top)
|
|
530
|
+
|
|
531
|
+
</div>
|
|
532
|
+
|
|
515
533
|
## 🔗 More Products
|
|
516
534
|
|
|
517
535
|
- **[🤯 Lobe Theme][lobe-theme]:** The modern theme for Stable Diffusion WebUI, exquisite interface design, highly customizable UI, and efficiency-boosting features.
|
|
@@ -613,6 +631,8 @@ This project is [MIT](./LICENSE) licensed.
|
|
|
613
631
|
[share-whatsapp-shield]: https://img.shields.io/badge/-share%20on%20whatsapp-black?labelColor=black&logo=whatsapp&logoColor=white&style=flat-square
|
|
614
632
|
[share-x-link]: https://x.com/intent/tweet?hashtags=chatbot%2CchatGPT%2CopenAI&text=Check%20this%20GitHub%20repository%20out%20%F0%9F%A4%AF%20LobeChat%20-%20An%20open-source%2C%20extensible%20%28Function%20Calling%29%2C%20high-performance%20chatbot%20framework.%20It%20supports%20one-click%20free%20deployment%20of%20your%20private%20ChatGPT%2FLLM%20web%20application.&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
|
|
615
633
|
[share-x-shield]: https://img.shields.io/badge/-share%20on%20x-black?labelColor=black&logo=x&logoColor=white&style=flat-square
|
|
634
|
+
[sponsor-link]: https://opencollective.com/lobehub 'Become 🩷 LobeHub Sponsor'
|
|
635
|
+
[sponsor-shield]: https://img.shields.io/badge/-Sponsor%20LobeHub-f04f88?logo=opencollective&logoColor=white&style=flat-square
|
|
616
636
|
[submit-agents-link]: https://github.com/lobehub/lobe-chat-agents
|
|
617
637
|
[submit-agents-shield]: https://img.shields.io/badge/🤖/🏪_submit_agent-%E2%86%92-c4f042?labelColor=black&style=for-the-badge
|
|
618
638
|
[submit-plugin-link]: https://github.com/lobehub/lobe-chat-plugins
|
package/README.zh-CN.md
CHANGED
|
@@ -26,7 +26,7 @@ LobeChat 是开源的高性能聊天机器人框架,支持语音合成、多
|
|
|
26
26
|
[![][github-stars-shield]][github-stars-link]
|
|
27
27
|
[![][github-issues-shield]][github-issues-link]
|
|
28
28
|
[![][github-license-shield]][github-license-link]<br>
|
|
29
|
-
[![]
|
|
29
|
+
[![][sponsor-shield]][sponsor-link]
|
|
30
30
|
|
|
31
31
|
**分享 LobeChat 给你的好友**
|
|
32
32
|
|
|
@@ -56,6 +56,7 @@ LobeChat 是开源的高性能聊天机器人框架,支持语音合成、多
|
|
|
56
56
|
- [🧩 插件体系](#-插件体系)
|
|
57
57
|
- [⌨️ 本地开发](#️-本地开发)
|
|
58
58
|
- [🤝 参与贡献](#-参与贡献)
|
|
59
|
+
- [🩷 感谢赞助](#-感谢赞助)
|
|
59
60
|
- [🔗 更多工具](#-更多工具)
|
|
60
61
|
|
|
61
62
|
####
|
|
@@ -182,12 +183,12 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
|
|
|
182
183
|
|
|
183
184
|
| 最近新增 | 助手说明 |
|
|
184
185
|
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
186
|
+
| [Mr. Feynman](https://chat-preview.lobehub.com/market?agent=mrfeynman)<br/><sup>By **[jjy1000](https://github.com/jjy1000)** on **2023-12-04**</sup> | 对你提出的复杂知识概念进行通俗性解释,帮助你理解复杂的知识概念。同时可以对包含答案和问题的知识类型进行解释。<br/>`通用教师助手` |
|
|
185
187
|
| [有机化学研究员](https://chat-preview.lobehub.com/market?agent=organic-chemistry-researcher)<br/><sup>By **[y22emc2](https://github.com/y22emc2)** on **2023-12-02**</sup> | 擅长有机化学领域的学术翻译和写作<br/>`有机化学` `科研` `翻译` `写作` `学术文章` |
|
|
186
188
|
| [JS 代码质量优化](https://chat-preview.lobehub.com/market?agent=js-code-quality)<br/><sup>By **[canisminor1990](https://github.com/canisminor1990)** on **2023-11-22**</sup> | 致力于干净和优雅的代码重构<br/>`重构` `代码优化` `代码质量` |
|
|
187
189
|
| [LobeChat 测试工程师](https://chat-preview.lobehub.com/market?agent=lobe-chat-unit-test-dev)<br/><sup>By **[arvinxx](https://github.com/arvinxx)** on **2023-11-22**</sup> | 擅长编写前端自动化测试,特别是 TypeScript 应用的全面测试覆盖。熟练使用 Vitest 测试框架,具备深入的测试原理和策略理解。<br/>`自动化测试` `测试` `lobe-chat` `前端` |
|
|
188
|
-
| [问答文档转换专家](https://chat-preview.lobehub.com/market?agent=q-a-helper)<br/><sup>By **[barryWang12138](https://github.com/barryWang12138)** on **2023-11-22**</sup> | 请提供您的文档内容,我将根据您的要求进行分段和清洗,并按照规范的格式回答。<br/>`q-a` `文档` |
|
|
189
190
|
|
|
190
|
-
> 📊 Total agents: [<kbd>**
|
|
191
|
+
> 📊 Total agents: [<kbd>**54**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
|
|
191
192
|
|
|
192
193
|
<!-- AGENT LIST -->
|
|
193
194
|
|
|
@@ -484,6 +485,23 @@ $ bun run dev
|
|
|
484
485
|
|
|
485
486
|
</div>
|
|
486
487
|
|
|
488
|
+
## 🩷 感谢赞助
|
|
489
|
+
|
|
490
|
+
每一分支持都珍贵无比,汇聚成我们支持的璀璨银河!你就像一颗划破夜空的流星,瞬间点亮我们前行的道路。感谢你对我们的信任 —— 你的支持笔就像星辰导航,一次又一次地为项目指明前进的光芒。
|
|
491
|
+
|
|
492
|
+
<a href="https://opencollective.com/lobehub" target="_blank">
|
|
493
|
+
<picture>
|
|
494
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://readme-wizard.lobehub.com/api/sponsor?themeMode=dark">
|
|
495
|
+
<img src="https://readme-wizard.lobehub.com/api/sponsor">
|
|
496
|
+
</picture>
|
|
497
|
+
</a>
|
|
498
|
+
|
|
499
|
+
<div align="right">
|
|
500
|
+
|
|
501
|
+
[![][back-to-top]](#readme-top)
|
|
502
|
+
|
|
503
|
+
</div>
|
|
504
|
+
|
|
487
505
|
## 🔗 更多工具
|
|
488
506
|
|
|
489
507
|
- [🤯 Lobe Theme][lobe-theme] : Stable Diffusion WebUI 的现代主题,精致的界面设计,高度可定制的 UI,以及提高效率的功能。
|
|
@@ -585,6 +603,8 @@ This project is [MIT](./LICENSE) licensed.
|
|
|
585
603
|
[share-whatsapp-shield]: https://img.shields.io/badge/-share%20on%20whatsapp-black?labelColor=black&logo=whatsapp&logoColor=white&style=flat-square
|
|
586
604
|
[share-x-link]: https://x.com/intent/tweet?hashtags=chatbot%2CchatGPT%2CopenAI&text=%E6%8E%A8%E8%8D%90%E4%B8%80%E4%B8%AA%20GitHub%20%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%20%F0%9F%A4%AF%20LobeChat%20-%20%E5%BC%80%E6%BA%90%E7%9A%84%E3%80%81%E5%8F%AF%E6%89%A9%E5%B1%95%E7%9A%84%EF%BC%88Function%20Calling%EF%BC%89%E9%AB%98%E6%80%A7%E8%83%BD%E8%81%8A%E5%A4%A9%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%A1%86%E6%9E%B6%E3%80%82%0A%E5%AE%83%E6%94%AF%E6%8C%81%E4%B8%80%E9%94%AE%E5%85%8D%E8%B4%B9%E9%83%A8%E7%BD%B2%E7%A7%81%E4%BA%BA%20ChatGPT%2FLLM%20%E7%BD%91%E9%A1%B5%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F&url=https%3A%2F%2Fgithub.com%2Flobehub%2Flobe-chat
|
|
587
605
|
[share-x-shield]: https://img.shields.io/badge/-share%20on%20x-black?labelColor=black&logo=x&logoColor=white&style=flat-square
|
|
606
|
+
[sponsor-link]: https://opencollective.com/lobehub 'Become 🩷 LobeHub Sponsor'
|
|
607
|
+
[sponsor-shield]: https://img.shields.io/badge/-Sponsor%20LobeHub-f04f88?logo=opencollective&logoColor=white&style=flat-square
|
|
588
608
|
[submit-agents-link]: https://github.com/lobehub/lobe-chat-agents
|
|
589
609
|
[submit-agents-shield]: https://img.shields.io/badge/🤖/🏪_submit_agent-%E2%86%92-c4f042?labelColor=black&style=for-the-badge
|
|
590
610
|
[submit-plugin-link]: https://github.com/lobehub/lobe-chat-plugins
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.110.0",
|
|
4
4
|
"description": "An open-source, extensible (Function Calling), high-performance chatbot framework. It supports one-click free deployment of your private ChatGPT/LLM web application",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatbot",
|
|
@@ -106,12 +106,12 @@
|
|
|
106
106
|
"react-intersection-observer": "^9",
|
|
107
107
|
"react-layout-kit": "^1",
|
|
108
108
|
"react-lazy-load": "^4",
|
|
109
|
-
"react-wrap-balancer": "^1
|
|
109
|
+
"react-wrap-balancer": "^1",
|
|
110
110
|
"remark": "^14",
|
|
111
111
|
"remark-gfm": "^3",
|
|
112
112
|
"remark-html": "^15",
|
|
113
113
|
"semver": "^7",
|
|
114
|
-
"sharp": "^0.33
|
|
114
|
+
"sharp": "^0.33",
|
|
115
115
|
"swr": "^2",
|
|
116
116
|
"systemjs": "^6",
|
|
117
117
|
"ts-md5": "^1",
|
|
@@ -126,11 +126,11 @@
|
|
|
126
126
|
},
|
|
127
127
|
"devDependencies": {
|
|
128
128
|
"@commitlint/cli": "^18",
|
|
129
|
-
"@ducanh2912/next-pwa": "^9
|
|
129
|
+
"@ducanh2912/next-pwa": "^9",
|
|
130
130
|
"@lobehub/i18n-cli": "latest",
|
|
131
131
|
"@lobehub/lint": "latest",
|
|
132
|
-
"@next/bundle-analyzer": "^14
|
|
133
|
-
"@next/eslint-plugin-next": "^14
|
|
132
|
+
"@next/bundle-analyzer": "^14",
|
|
133
|
+
"@next/eslint-plugin-next": "^14",
|
|
134
134
|
"@testing-library/jest-dom": "^6",
|
|
135
135
|
"@testing-library/react": "^14",
|
|
136
136
|
"@types/chroma-js": "^2",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useAudioPlayer } from '@lobehub/tts/react';
|
|
2
|
+
import { memo, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
import { useChatStore } from '@/store/chat';
|
|
5
|
+
import { useFileStore } from '@/store/file';
|
|
6
|
+
|
|
7
|
+
import { TTSProps } from './InitPlayer';
|
|
8
|
+
import Player from './Player';
|
|
9
|
+
|
|
10
|
+
const FilePlayer = memo<TTSProps>(({ file, id }) => {
|
|
11
|
+
const useFetchTTSFile = useFileStore((s) => s.useFetchTTSFile);
|
|
12
|
+
const [clearTTS] = useChatStore((s) => [s.clearTTS]);
|
|
13
|
+
const { data, isLoading: isFileLoading } = useFetchTTSFile(file || null);
|
|
14
|
+
const { isLoading, ...audio } = useAudioPlayer({ src: data ? data.url : '' });
|
|
15
|
+
|
|
16
|
+
const handleDelete = useCallback(() => {
|
|
17
|
+
clearTTS(id);
|
|
18
|
+
}, [id]);
|
|
19
|
+
|
|
20
|
+
if (!audio || isFileLoading) return;
|
|
21
|
+
|
|
22
|
+
return <Player audio={audio} isLoading={isLoading} onDelete={handleDelete} />;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default FilePlayer;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { memo, useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
|
|
4
|
+
import { useTTS } from '@/hooks/useTTS';
|
|
5
|
+
import { useChatStore } from '@/store/chat';
|
|
6
|
+
import { useFileStore } from '@/store/file';
|
|
7
|
+
import { ChatMessageError, ChatTTS } from '@/types/chatMessage';
|
|
8
|
+
import { getMessageError } from '@/utils/fetch';
|
|
9
|
+
|
|
10
|
+
import Player from './Player';
|
|
11
|
+
|
|
12
|
+
export interface TTSProps extends ChatTTS {
|
|
13
|
+
content: string;
|
|
14
|
+
id: string;
|
|
15
|
+
loading?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const InitPlayer = memo<TTSProps>(({ id, content, contentMd5, file }) => {
|
|
19
|
+
const [isStart, setIsStart] = useState(false);
|
|
20
|
+
const [error, setError] = useState<ChatMessageError>();
|
|
21
|
+
const uploadTTS = useFileStore((s) => s.uploadTTSByArrayBuffers);
|
|
22
|
+
const { t } = useTranslation('chat');
|
|
23
|
+
|
|
24
|
+
const [ttsMessage, clearTTS] = useChatStore((s) => [s.ttsMessage, s.clearTTS]);
|
|
25
|
+
|
|
26
|
+
const setDefaultError = useCallback(
|
|
27
|
+
(err?: any) => {
|
|
28
|
+
setError({ body: err, message: t('tts.responseError', { ns: 'error' }), type: 500 });
|
|
29
|
+
},
|
|
30
|
+
[t],
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const { isGlobalLoading, audio, start, stop, response } = useTTS(content, {
|
|
34
|
+
onError: (err) => {
|
|
35
|
+
stop();
|
|
36
|
+
setDefaultError(err);
|
|
37
|
+
},
|
|
38
|
+
onErrorRetry: (err) => {
|
|
39
|
+
stop();
|
|
40
|
+
setDefaultError(err);
|
|
41
|
+
},
|
|
42
|
+
onSuccess: async () => {
|
|
43
|
+
if (!response || response.ok) return;
|
|
44
|
+
const message = await getMessageError(response);
|
|
45
|
+
if (message) {
|
|
46
|
+
setError(message);
|
|
47
|
+
} else {
|
|
48
|
+
setDefaultError();
|
|
49
|
+
}
|
|
50
|
+
stop();
|
|
51
|
+
},
|
|
52
|
+
onUpload: async (currentVoice, arrayBuffers) => {
|
|
53
|
+
const fileID = await uploadTTS(id, arrayBuffers);
|
|
54
|
+
ttsMessage(id, { contentMd5, file: fileID, voice: currentVoice });
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const handleInitStart = useCallback(() => {
|
|
59
|
+
if (isStart) return;
|
|
60
|
+
start();
|
|
61
|
+
setIsStart(true);
|
|
62
|
+
}, [isStart, start]);
|
|
63
|
+
|
|
64
|
+
const handleDelete = useCallback(() => {
|
|
65
|
+
stop();
|
|
66
|
+
clearTTS(id);
|
|
67
|
+
}, [stop, id]);
|
|
68
|
+
|
|
69
|
+
const handleRetry = useCallback(() => {
|
|
70
|
+
setError(undefined);
|
|
71
|
+
start();
|
|
72
|
+
}, [start]);
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (file) return;
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
handleInitStart();
|
|
78
|
+
}, 100);
|
|
79
|
+
}, [file]);
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<Player
|
|
83
|
+
audio={audio}
|
|
84
|
+
error={error}
|
|
85
|
+
isLoading={isGlobalLoading}
|
|
86
|
+
onDelete={handleDelete}
|
|
87
|
+
onInitPlay={handleInitStart}
|
|
88
|
+
onRetry={handleRetry}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
export default InitPlayer;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AudioPlayer, AudioPlayerProps } from '@lobehub/tts/react';
|
|
2
|
+
import { ActionIcon, Alert, Highlighter } from '@lobehub/ui';
|
|
3
|
+
import { Button } from 'antd';
|
|
4
|
+
import { TrashIcon } from 'lucide-react';
|
|
5
|
+
import { memo } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
import { Flexbox } from 'react-layout-kit';
|
|
8
|
+
|
|
9
|
+
import { ChatMessageError } from '@/types/chatMessage';
|
|
10
|
+
|
|
11
|
+
interface PlayerProps extends AudioPlayerProps {
|
|
12
|
+
error?: ChatMessageError;
|
|
13
|
+
onDelete: () => void;
|
|
14
|
+
onRetry?: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const Player = memo<PlayerProps>(({ onRetry, error, onDelete, audio, isLoading, onInitPlay }) => {
|
|
18
|
+
const { t } = useTranslation('chat');
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Flexbox align={'center'} horizontal style={{ minWidth: 160, width: '100%' }}>
|
|
22
|
+
{error ? (
|
|
23
|
+
<Alert
|
|
24
|
+
action={
|
|
25
|
+
<Button onClick={onRetry} size={'small'} type={'primary'}>
|
|
26
|
+
{t('retry', { ns: 'common' })}
|
|
27
|
+
</Button>
|
|
28
|
+
}
|
|
29
|
+
closable
|
|
30
|
+
extra={
|
|
31
|
+
error.body && (
|
|
32
|
+
<Highlighter copyButtonSize={'small'} language={'json'} type={'pure'}>
|
|
33
|
+
{JSON.stringify(error.body, null, 2)}
|
|
34
|
+
</Highlighter>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
message={error.message}
|
|
38
|
+
onClose={onDelete}
|
|
39
|
+
style={{ alignItems: 'center', width: '100%' }}
|
|
40
|
+
type="error"
|
|
41
|
+
/>
|
|
42
|
+
) : (
|
|
43
|
+
<>
|
|
44
|
+
<AudioPlayer
|
|
45
|
+
allowPause={false}
|
|
46
|
+
audio={audio}
|
|
47
|
+
buttonSize={'small'}
|
|
48
|
+
isLoading={isLoading}
|
|
49
|
+
onInitPlay={onInitPlay}
|
|
50
|
+
onLoadingStop={stop}
|
|
51
|
+
timeRender={'tag'}
|
|
52
|
+
timeStyle={{ margin: 0 }}
|
|
53
|
+
/>
|
|
54
|
+
<ActionIcon icon={TrashIcon} onClick={onDelete} size={'small'} title={t('tts.clear')} />
|
|
55
|
+
</>
|
|
56
|
+
)}
|
|
57
|
+
</Flexbox>
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export default Player;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { memo, useMemo } from 'react';
|
|
2
|
+
import { Md5 } from 'ts-md5';
|
|
3
|
+
|
|
4
|
+
import { settingsSelectors, useGlobalStore } from '@/store/global';
|
|
5
|
+
import { useSessionStore } from '@/store/session';
|
|
6
|
+
import { agentSelectors } from '@/store/session/slices/agent';
|
|
7
|
+
|
|
8
|
+
import FilePlayer from './FilePlayer';
|
|
9
|
+
import InitPlayer, { TTSProps } from './InitPlayer';
|
|
10
|
+
|
|
11
|
+
const TTS = memo<TTSProps>(
|
|
12
|
+
(props) => {
|
|
13
|
+
const { file, voice, content, contentMd5 } = props;
|
|
14
|
+
const lang = useGlobalStore(settingsSelectors.currentLanguage);
|
|
15
|
+
const currentVoice = useSessionStore(agentSelectors.currentAgentTTSVoice(lang));
|
|
16
|
+
|
|
17
|
+
const md5 = useMemo(() => Md5.hashStr(content).toString(), [content]);
|
|
18
|
+
|
|
19
|
+
const isContentEqual = contentMd5 === md5;
|
|
20
|
+
const isVoiceEqual = currentVoice === voice;
|
|
21
|
+
const isEqual = isVoiceEqual && isContentEqual;
|
|
22
|
+
|
|
23
|
+
const PlayerRender = file && isEqual ? FilePlayer : InitPlayer;
|
|
24
|
+
|
|
25
|
+
return <PlayerRender {...props} contentMd5={md5} />;
|
|
26
|
+
},
|
|
27
|
+
(prevProps, nextProps) => {
|
|
28
|
+
return prevProps.id === nextProps.id && prevProps.content === nextProps.content;
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
export default TTS;
|
|
@@ -34,7 +34,7 @@ const AgentPlugin = memo(() => {
|
|
|
34
34
|
// =========== Plugin List =========== //
|
|
35
35
|
|
|
36
36
|
const list = installedPlugins.map(({ identifier, meta }) => ({
|
|
37
|
-
avatar: <Avatar avatar={meta
|
|
37
|
+
avatar: <Avatar avatar={pluginHelpers.getPluginAvatar(meta)} />,
|
|
38
38
|
children: <PluginAction identifier={identifier} />,
|
|
39
39
|
desc: pluginHelpers.getPluginDesc(meta),
|
|
40
40
|
label: pluginHelpers.getPluginTitle(meta),
|
|
@@ -45,7 +45,7 @@ const AgentPlugin = memo(() => {
|
|
|
45
45
|
// =========== Custom Plugin List =========== //
|
|
46
46
|
|
|
47
47
|
const customList = customPluginList.map(({ identifier, meta }) => ({
|
|
48
|
-
avatar: <Avatar avatar={pluginHelpers.getPluginAvatar(meta)
|
|
48
|
+
avatar: <Avatar avatar={pluginHelpers.getPluginAvatar(meta)} />,
|
|
49
49
|
children: <LocalPluginItem id={identifier} />,
|
|
50
50
|
desc: pluginHelpers.getPluginDesc(meta),
|
|
51
51
|
label: (
|
package/src/hooks/useTTS.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { VoiceList } from '@lobehub/tts';
|
|
2
1
|
import {
|
|
3
2
|
EdgeSpeechOptions,
|
|
4
3
|
MicrosoftSpeechOptions,
|
|
5
4
|
OpenAITTSOptions,
|
|
5
|
+
TTSOptions,
|
|
6
6
|
useEdgeSpeech,
|
|
7
7
|
useMicrosoftSpeech,
|
|
8
8
|
useOpenAITTS,
|
|
9
9
|
} from '@lobehub/tts/react';
|
|
10
10
|
import isEqual from 'fast-deep-equal';
|
|
11
|
-
import { SWRConfiguration } from 'swr';
|
|
12
11
|
|
|
13
12
|
import { createHeaderWithOpenAI } from '@/services/_header';
|
|
14
13
|
import { OPENAI_URLS, TTS_URL } from '@/services/_url';
|
|
@@ -17,7 +16,8 @@ import { useSessionStore } from '@/store/session';
|
|
|
17
16
|
import { agentSelectors } from '@/store/session/selectors';
|
|
18
17
|
import { TTSServer } from '@/types/agent';
|
|
19
18
|
|
|
20
|
-
interface TTSConfig extends
|
|
19
|
+
interface TTSConfig extends TTSOptions {
|
|
20
|
+
onUpload?: (currentVoice: string, arraybuffers: ArrayBuffer[]) => void;
|
|
21
21
|
server?: TTSServer;
|
|
22
22
|
voice?: string;
|
|
23
23
|
}
|
|
@@ -25,8 +25,8 @@ interface TTSConfig extends SWRConfiguration {
|
|
|
25
25
|
export const useTTS = (content: string, config?: TTSConfig) => {
|
|
26
26
|
const ttsSettings = useGlobalStore(settingsSelectors.currentTTS, isEqual);
|
|
27
27
|
const ttsAgentSettings = useSessionStore(agentSelectors.currentAgentTTS, isEqual);
|
|
28
|
-
const
|
|
29
|
-
|
|
28
|
+
const lang = useGlobalStore(settingsSelectors.currentLanguage);
|
|
29
|
+
const voice = useSessionStore(agentSelectors.currentAgentTTSVoice(lang));
|
|
30
30
|
let useSelectedTTS;
|
|
31
31
|
let options: any = {};
|
|
32
32
|
switch (config?.server || ttsAgentSettings.ttsService) {
|
|
@@ -39,10 +39,7 @@ export const useTTS = (content: string, config?: TTSConfig) => {
|
|
|
39
39
|
},
|
|
40
40
|
options: {
|
|
41
41
|
model: ttsSettings.openAI.ttsModel,
|
|
42
|
-
voice:
|
|
43
|
-
config?.voice ||
|
|
44
|
-
ttsAgentSettings.voice.openai ||
|
|
45
|
-
VoiceList.openaiVoiceOptions?.[0].value,
|
|
42
|
+
voice: config?.voice || voice,
|
|
46
43
|
},
|
|
47
44
|
} as OpenAITTSOptions;
|
|
48
45
|
break;
|
|
@@ -57,8 +54,7 @@ export const useTTS = (content: string, config?: TTSConfig) => {
|
|
|
57
54
|
*/
|
|
58
55
|
},
|
|
59
56
|
options: {
|
|
60
|
-
voice:
|
|
61
|
-
config?.voice || ttsAgentSettings.voice.edge || voiceList.edgeVoiceOptions?.[0].value,
|
|
57
|
+
voice: config?.voice || voice,
|
|
62
58
|
},
|
|
63
59
|
} as EdgeSpeechOptions;
|
|
64
60
|
break;
|
|
@@ -70,10 +66,7 @@ export const useTTS = (content: string, config?: TTSConfig) => {
|
|
|
70
66
|
serviceUrl: TTS_URL.microsoft,
|
|
71
67
|
},
|
|
72
68
|
options: {
|
|
73
|
-
voice:
|
|
74
|
-
config?.voice ||
|
|
75
|
-
ttsAgentSettings.voice.microsoft ||
|
|
76
|
-
voiceList.microsoftVoiceOptions?.[0].value,
|
|
69
|
+
voice: config?.voice || voice,
|
|
77
70
|
},
|
|
78
71
|
} as MicrosoftSpeechOptions;
|
|
79
72
|
break;
|
|
@@ -83,5 +76,8 @@ export const useTTS = (content: string, config?: TTSConfig) => {
|
|
|
83
76
|
return useSelectedTTS(content, {
|
|
84
77
|
...config,
|
|
85
78
|
...options,
|
|
79
|
+
onFinish: (arraybuffers) => {
|
|
80
|
+
config?.onUpload?.(options.voice || 'alloy', arraybuffers);
|
|
81
|
+
},
|
|
86
82
|
});
|
|
87
83
|
};
|