Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
AnkushRathour authored Apr 21, 2024
1 parent 739cff8 commit 7effcdb
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 0 deletions.
32 changes: 32 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import uvicorn
from langchain_cohere import ChatCohere
from langchain_core.messages import HumanMessage

app = FastAPI()

llm = ChatCohere(cohere_api_key='lMQ2FCVWccphyyB10tGpZg3oinBjGOixW0D3fmPd')

app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")

@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
return templates.TemplateResponse("index.html", {"request": request})

@app.websocket("/transcribe")
async def transcribe(websocket: WebSocket):
await websocket.accept()

while True:
human_input = await websocket.receive_text()
if human_input:
human_message = [HumanMessage(content=human_input)]
response = llm.invoke(human_message, max_tokens=80)
await websocket.send_text(response.content)

if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=5000, reload=True)
34 changes: 34 additions & 0 deletions static/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* Speech recognition output */
.output-box {
background-color: rgb(248 245 245);
padding: 20px;
border-radius: 10px;
min-height: 150px;
overflow-y: auto;
}

/* Theme toggle button styles */
.theme-toggle {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
background-color: #9a69dc;
color: white;
border: none;
border-radius: 50%;
width: 50px;
height: 50px;
font-size: 24px;
cursor: pointer;
}

/* Recording button styles */
.recording-button {
font-size: 24px;
border-radius: 50%;
width: 90px;
height: 90px;
margin: 0 10px;
background-color: #9a69dc;
}
116 changes: 116 additions & 0 deletions static/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Theme toggle
const body = document.body;
const themeToggle = document.getElementById("themeToggle");
// WebSocket
var httpProtocol = 'http://';
var wsProtocol = 'ws://';
if (window.location.protocol === 'https:') {
httpProtocol = 'https://';
wsProtocol = 'wss://';
}
const socket = new WebSocket(wsProtocol + window.location.host + "/transcribe");
// Recording Button
const recordingButton = document.getElementById("recordingButton");
// Output Box
const output = document.getElementById("output");
let isRecording = false;

// Theme toggle functionality
themeToggle.addEventListener("click", () => {
body.classList.toggle("bg-dark");
const isDarkTheme = body.classList.contains("bg-dark");
themeToggle.innerHTML = isDarkTheme
? '<i class="bi bi-sun"></i>'
: '<i class="bi bi-moon"></i>';
});

// Initialize speech recognition
const SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();

recognition.interimResults = false; // Enable interim results
recognition.continuous = false;
recognition.lang = "en-US";

// Event listeners for start and stop buttons
recordingButton.addEventListener("click", toggleRecording);
function toggleRecording() {
isRecording = !isRecording;
recordingButton.innerHTML = isRecording
? '<i class="bi bi-mic-mute-fill"></i>'
: '<i class="bi bi-mic-fill"></i>';
if (isRecording) {
startRecording();
} else {
stopRecording();
}
}

// Event listener for when speech recognition starts
recognition.onstart = function () {
console.log("Speech recognition started...");
output.innerHTML = "";
output.innerHTML = '<p class="text-muted">Listening...</p>';
};

// Event listener for interim results
recognition.onresult = function (event) {
const interimTranscript = Array.from(event.results)
.map((result) => result[0].transcript)
.join("");
output.innerHTML = `<p>${interimTranscript}</p>`;
socket.send(interimTranscript);
};

// Event listener for when speech recognition ends
recognition.onend = function () {
console.log("Speech recognition ended.");
isRecording = !isRecording;
recordingButton.innerHTML = isRecording
? '<i class="bi bi-mic-mute-fill"></i>'
: '<i class="bi bi-mic-fill"></i>';
};

// Function to start recording
function startRecording() {
navigator.mediaDevices
.getUserMedia({ audio: true })
.then(() => {
recognition.start(); // Start recognition
speechSynthesis.cancel();
isRecording = true
})
.catch((error) => {
// Microphone is not enabled or available
console.error("Microphone is not enabled or available:", error);
alert(
"Microphone is not enabled or available. Please enable your microphone and refresh the page."
);
});
}

function stopRecording() {
recognition.stop();
isRecording = false
output.innerHTML = '<p class="text-muted">Start Recording to begin.</p>'
}

// On reciveing message from socket
socket.onmessage = function (event) {
stopRecording();
output.innerHTML = `<p>${event.data}</p>`;
textToSpeech(event.data);
};

// Speak recieved text from AI
function textToSpeech(phrase) {
const audio = new Audio();
const speechSettings = new SpeechSynthesisUtterance(phrase);
speechSynthesis.speak(speechSettings);
}

// Stop speaking
function stopSpeaker() {
speechSynthesis.cancel();
}
Binary file added static/logo/talkgenie-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/logo/talkgenie-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TalkGenie</title>
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', path='/logo/talkgenie-icon.png') }}">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
<link href="{{ url_for('static', path='/css/style.css') }}" rel="stylesheet">
</head>

<body class="bg-dark">
<!-- Theme toggle button -->
<button id="themeToggle" class="theme-toggle" title="Toggle Theme">
<i class="bi bi-sun"></i>
</button>

<!-- Main contianer -->
<div class="container text-center">
<img src="{{ url_for('static', path='/logo/talkgenie-logo.png') }}" height="500" />
<p style="color: rgb(182 146 228);">TalkGenie grant your voice wishes, utilizing advanced AI to understand your
commands and provide swift and accurate responses tailored to your needs.</p>
<div class="mb-4">
<button id="recordingButton" class="btn btn-dark recording-button" title="Start Recording">
<i class="bi bi-mic-fill"></i>
</button>
</div>
<div id="output" class="output-box">
<p class="text-muted">Start Recording to begin.</p>
</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script src="{{ url_for('static', path='/js/index.js') }}"></script>
<script>
</script>
</body>

</html>

0 comments on commit 7effcdb

Please sign in to comment.