yt-chat-components 1.6.7 → 1.6.8
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/package.json +1 -1
- package/src/YtChatView/chatWidget/chatWindow/audioPlayer/AudioPlayer.tsx +23 -13
- package/src/YtChatView/chatWidget/chatWindow/audioRecorder/index.tsx +18 -11
- package/src/YtChatView/chatWidget/chatWindow/chatMessage/index.tsx +17 -13
- package/src/YtChatView/chatWidget/chatWindow/controllers/index.ts +9 -0
- package/src/YtChatView/chatWidget/chatWindow/index.tsx +26 -21
- package/src/YtChatView/chatWidget/chatWindow/inputMobile/inputMobile.jsx +1 -1
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
3
|
import PCMAudioPlayer from "./PCMAudioPlayer";
|
|
4
|
+
import {getAsrToken} from "../controllers";
|
|
4
5
|
|
|
5
6
|
export class AudioPlayer {
|
|
6
7
|
private websocket: WebSocket | null = null;
|
|
7
8
|
private appkey: string;
|
|
8
|
-
private token: string;
|
|
9
9
|
private isSendSentenceEnd : boolean = false;
|
|
10
10
|
private pcmAudioPlayer: PCMAudioPlayer | null = null;
|
|
11
|
-
private voice : string = 'longxiaochun'; // longxiaochun zhixiaoxia
|
|
11
|
+
private voice : string | undefined = 'longxiaochun'; // longxiaochun zhixiaoxia
|
|
12
12
|
|
|
13
13
|
// 回调函数
|
|
14
14
|
onError?: (error: any) => void;
|
|
@@ -20,30 +20,40 @@ export class AudioPlayer {
|
|
|
20
20
|
private isPlaying: boolean = false;
|
|
21
21
|
|
|
22
22
|
constructor(voice: string) {
|
|
23
|
-
// this.appkey = "9S7HL8z0fT80giNH";
|
|
24
|
-
// this.token = 'd20cf27fac634fee88d5d54a12cc36a6';
|
|
25
|
-
|
|
26
23
|
this.appkey = 'DhyCL7mwzachpGjL';
|
|
27
|
-
this.token = '980bc0c1a3fe4fa093ae7cbb470c086f';
|
|
28
|
-
|
|
29
24
|
this.taskId = uuidv4().replaceAll('-', '');
|
|
30
|
-
if (voice){
|
|
25
|
+
if (voice) {
|
|
31
26
|
this.voice = voice;
|
|
32
27
|
}
|
|
33
|
-
|
|
34
28
|
this.pcmAudioPlayer = new PCMAudioPlayer(16000);
|
|
35
29
|
this.pcmAudioPlayer.onQueueEnd = () => {
|
|
36
30
|
this.isPlaying = false;
|
|
37
|
-
if (this.onComplete){
|
|
31
|
+
if (this.onComplete) {
|
|
38
32
|
this.onComplete();
|
|
39
33
|
}
|
|
40
34
|
};
|
|
41
|
-
this.connect();
|
|
42
35
|
}
|
|
43
36
|
|
|
44
|
-
|
|
37
|
+
// 工厂方法:用于异步创建实例
|
|
38
|
+
static async createInstance(voice: string): Promise<AudioPlayer> {
|
|
39
|
+
const instance = new AudioPlayer(voice);
|
|
40
|
+
try {
|
|
41
|
+
// 假设这是你的异步请求
|
|
42
|
+
const response = await getAsrToken('http://localhost:7860', '5f48c683-38d8-430e-8479-17730a605821');
|
|
43
|
+
console.log('response = ', response);
|
|
44
|
+
instance.connect(response?.data?.data?.token); // 连接或其他逻辑
|
|
45
|
+
return instance;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error('Failed to initialize instance:', error);
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
connect(token : string) {
|
|
45
54
|
// cosyvoice 流式语言合成 2元、万字
|
|
46
|
-
|
|
55
|
+
console.log('token = ', token)
|
|
56
|
+
const socketUrl = `wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1?token=${token}`;
|
|
47
57
|
// 普通语言合成 1元、万字
|
|
48
58
|
// const socketUrl = `wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1?token=${this.token}`;
|
|
49
59
|
this.websocket = new WebSocket(socketUrl);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @ts-ignore
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import {getAsrToken} from "../controllers";
|
|
3
4
|
|
|
4
5
|
export class AudioRecorder {
|
|
5
6
|
// 状态与资源
|
|
@@ -11,12 +12,10 @@ export class AudioRecorder {
|
|
|
11
12
|
recordingTimeout: any = null;
|
|
12
13
|
timeoutSeconds: number = 60;
|
|
13
14
|
appkey: string;
|
|
14
|
-
token: string;
|
|
15
|
+
token: string | undefined;
|
|
15
16
|
onTextUpdate: ((text: string) => void) | null = null;
|
|
16
17
|
onRecordError: ((error: any) => void) | null = null;
|
|
17
18
|
onRecordTimeout: (() => void) | null = null;
|
|
18
|
-
|
|
19
|
-
|
|
20
19
|
// 缓存识别结果
|
|
21
20
|
transcriptionCache: {
|
|
22
21
|
[taskId: string]: {
|
|
@@ -29,7 +28,6 @@ export class AudioRecorder {
|
|
|
29
28
|
|
|
30
29
|
finalResults: string[] = [];
|
|
31
30
|
|
|
32
|
-
|
|
33
31
|
constructor(timeoutSeconds: number) {
|
|
34
32
|
this.websocket = null;
|
|
35
33
|
this.audioContext = null;
|
|
@@ -39,14 +37,26 @@ export class AudioRecorder {
|
|
|
39
37
|
if (timeoutSeconds){
|
|
40
38
|
this.timeoutSeconds = timeoutSeconds;
|
|
41
39
|
}
|
|
42
|
-
|
|
43
40
|
this.appkey = 'DhyCL7mwzachpGjL';
|
|
44
|
-
this.token = '980bc0c1a3fe4fa093ae7cbb470c086f';
|
|
45
|
-
|
|
46
41
|
this.bindEventHandlers();
|
|
47
42
|
console.log('AudioRecorder init')
|
|
48
43
|
}
|
|
49
44
|
|
|
45
|
+
// 工厂方法:用于异步创建实例
|
|
46
|
+
static async createInstance(timeoutSeconds: number): Promise<AudioRecorder> {
|
|
47
|
+
const instance = new AudioRecorder(timeoutSeconds);
|
|
48
|
+
try {
|
|
49
|
+
// 假设这是你的异步请求
|
|
50
|
+
const response = await getAsrToken('http://localhost:7860', '5f48c683-38d8-430e-8479-17730a605821');
|
|
51
|
+
console.log('response = ', response);
|
|
52
|
+
instance.token = response?.data?.data?.token;
|
|
53
|
+
return instance;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('Failed to initialize instance:', error);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
bindEventHandlers() {
|
|
51
61
|
// 绑定 this 到所有回调函数中
|
|
52
62
|
this.connectWebSocket = this.connectWebSocket.bind(this);
|
|
@@ -59,12 +69,8 @@ export class AudioRecorder {
|
|
|
59
69
|
}
|
|
60
70
|
|
|
61
71
|
connectWebSocket() {
|
|
62
|
-
|
|
63
|
-
|
|
64
72
|
const socketUrl = `wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1?token=${this.token}`;
|
|
65
|
-
|
|
66
73
|
this.websocket = new WebSocket(socketUrl);
|
|
67
|
-
|
|
68
74
|
// 移除旧事件监听器
|
|
69
75
|
this.cleanupWebSocketListeners();
|
|
70
76
|
|
|
@@ -199,6 +205,7 @@ export class AudioRecorder {
|
|
|
199
205
|
}
|
|
200
206
|
|
|
201
207
|
async startRecorder() {
|
|
208
|
+
console.log('开始录音')
|
|
202
209
|
this.connectWebSocket();
|
|
203
210
|
|
|
204
211
|
// 设置 60 秒超时自动停止
|
|
@@ -151,19 +151,23 @@ export default function ChatMessage({
|
|
|
151
151
|
window.messageAudioPlayer.stop();
|
|
152
152
|
window.messageAudioPlayer = null;
|
|
153
153
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
154
|
+
AudioPlayer.createInstance(voice).then(instance => {
|
|
155
|
+
window.messageAudioPlayer = instance;
|
|
156
|
+
window.messageAudioPlayer.onReady = () => {
|
|
157
|
+
console.log('已连接到语音合成服务');
|
|
158
|
+
window.messageAudioPlayer.sendRunSynthesis(text)// 尽快发送 StartSynthesis
|
|
159
|
+
};
|
|
160
|
+
window.messageAudioPlayer.onComplete = () => {
|
|
161
|
+
setIsPlay(false);
|
|
162
|
+
};
|
|
163
|
+
window.messageAudioPlayer.onError = (err) => {
|
|
164
|
+
// alert('发生错误:' + err);
|
|
165
|
+
};
|
|
166
|
+
setIsPlay(true)
|
|
167
|
+
|
|
168
|
+
}).catch(err => {
|
|
169
|
+
console.error('创建实例失败', err);
|
|
170
|
+
});
|
|
167
171
|
}
|
|
168
172
|
}
|
|
169
173
|
|
|
@@ -256,4 +256,13 @@ export async function getQaInfo(baseUrl: string, flowId: string, api_key: string
|
|
|
256
256
|
timeout:600000
|
|
257
257
|
};
|
|
258
258
|
return axios.get(`${baseUrl}/api/t1/qa_doc/find_doc_by_flow_id/${flowId}`,{headers});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export async function getAsrToken(baseUrl: string, flowId: string) {
|
|
262
|
+
const headers = {
|
|
263
|
+
'Content-Type': 'multipart/form-data',
|
|
264
|
+
// 'x-api-key': api_key,
|
|
265
|
+
timeout:10000
|
|
266
|
+
};
|
|
267
|
+
return axios.get(`${baseUrl}/api/v1/token/${flowId}`,{headers});
|
|
259
268
|
}
|
|
@@ -893,7 +893,7 @@ export default function ChatWindow({
|
|
|
893
893
|
};
|
|
894
894
|
|
|
895
895
|
const stopRecord = () =>{
|
|
896
|
-
audioRecorder
|
|
896
|
+
audioRecorder?.current?.stopRecorder();
|
|
897
897
|
audioRecorder.current = undefined;
|
|
898
898
|
setRecordState(false)
|
|
899
899
|
}
|
|
@@ -902,26 +902,31 @@ export default function ChatWindow({
|
|
|
902
902
|
stopRecord()
|
|
903
903
|
}else {
|
|
904
904
|
setRecordState(true)
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
inputMobileRef.current
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
inputRef.current
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
inputMobileRef.current
|
|
923
|
-
|
|
924
|
-
|
|
905
|
+
AudioRecorder.createInstance(5).then(instance => {
|
|
906
|
+
audioRecorder.current = instance;
|
|
907
|
+
audioRecorder.current.startRecorder();
|
|
908
|
+
audioRecorder.current.onTextUpdate = (text: string) => {
|
|
909
|
+
setValue(text);
|
|
910
|
+
if (inputMobileRef.current){
|
|
911
|
+
inputMobileRef.current.handleSetInputText(text);
|
|
912
|
+
}
|
|
913
|
+
if (inputRef.current) {
|
|
914
|
+
inputRef.current.value = text;
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
audioRecorder.current.onRecordError = (error: string) => {
|
|
918
|
+
stopRecord()
|
|
919
|
+
};
|
|
920
|
+
audioRecorder.current.onRecordTimeout = () => {
|
|
921
|
+
stopRecord()
|
|
922
|
+
if (inputMobileRef.current){
|
|
923
|
+
console.log(inputMobileRef.current)
|
|
924
|
+
inputMobileRef.current.stopRecording();
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
}).catch(error => {
|
|
928
|
+
console.error("启动语音识别失败:", error);
|
|
929
|
+
})
|
|
925
930
|
}
|
|
926
931
|
};
|
|
927
932
|
|
|
@@ -128,7 +128,7 @@ class InputMobile extends React.Component {
|
|
|
128
128
|
onSendClick();
|
|
129
129
|
this.setState({inputText: ''})
|
|
130
130
|
}}>
|
|
131
|
-
<span style={{color: 'white', fontSize: 14}}>{disabled ? '停止' : '
|
|
131
|
+
<span style={{color: 'white', fontSize: 14}}>{disabled ? '停止' : '发送'}</span>
|
|
132
132
|
</div>
|
|
133
133
|
)
|
|
134
134
|
}
|