From eef030e54c2446005611af95bd8a57738e49dae1 Mon Sep 17 00:00:00 2001 From: Sara Date: Fri, 8 Dec 2023 18:41:02 +0100 Subject: [PATCH] basic audio --- .../[transcriptId]/correct/page.tsx | 31 ++++- .../[transcriptId]/correct/topicHeader.tsx | 5 +- .../[transcriptId]/correct/topicPlayer.tsx | 125 ++++++++++++++++++ .../[transcriptId]/correct/topicWords.tsx | 11 +- 4 files changed, 163 insertions(+), 9 deletions(-) create mode 100644 www/app/[domain]/transcripts/[transcriptId]/correct/topicPlayer.tsx diff --git a/www/app/[domain]/transcripts/[transcriptId]/correct/page.tsx b/www/app/[domain]/transcripts/[transcriptId]/correct/page.tsx index 4f8ac9a4..4f6ae512 100644 --- a/www/app/[domain]/transcripts/[transcriptId]/correct/page.tsx +++ b/www/app/[domain]/transcripts/[transcriptId]/correct/page.tsx @@ -1,8 +1,9 @@ "use client"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import useTranscript from "../../useTranscript"; import TopicHeader from "./topicHeader"; import TopicWords from "./topicWords"; +import TopicPlayer from "./topicPlayer"; type TranscriptCorrect = { params: { @@ -10,16 +11,26 @@ type TranscriptCorrect = { }; }; +type TimeSlice = { + start: number; + end: number; +}; + export default function TranscriptCorrect(details: TranscriptCorrect) { const transcriptId = details.params.transcriptId; const transcript = useTranscript(transcriptId); const [currentTopic, setCurrentTopic] = useState(""); - const [selectedTime, setSelectedTime] = useState<{ - start: number; - end: number; - }>(); + const [selectedTime, setSelectedTime] = useState(); + const [topicTime, setTopicTime] = useState(); + + // TODO BE + // Get one topic with words + // -> fix useTopicWithWords.ts + // Add start and end time of each topic in the topic list + // -> use full current topic instead of topicId here + // -> remove time calculation and setting from TopicHeader + // -> pass in topicTime to player directly - console.log(selectedTime); return (
@@ -32,6 +43,14 @@ export default function TranscriptCorrect(details: TranscriptCorrect) { setSelectedTime={setSelectedTime} currentTopic={currentTopic} transcriptId={transcriptId} + setTopicTime={setTopicTime} + /> +
+
+
diff --git a/www/app/[domain]/transcripts/[transcriptId]/correct/topicHeader.tsx b/www/app/[domain]/transcripts/[transcriptId]/correct/topicHeader.tsx index a21a8581..335d9bde 100644 --- a/www/app/[domain]/transcripts/[transcriptId]/correct/topicHeader.tsx +++ b/www/app/[domain]/transcripts/[transcriptId]/correct/topicHeader.tsx @@ -10,8 +10,9 @@ export default function TopicHeader({ }) { const topics = useTopics(transcriptId); useEffect(() => { - !topics.loading && setCurrentTopic(topics?.topics?.at(0)?.id); - console.log(currentTopic); + if (!topics.loading && !currentTopic) { + setCurrentTopic(topics?.topics?.at(0)?.id); + } }, [topics.loading]); if (topics.topics) { diff --git a/www/app/[domain]/transcripts/[transcriptId]/correct/topicPlayer.tsx b/www/app/[domain]/transcripts/[transcriptId]/correct/topicPlayer.tsx new file mode 100644 index 00000000..a3c24f56 --- /dev/null +++ b/www/app/[domain]/transcripts/[transcriptId]/correct/topicPlayer.tsx @@ -0,0 +1,125 @@ +import { useEffect, useState } from "react"; +import useMp3 from "../../useMp3"; + +const TopicPlayer = ({ transcriptId, selectedTime, topicTime }) => { + const mp3 = useMp3(transcriptId); + const [isPlaying, setIsPlaying] = useState(false); + const [endTopicCallback, setEndTopicCallback] = useState<() => void>(); + const [endSelectionCallback, setEndSelectionCallback] = + useState<() => void>(); + + useEffect(() => { + setEndTopicCallback( + () => + function () { + if ( + mp3.media && + topicTime.end && + mp3.media.currentTime >= topicTime.end + ) { + mp3.media.pause(); + setIsPlaying(false); + mp3.media.currentTime = topicTime.start; + } + }, + ); + if (mp3.media) { + mp3.media.currentTime = topicTime.start; + } + }, [topicTime]); + + useEffect(() => { + console.log(endTopicCallback, "he"); + endTopicCallback && + mp3.media && + mp3.media.addEventListener("timeupdate", endTopicCallback); + + return () => { + endTopicCallback && + mp3.media && + mp3.media.removeEventListener("timeupdate", endTopicCallback); + }; + }, [endTopicCallback]); + + const setEndTime = (time) => () => { + if (mp3.media && time && mp3.media.currentTime >= time) { + mp3.media.pause(); + setIsPlaying(false); + mp3.media.removeEventListener("timeupdate", setEndTime); + } + }; + + const playSelection = () => { + if (mp3.media && selectedTime?.start !== undefined) { + mp3.media.currentTime = selectedTime?.start; + setEndSelectionCallback( + () => + function () { + if ( + mp3.media && + selectedTime.end && + mp3.media.currentTime >= selectedTime.end + ) { + mp3.media.pause(); + setIsPlaying(false); + endSelectionCallback && + removeEventListener("timeupdate", endSelectionCallback); + setEndSelectionCallback(() => {}); + } + }, + ); + mp3.media.play(); + setIsPlaying(true); + } + }; + + useEffect(() => { + endSelectionCallback && + mp3.media && + mp3.media.addEventListener("timeupdate", endSelectionCallback); + console.log(endSelectionCallback, "hi"); + return () => { + endSelectionCallback && + mp3.media && + mp3.media.removeEventListener("timeupdate", endSelectionCallback); + }; + }, [endSelectionCallback]); + + const playTopic = () => { + if (mp3.media) { + mp3.media.currentTime = topicTime.start; + mp3.media.play(); + setIsPlaying(true); + endSelectionCallback && + mp3.media.removeEventListener("timeupdate", endSelectionCallback); + } + }; + + const playCurrent = () => { + mp3.media?.play(); + setIsPlaying(true); + }; + + const pause = () => { + mp3.media?.pause(); + setIsPlaying(false); + }; + + if (mp3.media) { + return ( +
+ {!isPlaying ? ( + + ) : ( + + )} + {selectedTime && ( + + )} + {topicTime && } +
+ ); + } +}; + +export default TopicPlayer; diff --git a/www/app/[domain]/transcripts/[transcriptId]/correct/topicWords.tsx b/www/app/[domain]/transcripts/[transcriptId]/correct/topicWords.tsx index aad04924..585cccac 100644 --- a/www/app/[domain]/transcripts/[transcriptId]/correct/topicWords.tsx +++ b/www/app/[domain]/transcripts/[transcriptId]/correct/topicWords.tsx @@ -11,7 +11,12 @@ type Word = { type WordBySpeaker = { speaker: number; words: Word[] }[]; -const topicWords = ({ setSelectedTime, currentTopic, transcriptId }) => { +const topicWords = ({ + setSelectedTime, + currentTopic, + transcriptId, + setTopicTime, +}) => { const topicWithWords = useTopicWithWords(currentTopic, transcriptId); const [wordsBySpeaker, setWordsBySpeaker] = useState(); @@ -35,6 +40,10 @@ const topicWords = ({ setSelectedTime, currentTopic, transcriptId }) => { } }, [] as WordBySpeaker); setWordsBySpeaker(wordsSorted); + setTopicTime({ + start: wordsFlat.at(0)?.start, + end: wordsFlat.at(wordsFlat.length - 1)?.end, + }); } }, [topicWithWords.response]);