Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OPENAI_API_KEY=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
139 changes: 139 additions & 0 deletions app/(main)/(routes)/documents/[documentId]/S2T.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
"use client";

// Import necessary modules and components
import { useEffect, useState, useRef } from "react";

// Declare a global interface to add the webkitSpeechRecognition property to the Window object
declare global {
interface Window {
webkitSpeechRecognition: any;
}
}

// Export the MicrophoneComponent function component
export const MicrophoneComponent = () => {
// State variables to manage recording status, completion, and transcript
const [isRecording, setIsRecording] = useState(false);
const [recordingComplete, setRecordingComplete] = useState(false);
const [transcript, setTranscript] = useState("");

// Reference to store the SpeechRecognition instance
const recognitionRef = useRef<any>(null);

// Function to start recording
const startRecording = () => {
setIsRecording(true);
// Create a new SpeechRecognition instance and configure it
recognitionRef.current = new window.webkitSpeechRecognition();
recognitionRef.current.continuous = true;
recognitionRef.current.interimResults = true;

// Event handler for speech recognition results
recognitionRef.current.onresult = (event: any) => {
const { transcript } = event.results[event.results.length - 1][0];


// Update the transcript state by concatenating the new transcript
setTranscript(transcript);
console.log('transcript:',transcript)
};

};

// Cleanup effect when the component unmounts
useEffect(() => {
return () => {
// Stop the speech recognition if it's active
if (recognitionRef.current) {
recognitionRef.current.stop();
}
};
}, []);

// Function to stop recording
const stopRecording = () => {
if (recognitionRef.current) {
// Stop the speech recognition and mark recording as complete
recognitionRef.current.stop();
setRecordingComplete(true);
}
};

// Toggle recording state and manage recording actions
const handleToggleRecording = () => {
setIsRecording(!isRecording);
if (!isRecording) {
startRecording();
} else {
stopRecording();
}
};

// Render the microphone component with appropriate UI based on recording state
return (
<div className="flex items-center justify-center h-screen w-full">
<div className="w-full">
{(isRecording || transcript) && (
<div className="w-1/4 m-auto rounded-md border p-4 bg-white">
<div className="flex-1 flex w-full justify-between">
<div className="space-y-1">
<p className="text-sm font-medium leading-none">
{recordingComplete ? "Recorded" : "Recording"}
</p>
<p className="text-sm text-muted-foreground">
{recordingComplete
? "Thanks for talking."
: "Start speaking..."}
</p>
</div>
{isRecording && (
<div className="rounded-full w-4 h-4 bg-red-400 animate-pulse" />
)}
</div>

{transcript && (
<div className="border rounded-md p-2 h-full mt-4">
<p className="text-black mb-0">{transcript}</p>
</div>
)}
</div>
)}

<div className="flex items-center w-full">
{isRecording ? (
// Button for stopping recording
<button
onClick={handleToggleRecording}
className="mt-10 m-auto flex items-center justify-center bg-red-400 hover:bg-red-500 rounded-full w-20 h-20 focus:outline-none"
>
<svg
className="h-12 w-12 "
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path fill="white" d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
</svg>
</button>
) : (
// Button for starting recording
<button
onClick={handleToggleRecording}
className="mt-10 m-auto flex items-center justify-center bg-blue-400 hover:bg-blue-500 rounded-full w-20 h-20 focus:outline-none"
>
<svg
viewBox="0 0 256 256"
xmlns="http://www.w3.org/2000/svg"
className="w-12 h-12 text-white"
>
<path
fill="currentColor" // Change fill color to the desired color
d="M128 176a48.05 48.05 0 0 0 48-48V64a48 48 0 0 0-96 0v64a48.05 48.05 0 0 0 48 48ZM96 64a32 32 0 0 1 64 0v64a32 32 0 0 1-64 0Zm40 143.6V232a8 8 0 0 1-16 0v-24.4A80.11 80.11 0 0 1 48 128a8 8 0 0 1 16 0a64 64 0 0 0 128 0a8 8 0 0 1 16 0a80.11 80.11 0 0 1-72 79.6Z"
/>
</svg>
</button>
)}
</div>
</div>
</div>
);
}
11 changes: 11 additions & 0 deletions app/(main)/(routes)/documents/[documentId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { api } from "@/convex/_generated/api";
import { Id } from "@/convex/_generated/dataModel";
import { Toolbar } from "@/components/toolbar";
import { Skeleton } from "@/components/ui/skeleton";
import { Button } from "@/components/ui/button";

import { MicrophoneComponent } from "./S2T";

interface DocumentIdPageProps {
params: {
Expand All @@ -33,6 +36,13 @@ const DocumentIdPage = ({
});
};

const onTranscript = (content:string) => {
update({
id: params.documentId,
content
})
}

if (document === undefined) {
return (
<div>
Expand All @@ -56,6 +66,7 @@ const DocumentIdPage = ({
<div className="pb-40">
<div className="md:max-w-3xl lg:max-w-4xl mx-auto">
<Toolbar initialData={document} />
<MicrophoneComponent />
<Editor
onChange={onChange}
initialContent={document.content}
Expand Down
1 change: 1 addition & 0 deletions app/(main)/(routes)/documents/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const DocumentsPage = () => {

return (
<div className="h-full flex flex-col items-center justify-center space-y-4">

<Image
src="/empty.png"
height="300"
Expand Down
1 change: 1 addition & 0 deletions app/(main)/_components/banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { api } from "@/convex/_generated/api";
import { Button } from "@/components/ui/button";
import { ConfirmModal } from "@/components/modals/confirm-modal";


interface BannerProps {
documentId: Id<"documents">;
};
Expand Down
1 change: 1 addition & 0 deletions app/utils/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
OPENAI_API_KEY=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
8 changes: 8 additions & 0 deletions app/utils/openai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import OpenAI from 'openai';

const openai = new OpenAI({
apiKey: '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',dangerouslyAllowBrowser: true
});


export default openai
Loading