import { useRef, useEffect } from "react"; import { TranscriberData } from "../hooks/useTranscriber"; import { formatAudioTimestamp } from "../utils/AudioUtils"; interface Props { transcribedData: TranscriberData | undefined; } export default function Transcript({ transcribedData }: Props) { const divRef = useRef(null); const saveBlob = (blob: Blob, filename: string) => { const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = filename; link.click(); URL.revokeObjectURL(url); }; const exportTXT = () => { let chunks = transcribedData?.chunks ?? []; let text = chunks .map((chunk) => chunk.text) .join("") .trim(); const blob = new Blob([text], { type: "text/plain" }); saveBlob(blob, "transcript.txt"); }; const exportJSON = () => { let jsonData = JSON.stringify(transcribedData?.chunks ?? [], null, 2); // post-process the JSON to make it more readable const regex = /( "timestamp": )\[\s+(\S+)\s+(\S+)\s+\]/gm; jsonData = jsonData.replace(regex, "$1[$2 $3]"); const blob = new Blob([jsonData], { type: "application/json" }); saveBlob(blob, "transcript.json"); }; // Scroll to the bottom when the component updates useEffect(() => { if (divRef.current) { const diff = Math.abs( divRef.current.offsetHeight + divRef.current.scrollTop - divRef.current.scrollHeight, ); if (diff <= 64) { // We're close enough to the bottom, so scroll to the bottom divRef.current.scrollTop = divRef.current.scrollHeight; } } }); return (
{transcribedData?.chunks && transcribedData.chunks.map((chunk, i) => (
{formatAudioTimestamp(chunk.timestamp[0])}
{chunk.text}
))} {transcribedData && !transcribedData.isBusy && (
)}
); }