yt-chat-components 1.1.9 → 1.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yt-chat-components",
3
- "version": "1.1.9",
3
+ "version": "1.2.0",
4
4
  "main": "build/static/js/bundle.min.js",
5
5
  "module": "build/static/js/bundle.min.js",
6
6
  "types": "build/static/js/index.d.ts",
@@ -42,7 +42,6 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
42
42
 
43
43
  // 添加VAD相关状态
44
44
  const isSpeakingRef = useRef<boolean>(false);
45
- const [isListening, setIsListening] = useState(false);
46
45
  const SILENCE_THRESHOLD = 35; // 静音阈值,可根据环境调整
47
46
  const SPEECH_DELAY = 1500; // 停止说话多久后认为一段话结束(毫秒)
48
47
 
@@ -61,7 +60,8 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
61
60
  const speechTimeoutRef = useRef<NodeJS.Timeout | null>(null);
62
61
  const vadProcessorRef = useRef<ScriptProcessorNode | null>(null);
63
62
  const audioContextRef = useRef<AudioContext | null>(null);
64
-
63
+ const [isSpeakingNow,setIsSpeakingNow] = useState(false);
64
+
65
65
 
66
66
  // 添加统一的WebSocket消息发送方法
67
67
  const sendWebSocketMessage = (type: string, data: any) => {
@@ -73,7 +73,6 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
73
73
  };
74
74
 
75
75
  const handleAudioData = (audioData: string) => {
76
- setIsListening(true);
77
76
  setWorkStatus('正在回复');
78
77
 
79
78
  // 将base64音频转换为Blob
@@ -90,13 +89,6 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
90
89
  const audio = new Audio(audioUrl);
91
90
  responseAudio = audio;
92
91
 
93
- // 监听播放结束事件
94
- audio.onended = () => {
95
- URL.revokeObjectURL(audioUrl);
96
- setIsListening(false);
97
- setWorkStatus('正在聆听');
98
- };
99
-
100
92
  // 监听用户打断
101
93
  audio.onplay = () => {
102
94
  // 设置打断检测
@@ -106,9 +98,8 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
106
98
  console.log('用户打断播放');
107
99
  audio.pause();
108
100
  URL.revokeObjectURL(audioUrl);
109
- setIsListening(false);
110
- setWorkStatus('正在聆听');
111
101
  clearInterval(interruptionCheck);
102
+ setWorkStatus('正在聆听');
112
103
  }
113
104
  }, 100);
114
105
 
@@ -116,7 +107,6 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
116
107
  audio.onended = () => {
117
108
  clearInterval(interruptionCheck);
118
109
  URL.revokeObjectURL(audioUrl);
119
- setIsListening(false);
120
110
  setWorkStatus('正在聆听');
121
111
  };
122
112
  };
@@ -124,7 +114,6 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
124
114
  // 开始播放
125
115
  audio.play().catch(err => {
126
116
  console.error('播放音频失败:', err);
127
- setIsListening(false);
128
117
  setWorkStatus('正在聆听');
129
118
  });
130
119
  };
@@ -210,7 +199,7 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
210
199
  vadProcessorRef.current = vadProcessor;
211
200
 
212
201
  vadProcessor.onaudioprocess = (e) => {
213
- if (isListening) return; // 正在听对方说话,不处理
202
+ if (workStatus === '正在回复' || workStatus === '正在思考') return; // 正在听对方说话 or 思考,不处理
214
203
 
215
204
  analyser.getByteFrequencyData(dataArray);
216
205
 
@@ -223,12 +212,13 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
223
212
 
224
213
  // 检测是否有语音
225
214
  const isSpeakingNow = average > SILENCE_THRESHOLD;
226
-
215
+
227
216
  if (isSpeakingNow && !isSpeakingRef.current) {
217
+ setIsSpeakingNow(true)
228
218
  // 开始说话
229
219
  console.log('开始说话', isSpeakingRef.current);
230
220
  isSpeakingRef.current = true;
231
-
221
+
232
222
  // 开始录制
233
223
  if (!recorderRef.current && localStreamRef.current) {
234
224
  console.log('准备录制');
@@ -257,13 +247,14 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
257
247
  });
258
248
  recorder.start();
259
249
  }
260
-
250
+
261
251
  // 清除之前的超时
262
252
  if (speechTimeoutRef.current) {
263
253
  clearTimeout(speechTimeoutRef.current);
264
254
  speechTimeoutRef.current = null;
265
255
  }
266
- } else if (!isSpeakingNow && isSpeakingRef.current) {
256
+ }
257
+ else if (!isSpeakingNow && isSpeakingRef.current) {
267
258
  console.log('准备停止说话');
268
259
  // 可能停止说话,设置超时
269
260
  if (!speechTimeoutRef.current) {
@@ -271,7 +262,7 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
271
262
  // 确认停止说话
272
263
  console.log('停止说话');
273
264
  isSpeakingRef.current = false;
274
-
265
+
275
266
  // 停止录制
276
267
  if (recorderRef.current) {
277
268
  recorderRef.current.stop((blob: Blob, duration:any, mime:any) => {
@@ -289,8 +280,7 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
289
280
  audioData: base64Audio.split(',')[1], // 移除data URL前缀
290
281
  userMessage: true,
291
282
  audioFormat:"mp3",
292
- sampleRate:16000,
293
- voice:"longxiang"
283
+ sampleRate:16000
294
284
  });
295
285
  console.log('发送完毕');
296
286
 
@@ -301,9 +291,8 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
301
291
  // timestamp: new Date().toISOString()
302
292
  // });
303
293
 
304
- // 设置为正在听模式
305
- setIsListening(true);
306
294
  setWorkStatus('正在思考');
295
+ setIsSpeakingNow(false)
307
296
  }
308
297
  };
309
298
 
@@ -316,11 +305,12 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
316
305
  recorderRef.current=null;
317
306
  });
318
307
  }
319
-
308
+
320
309
  speechTimeoutRef.current = null;
321
310
  }, SPEECH_DELAY);
322
311
  }
323
- } else if (isSpeakingNow && isSpeakingRef.current) {
312
+ }
313
+ else if (isSpeakingNow && isSpeakingRef.current) {
324
314
  console.log('继续说话');
325
315
  // 继续说话,重置超时
326
316
  if (speechTimeoutRef.current) {
@@ -520,8 +510,8 @@ const CallInterface: React.FC<CallInterfaceProps> = ({
520
510
  {/* <div className='recwave' style={{width: 120, height: 50, display: workStatus === '正在聆听' ? 'block' : 'none'}}></div>*/}
521
511
  {/* }*/}
522
512
  {/*</div>*/}
523
- <div className='recwave' style={{width: 120, height: 50}}>{
524
- workStatus === '正在聆听'|| workStatus === '正在回复' ? <img src={ai_call_working}/>:<img src={ai_call_thinking}/>
513
+ <div className='recwave' style={{width: 120, height: 65}}>{
514
+ (isSpeakingNow && workStatus === '正在聆听')|| workStatus === '正在回复' ? <img src={ai_call_working}/>:<img src={ai_call_thinking}/>
525
515
  }</div>
526
516
  <p className="call-status">
527
517
  {workStatus}