diff --git a/www/app/[domain]/transcripts/[transcriptId]/page.tsx b/www/app/[domain]/transcripts/[transcriptId]/page.tsx index 3e30b97f..8e2184a0 100644 --- a/www/app/[domain]/transcripts/[transcriptId]/page.tsx +++ b/www/app/[domain]/transcripts/[transcriptId]/page.tsx @@ -4,6 +4,7 @@ import getApi from "../../../lib/getApi"; import useTranscript from "../useTranscript"; import useTopics from "../useTopics"; import useWaveform from "../useWaveform"; +import useMp3 from "../useMp3"; import { TopicList } from "../topicList"; import Recorder from "../recorder"; import { Topic } from "../webSocketTypes"; @@ -31,6 +32,7 @@ export default function TranscriptDetails(details: TranscriptDetails) { const waveform = useWaveform(api, transcriptId); const useActiveTopic = useState(null); const requireLogin = featureEnabled("requireLogin"); + const mp3 = useMp3(api, transcriptId); useEffect(() => { if (requireLogin && !isAuthenticated) return; @@ -70,6 +72,7 @@ export default function TranscriptDetails(details: TranscriptDetails) { waveform={waveform?.waveform} isPastMeeting={true} transcriptId={transcript?.response?.id} + mp3Blob={mp3.blob} /> )} diff --git a/www/app/[domain]/transcripts/recorder.tsx b/www/app/[domain]/transcripts/recorder.tsx index 401b6c9e..d50c90e3 100644 --- a/www/app/[domain]/transcripts/recorder.tsx +++ b/www/app/[domain]/transcripts/recorder.tsx @@ -29,6 +29,7 @@ type RecorderProps = { waveform?: AudioWaveform | null; isPastMeeting: boolean; transcriptId?: string | null; + mp3Blob?: Blob | null; }; export default function Recorder(props: RecorderProps) { @@ -107,11 +108,7 @@ export default function Recorder(props: RecorderProps) { if (waveformRef.current) { const _wavesurfer = WaveSurfer.create({ container: waveformRef.current, - url: props.transcriptId - ? `${process.env.NEXT_PUBLIC_API_URL}/v1/transcripts/${props.transcriptId}/audio/mp3` - : undefined, peaks: props.waveform?.data, - hideScrollbar: true, autoCenter: true, barWidth: 2, @@ -145,6 +142,10 @@ export default function Recorder(props: RecorderProps) { if (props.isPastMeeting) _wavesurfer.toggleInteraction(true); + if (props.mp3Blob) { + _wavesurfer.loadBlob(props.mp3Blob); + } + setWavesurfer(_wavesurfer); return () => { @@ -156,6 +157,12 @@ export default function Recorder(props: RecorderProps) { } }, []); + useEffect(() => { + if (!wavesurfer) return; + if (!props.mp3Blob) return; + wavesurfer.loadBlob(props.mp3Blob); + }, [props.mp3Blob]); + useEffect(() => { topicsRef.current = props.topics; if (!isRecording) renderMarkers(); diff --git a/www/app/[domain]/transcripts/useMp3.ts b/www/app/[domain]/transcripts/useMp3.ts index 8bccf903..b7677180 100644 --- a/www/app/[domain]/transcripts/useMp3.ts +++ b/www/app/[domain]/transcripts/useMp3.ts @@ -1,36 +1,64 @@ -import { useEffect, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { DefaultApi, - V1TranscriptGetAudioMp3Request, + // V1TranscriptGetAudioMp3Request, } from "../../api/apis/DefaultApi"; import {} from "../../api"; import { useError } from "../../(errors)/errorContext"; +import { DomainContext } from "../domainContext"; type Mp3Response = { url: string | null; + blob: Blob | null; loading: boolean; error: Error | null; }; const useMp3 = (api: DefaultApi, id: string): Mp3Response => { const [url, setUrl] = useState(null); + const [blob, setBlob] = useState(null); const [loading, setLoading] = useState(false); const [error, setErrorState] = useState(null); const { setError } = useError(); + const { api_url } = useContext(DomainContext); const getMp3 = (id: string) => { - if (!id) throw new Error("Transcript ID is required to get transcript Mp3"); + if (!id) return; setLoading(true); - const requestParameters: V1TranscriptGetAudioMp3Request = { - transcriptId: id, - }; - api - .v1TranscriptGetAudioMp3(requestParameters) - .then((result) => { - setUrl(result); - setLoading(false); - console.debug("Transcript Mp3 loaded:", result); + // XXX Current API interface does not output a blob, we need to to is manually + // const requestParameters: V1TranscriptGetAudioMp3Request = { + // transcriptId: id, + // }; + // api + // .v1TranscriptGetAudioMp3(requestParameters) + // .then((result) => { + // setUrl(result); + // setLoading(false); + // console.debug("Transcript Mp3 loaded:", result); + // }) + // .catch((err) => { + // setError(err); + // setErrorState(err); + // }); + const localUrl = `${api_url}/v1/transcripts/${id}/audio/mp3`; + if (localUrl == url) return; + const headers = new Headers(); + + if (api.configuration.configuration.accessToken) { + headers.set("Authorization", api.configuration.configuration.accessToken); + } + + fetch(localUrl, { + method: "GET", + headers, + }) + .then((response) => { + setUrl(localUrl); + response.blob().then((blob) => { + setBlob(blob); + setLoading(false); + }); }) .catch((err) => { setError(err); @@ -42,7 +70,7 @@ const useMp3 = (api: DefaultApi, id: string): Mp3Response => { getMp3(id); }, [id]); - return { url, loading, error }; + return { url, blob, loading, error }; }; export default useMp3; diff --git a/www/package.json b/www/package.json index edbc0790..55c7df73 100644 --- a/www/package.json +++ b/www/package.json @@ -35,7 +35,7 @@ "supports-color": "^9.4.0", "tailwindcss": "^3.3.2", "typescript": "^5.1.6", - "wavesurfer.js": "^7.0.3" + "wavesurfer.js": "^7.4.2" }, "main": "index.js", "repository": "https://github.com/Monadical-SAS/reflector-ui.git", diff --git a/www/yarn.lock b/www/yarn.lock index a67822be..8ec03382 100644 --- a/www/yarn.lock +++ b/www/yarn.lock @@ -2638,10 +2638,10 @@ watchpack@2.4.0: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" -wavesurfer.js@^7.0.3: - version "7.0.3" - resolved "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-7.0.3.tgz" - integrity sha512-gJ3P+Bd3Q4E8qETjjg0pneaVqm2J7jegG2Cc6vqEF5YDDKQ3m8sKsvVfgVhJkacKkO9jFAGDu58Hw4zLr7xD0A== +wavesurfer.js@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/wavesurfer.js/-/wavesurfer.js-7.4.2.tgz#59f5c87193d4eeeb199858688ddac1ad7ba86b3a" + integrity sha512-4pNQ1porOCUBYBmd2F1TqVuBnB2wBPipaw2qI920zYLuPnada0Rd1CURgh8HRuPGKxijj2iyZDFN2UZwsaEuhA== wcwidth@>=1.0.1, wcwidth@^1.0.1: version "1.0.1"