File size: 3,171 Bytes
7d8f5e6 d2e049e a7e962d d2e049e 2b66f8c d2e049e 7b381b0 a7e962d 2b66f8c d2e049e 7d8f5e6 0086f8a 7d8f5e6 0086f8a 7d8f5e6 a7e962d 16e3fae a7e962d 2b66f8c a7e962d 2b66f8c a7e962d 2b66f8c a7e962d 2b66f8c a7e962d 7b381b0 16e3fae a7e962d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
import { useDeleteMessage, useFeedback } from '@/hooks/chat-hooks';
import { useSetModalState } from '@/hooks/common-hooks';
import { IRemoveMessageById, useSpeechWithSse } from '@/hooks/logic-hooks';
import { IFeedbackRequestBody } from '@/interfaces/request/chat';
import { ConversationContext } from '@/pages/chat/context';
import { getMessagePureId } from '@/utils/chat';
import { hexStringToUint8Array } from '@/utils/common-util';
import { SpeechPlayer } from 'openai-speech-stream-player';
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
export const useSendFeedback = (messageId: string) => {
const { visible, hideModal, showModal } = useSetModalState();
const { feedback, loading } = useFeedback();
const onFeedbackOk = useCallback(
async (params: IFeedbackRequestBody) => {
const ret = await feedback({
...params,
messageId: getMessagePureId(messageId),
});
if (ret === 0) {
hideModal();
}
},
[feedback, hideModal, messageId],
);
return {
loading,
onFeedbackOk,
visible,
hideModal,
showModal,
};
};
export const useRemoveMessage = (
messageId: string,
removeMessageById?: IRemoveMessageById['removeMessageById'],
) => {
const { deleteMessage, loading } = useDeleteMessage();
const onRemoveMessage = useCallback(async () => {
const pureId = getMessagePureId(messageId);
if (pureId) {
const retcode = await deleteMessage(pureId);
if (retcode === 0) {
removeMessageById?.(messageId);
}
}
}, [deleteMessage, messageId, removeMessageById]);
return { onRemoveMessage, loading };
};
export const useSpeech = (content: string, audioBinary?: string) => {
const ref = useRef<HTMLAudioElement>(null);
const { read } = useSpeechWithSse();
const player = useRef<SpeechPlayer>();
const [isPlaying, setIsPlaying] = useState<boolean>(false);
const callback = useContext(ConversationContext);
const initialize = useCallback(async () => {
player.current = new SpeechPlayer({
audio: ref.current!,
onPlaying: () => {
setIsPlaying(true);
callback?.(true);
},
onPause: () => {
setIsPlaying(false);
callback?.(false);
},
onChunkEnd: () => {},
mimeType: 'audio/mpeg',
});
await player.current.init();
}, [callback]);
const pause = useCallback(() => {
player.current?.pause();
}, []);
const speech = useCallback(async () => {
const response = await read({ text: content });
if (response) {
player?.current?.feedWithResponse(response);
}
}, [read, content]);
const handleRead = useCallback(async () => {
if (isPlaying) {
setIsPlaying(false);
pause();
} else {
setIsPlaying(true);
speech();
}
}, [setIsPlaying, speech, isPlaying, pause]);
useEffect(() => {
if (audioBinary) {
const units = hexStringToUint8Array(audioBinary);
if (units) {
player.current?.feed(units);
}
}
}, [audioBinary]);
useEffect(() => {
initialize();
}, [initialize]);
return { ref, handleRead, isPlaying };
};
|