|
|
@@ -1,6 +1,7 @@
|
|
|
import { useState, useCallback, useRef, useEffect } from 'react';
|
|
|
import { AgoraSTTConfig, TranscriptionResult, AgoraSTTState, UseAgoraSTTResult } from '@/client/types/agora-stt';
|
|
|
import { getAgoraConfig, validateAgoraConfig, isBrowserSupported, getBrowserSupportError } from '@/client/utils/agora-stt';
|
|
|
+import { agoraClient } from '@/client/api';
|
|
|
|
|
|
export const useAgoraSTT = (): UseAgoraSTTResult => {
|
|
|
const [state, setState] = useState<AgoraSTTState>({
|
|
|
@@ -19,6 +20,7 @@ export const useAgoraSTT = (): UseAgoraSTTResult => {
|
|
|
const mediaRecorder = useRef<MediaRecorder | null>(null);
|
|
|
const audioChunks = useRef<Blob[]>([]);
|
|
|
const config = useRef<AgoraSTTConfig | null>(null);
|
|
|
+ const currentToken = useRef<string | null>(null);
|
|
|
|
|
|
const updateState = useCallback((updates: Partial<AgoraSTTState>) => {
|
|
|
setState(prev => ({ ...prev, ...updates }));
|
|
|
@@ -28,6 +30,34 @@ export const useAgoraSTT = (): UseAgoraSTTResult => {
|
|
|
updateState({ error });
|
|
|
}, [updateState]);
|
|
|
|
|
|
+ const fetchDynamicToken = useCallback(async (type: 'rtc' | 'rtm', channel?: string, userId?: string): Promise<string> => {
|
|
|
+ try {
|
|
|
+ const query: any = { type };
|
|
|
+
|
|
|
+ if (type === 'rtc' && channel) {
|
|
|
+ query.channel = channel;
|
|
|
+ } else if (type === 'rtm' && userId) {
|
|
|
+ query.userId = userId;
|
|
|
+ }
|
|
|
+
|
|
|
+ const response = await agoraClient.token.$get({ query });
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error(`Token API returned ${response.status}: ${response.statusText}`);
|
|
|
+ }
|
|
|
+
|
|
|
+ const data = await response.json();
|
|
|
+
|
|
|
+ if (!data.token) {
|
|
|
+ throw new Error('Invalid token response format');
|
|
|
+ }
|
|
|
+
|
|
|
+ return data.token;
|
|
|
+ } catch (error) {
|
|
|
+ throw new Error(`Failed to fetch dynamic token: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
|
+ }
|
|
|
+ }, []);
|
|
|
+
|
|
|
const initializeConfig = useCallback((): boolean => {
|
|
|
try {
|
|
|
if (!isBrowserSupported()) {
|
|
|
@@ -59,12 +89,16 @@ export const useAgoraSTT = (): UseAgoraSTTResult => {
|
|
|
try {
|
|
|
updateState({ error: null, isConnecting: true });
|
|
|
|
|
|
+ // 动态获取RTC Token
|
|
|
+ const dynamicToken = await fetchDynamicToken('rtc', config.current!.channel);
|
|
|
+ currentToken.current = dynamicToken;
|
|
|
+
|
|
|
// 模拟Agora STT加入频道API调用
|
|
|
const joinResponse = await fetch(config.current!.sttJoinUrl, {
|
|
|
method: 'POST',
|
|
|
headers: {
|
|
|
'Content-Type': 'application/json',
|
|
|
- 'Authorization': `Bearer ${config.current!.token}`
|
|
|
+ 'Authorization': `Bearer ${dynamicToken}`
|
|
|
},
|
|
|
body: JSON.stringify({
|
|
|
appId: config.current!.appId,
|
|
|
@@ -133,7 +167,7 @@ export const useAgoraSTT = (): UseAgoraSTTResult => {
|
|
|
setError('Failed to join Agora channel: ' + (error instanceof Error ? error.message : 'Unknown error'));
|
|
|
updateState({ isConnecting: false });
|
|
|
}
|
|
|
- }, [initializeConfig, updateState, setError]);
|
|
|
+ }, [initializeConfig, updateState, setError, fetchDynamicToken]);
|
|
|
|
|
|
const leaveChannel = useCallback((): void => {
|
|
|
if (wsConnection.current) {
|