diff --git a/projects/translate-h5/src/http/axios-instance.ts b/projects/translate-h5/src/http/axios-instance.ts index 5751940..0935e07 100644 --- a/projects/translate-h5/src/http/axios-instance.ts +++ b/projects/translate-h5/src/http/axios-instance.ts @@ -46,6 +46,9 @@ class AxiosInstance { return this.instance; } } - -const baseURL = import.meta.env.VITE_BASE_URL || "https://petshy.tashowz.com"; +console.log(import.meta.env.VITE_BASE_URL, "import.meta.env.VITE_BASE_URL"); +// https://petshy.tashowz.com +//192.168.1.231:48080 +// || "http://192.168.1.231:48080" +const baseURL = import.meta.env.VITE_BASE_URL; export const axiosInstance = new AxiosInstance(baseURL).getInstance(); diff --git a/projects/translate-h5/src/view/home/translate/component/message/index.tsx b/projects/translate-h5/src/view/home/translate/component/message/index.tsx index 0c04af3..4c673ae 100644 --- a/projects/translate-h5/src/view/home/translate/component/message/index.tsx +++ b/projects/translate-h5/src/view/home/translate/component/message/index.tsx @@ -74,7 +74,7 @@ function Index(props: DefinedProps) { break; default: console.warn("未知错误"); - }; + } Toast.show("音频播放失败"); setIsPlating(false); }; @@ -127,6 +127,7 @@ function Index(props: DefinedProps) { {data.map((item, index) => (
playAudio(item.id, item.contentText)}> {renderAvatar(item.petType)} +
{item.petName} diff --git a/projects/translate-h5/src/view/home/translate/component/voice/index.tsx b/projects/translate-h5/src/view/home/translate/component/voice/index.tsx index 0d876c9..908b426 100644 --- a/projects/translate-h5/src/view/home/translate/component/voice/index.tsx +++ b/projects/translate-h5/src/view/home/translate/component/voice/index.tsx @@ -4,9 +4,8 @@ import { Button, Dialog, Image, ProgressCircle, Toast } from "antd-mobile"; import microphoneSvg from "@/assets/translate/microphone.svg"; import microphoneDisabledSvg from "@/assets/translate/microphoneDisabledSvg.svg"; import { createStartRecordSound, createSendSound } from "@/utils/voice"; -import "./index.less"; import VConsole from "vconsole"; - +import "./index.less"; interface DefinedProps { onRecordingComplete: (url: string, finalDuration: number, formData: FormData) => void; isRecording: boolean; @@ -195,6 +194,74 @@ function Index(props: DefinedProps) { } }; + // 添加音频转换函数 + const convertToWav = async (blob: Blob): Promise => { + const arrayBuffer = await blob.arrayBuffer(); + const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)(); + const audioBuffer = await audioContext.decodeAudioData(arrayBuffer); + + // 转换为 WAV 格式 + const wavBuffer = audioBufferToWav(audioBuffer); + return new Blob([wavBuffer], { type: "audio/wav" }); + }; + + // WAV 转换辅助函数 + const audioBufferToWav = (buffer: AudioBuffer): ArrayBuffer => { + const length = buffer.length; + const numberOfChannels = buffer.numberOfChannels; + const sampleRate = buffer.sampleRate; + const bitsPerSample = 16; + const byteRate = (sampleRate * numberOfChannels * bitsPerSample) / 8; + const blockAlign = (numberOfChannels * bitsPerSample) / 8; + const dataSize = length * numberOfChannels * (bitsPerSample / 8); + const bufferLength = 44 + dataSize; + const arrayBuffer = new ArrayBuffer(bufferLength); + const view = new DataView(arrayBuffer); + // RIFF identifier + writeString(view, 0, "RIFF"); + // file length + view.setUint32(4, 36 + dataSize, true); + // RIFF type + writeString(view, 8, "WAVE"); + // format chunk identifier + writeString(view, 12, "fmt "); + // format chunk length + view.setUint32(16, 16, true); + // sample format (raw) + view.setUint16(20, 1, true); + // channel count + view.setUint16(22, numberOfChannels, true); + // sample rate + view.setUint32(24, sampleRate, true); + // byte rate (sample rate * block align) + view.setUint32(28, byteRate, true); + // block align (channel count * bytes per sample) + view.setUint16(32, blockAlign, true); + // bits per sample + view.setUint16(34, bitsPerSample, true); + // data chunk identifier + writeString(view, 36, "data"); + // data chunk length + view.setUint32(40, dataSize, true); + + // write the PCM samples + let offset = 44; + for (let i = 0; i < length; i++) { + for (let channel = 0; channel < numberOfChannels; channel++) { + const sample = Math.max(-1, Math.min(1, buffer.getChannelData(channel)[i])); + view.setInt16(offset, sample < 0 ? sample * 0x8000 : sample * 0x7fff, true); + offset += 2; + } + } + return arrayBuffer; + }; + + const writeString = (view: DataView, offset: number, string: string) => { + for (let i = 0; i < string.length; i++) { + view.setUint8(offset + i, string.charCodeAt(i)); + } + }; + //开始录音 const onStartRecording = () => { isCancelledRef.current = false; @@ -214,6 +281,7 @@ function Index(props: DefinedProps) { recorderControls.stopRecording(); onResetRecordingState(); }, [recorderControls, recordingDuration]); + //录音完成 // 在发送时检查录音时长 const onRecordingComplete = useCallback( @@ -222,30 +290,17 @@ function Index(props: DefinedProps) { Toast.show("已取消"); return; } + // 检查blob有效性 if (!blob || blob.size === 0) { Toast.show("录音数据无效,请重新录音"); - return; } + // 转换为 WAV 格式以获得最佳兼容性 + const wavBlob = await convertToWav(blob); const formData: FormData = new FormData(); - formData.append( - "file", - blob, - new Date().getTime() + "." + blob.type.split("/").pop()?.split(";")[0] - ); - - // 把demoWAV替换成blob - - // const response = await fetch(demoWAV); - // const arrayBuffer = await response.arrayBuffer(); - // const demoWAVBlob = new Blob([arrayBuffer], { type: "audio/wav" }); - - // formData.append("file", demoWAVBlob); + formData.append("file", wavBlob, new Date().getTime() + "." + new Date().getTime() + ".wav"); formData.append("dialogId", `${dialogId}`); - - // await handleUploadAudio(formData); - // const audioUrl = URL.createObjectURL(demoWAVBlob); const audioUrl = URL.createObjectURL(blob); const audio = new Audio(); audio.src = audioUrl; @@ -283,6 +338,9 @@ function Index(props: DefinedProps) { autoGainControl: true, }} showVisualizer={false} + mediaRecorderOptions={{ + mimeType: "audio/webm", + }} />
{renderBtn()}
diff --git a/projects/translate-h5/vite.config.ts b/projects/translate-h5/vite.config.ts index 0587ee7..cfdbfd7 100644 --- a/projects/translate-h5/vite.config.ts +++ b/projects/translate-h5/vite.config.ts @@ -5,6 +5,8 @@ import { inspectorServer } from "@react-dev-inspector/vite-plugin"; import basicSsl from "@vitejs/plugin-basic-ssl"; export default defineConfig({ // basicSsl() + // target: "https://petshy.tashowz.com", + // http://192.168.1.231:48080 plugins: [react()], server: { port: 3000, @@ -12,7 +14,7 @@ export default defineConfig({ open: true, proxy: { "/app-api": { - target: "https://petshy.tashowz.com", + target: "http://192.168.1.231:48080", changeOrigin: true, }, },