From dc23a23d5f2a3d9f22a28a78b8dec243fcd93bd3 Mon Sep 17 00:00:00 2001 From: an-lee Date: Wed, 14 Aug 2024 18:30:31 +0800 Subject: [PATCH] Refactor recorder (#968) * refactor recorder * refactor recording for full transcription * remove deprecated codes * recording time limit * refactor hotkey invoke --- enjoy/src/renderer/components/medias/index.ts | 1 - .../medias/media-current-recording.tsx | 126 ++++++++++-- .../medias/media-player-controls.tsx | 24 ++- .../components/medias/media-recorder.tsx | 154 -------------- .../media-transcription-read-button.tsx | 188 +++++++++--------- .../context/media-player-provider.tsx | 29 ++- 6 files changed, 246 insertions(+), 276 deletions(-) delete mode 100644 enjoy/src/renderer/components/medias/media-recorder.tsx diff --git a/enjoy/src/renderer/components/medias/index.ts b/enjoy/src/renderer/components/medias/index.ts index f57e0d14..249f2929 100644 --- a/enjoy/src/renderer/components/medias/index.ts +++ b/enjoy/src/renderer/components/medias/index.ts @@ -3,7 +3,6 @@ export * from "./media-caption"; export * from "./media-info-panel"; export * from "./media-recordings"; export * from "./media-current-recording"; -export * from "./media-recorder"; export * from "./media-transcription"; export * from "./media-transcription-read-button"; export * from "./media-transcription-generate-button"; diff --git a/enjoy/src/renderer/components/medias/media-current-recording.tsx b/enjoy/src/renderer/components/medias/media-current-recording.tsx index 7ab0297d..60209915 100644 --- a/enjoy/src/renderer/components/medias/media-current-recording.tsx +++ b/enjoy/src/renderer/components/medias/media-current-recording.tsx @@ -4,7 +4,7 @@ import { HotKeysSettingsProviderContext, MediaPlayerProviderContext, } from "@renderer/context"; -import { MediaRecorder, RecordingDetail } from "@renderer/components"; +import { RecordingDetail } from "@renderer/components"; import { renderPitchContour } from "@renderer/lib/utils"; import { extractFrequencies } from "@/utils"; import WaveSurfer from "wavesurfer.js"; @@ -46,12 +46,15 @@ import { import { t } from "i18next"; import { formatDuration } from "@renderer/lib/utils"; import { useHotkeys } from "react-hotkeys-hook"; +import { LiveAudioVisualizer } from "react-audio-visualize"; export const MediaCurrentRecording = () => { const { layout, isRecording, - setIsRecording, + isPaused, + recordingTime, + mediaRecorder, currentRecording, renderPitchContour: renderMediaPitchContour, regions: mediaRegions, @@ -421,13 +424,53 @@ export const MediaCurrentRecording = () => { }, [currentRecording, isRecording, layout?.width]); useHotkeys(currentHotkeys.PlayOrPauseRecording, () => { - document.getElementById("recording-play-or-pause-button")?.click(); + const button = document.getElementById("recording-play-or-pause-button"); + if (!button) return; + + const rect = button.getBoundingClientRect(); + const elementAtPoint = document.elementFromPoint( + rect.left + rect.width / 2, + rect.top + rect.height / 2 + ); + if (elementAtPoint !== button && !button.contains(elementAtPoint)) return; + + button.click(); }); + useHotkeys(currentHotkeys.PronunciationAssessment, () => { + if (isRecording) return; setDetailIsOpen(!detailIsOpen); }); - if (isRecording) return ; + if (isRecording || isPaused) { + return ( +
+
+
+ + + {Math.floor(recordingTime / 60)}: + {String(recordingTime % 60).padStart(2, "0")} + +
+
+
+ +
+
+ ); + } + if (!currentRecording?.src) return (
@@ -443,10 +486,7 @@ export const MediaCurrentRecording = () => {
- +
); @@ -494,10 +534,7 @@ export const MediaCurrentRecording = () => { )} - + + + + + ); + } - const record = ws.registerPlugin(RecordPlugin.create()); - setRecorder(record); - - record.on("record-end", async (blob: Blob) => { - if (interval) clearInterval(interval); - createRecording(blob); - setIsRecording(false); - }); - - return () => { - if (interval) clearInterval(interval); - recorder?.stopRecording(); - ws?.destroy(); - }; - }, [access, ref]); - - useEffect(() => { - askForMediaAccess(); - }, []); return (
-
- {isRecording && ( -
- {duration.toFixed(1)} / {TEN_MINUTES} -
- )}
); diff --git a/enjoy/src/renderer/context/media-player-provider.tsx b/enjoy/src/renderer/context/media-player-provider.tsx index 2f6aa54a..175c6a31 100644 --- a/enjoy/src/renderer/context/media-player-provider.tsx +++ b/enjoy/src/renderer/context/media-player-provider.tsx @@ -16,6 +16,7 @@ import { TimelineEntry } from "echogarden/dist/utilities/Timeline.d.js"; import { toast } from "@renderer/components/ui"; import { Tooltip } from "react-tooltip"; import { debounce } from "lodash"; +import { useAudioRecorder } from "react-audio-voice-recorder"; type MediaPlayerContextType = { layout: { @@ -77,8 +78,14 @@ type MediaPlayerContextType = { transcriptionDraft: TranscriptionType["result"]; setTranscriptionDraft: (result: TranscriptionType["result"]) => void; // Recordings + startRecording: () => void; + stopRecording: () => void; + togglePauseResume: () => void; + recordingBlob: Blob; isRecording: boolean; - setIsRecording: (isRecording: boolean) => void; + isPaused: boolean; + recordingTime: number; + mediaRecorder: MediaRecorder; currentRecording: RecordingType; setCurrentRecording: (recording: RecordingType) => void; recordings: RecordingType[]; @@ -163,7 +170,6 @@ export const MediaPlayerProvider = ({ const [fitZoomRatio, setFitZoomRatio] = useState(1.0); const [zoomRatio, setZoomRatio] = useState(1.0); - const [isRecording, setIsRecording] = useState(false); const [currentRecording, setCurrentRecording] = useState(null); const [transcriptionDraft, setTranscriptionDraft] = @@ -185,6 +191,17 @@ export const MediaPlayerProvider = ({ hasMore: hasMoreRecordings, } = useRecordings(media, currentSegmentIndex); + const { + startRecording, + stopRecording, + togglePauseResume, + recordingBlob, + isRecording, + isPaused, + recordingTime, + mediaRecorder, + } = useAudioRecorder(); + const { segment, createSegment } = useSegments({ targetId: media?.id, targetType: media?.mediaType, @@ -625,8 +642,14 @@ export const MediaPlayerProvider = ({ transcribingOutput, transcriptionDraft, setTranscriptionDraft, + startRecording, + stopRecording, + togglePauseResume, + recordingBlob, isRecording, - setIsRecording, + isPaused, + recordingTime, + mediaRecorder, currentRecording, setCurrentRecording, recordings,