myexperiments / index.html
naresh10's picture
Add 3 files
11a4805 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meeting Minutes Transcriber</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.pulse-animation {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.waveform {
display: flex;
align-items: center;
height: 40px;
width: 100%;
}
.waveform-bar {
background-color: #4f46e5;
margin: 0 1px;
width: 3px;
transition: height 0.2s ease;
}
.transcript-container {
max-height: 300px;
overflow-y: auto;
scrollbar-width: thin;
}
.transcript-container::-webkit-scrollbar {
width: 5px;
}
.transcript-container::-webkit-scrollbar-thumb {
background-color: #c7d2fe;
border-radius: 10px;
}
</style>
</head>
<body class="bg-gray-100 font-sans">
<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl min-h-screen">
<!-- App Header -->
<header class="bg-indigo-600 text-white p-4">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<i class="fas fa-microphone text-xl"></i>
<h1 class="text-xl font-bold">MeetNotes</h1>
</div>
<div class="flex space-x-3">
<button class="p-1 rounded-full hover:bg-indigo-500">
<i class="fas fa-cog"></i>
</button>
<button class="p-1 rounded-full hover:bg-indigo-500">
<i class="fas fa-question-circle"></i>
</button>
</div>
</div>
</header>
<!-- Main Content -->
<main class="p-4">
<!-- Recording Section -->
<div class="bg-indigo-50 rounded-lg p-4 mb-6">
<div class="flex justify-between items-center mb-3">
<h2 class="text-lg font-semibold text-indigo-800">Meeting Recording</h2>
<span id="recording-time" class="text-sm font-medium text-indigo-600">00:00:00</span>
</div>
<div class="waveform mb-4" id="waveform">
<!-- Dynamic waveform bars will be inserted here by JS -->
</div>
<div class="flex justify-center space-x-6">
<button id="record-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white rounded-full p-4 shadow-lg transition-all">
<i class="fas fa-microphone text-2xl"></i>
</button>
<button id="stop-btn" class="bg-red-600 hover:bg-red-700 text-white rounded-full p-4 shadow-lg transition-all opacity-50 cursor-not-allowed">
<i class="fas fa-stop text-2xl"></i>
</button>
<button id="pause-btn" class="bg-yellow-500 hover:bg-yellow-600 text-white rounded-full p-4 shadow-lg transition-all opacity-50 cursor-not-allowed">
<i class="fas fa-pause text-2xl"></i>
</button>
</div>
<div class="mt-4 text-center text-sm text-gray-600">
<p id="recording-status">Ready to record meeting</p>
</div>
</div>
<!-- Transcription Section -->
<div class="bg-white border border-gray-200 rounded-lg p-4 mb-6">
<div class="flex justify-between items-center mb-3">
<h2 class="text-lg font-semibold text-gray-800">Live Transcription</h2>
<button id="copy-transcript" class="text-indigo-600 hover:text-indigo-800 text-sm font-medium">
<i class="fas fa-copy mr-1"></i> Copy
</button>
</div>
<div class="transcript-container bg-gray-50 p-3 rounded-lg mb-3" id="transcript-container">
<p id="transcript-text" class="text-gray-700">Transcription will appear here as you speak...</p>
</div>
<div class="flex justify-between text-xs text-gray-500">
<span id="word-count">0 words</span>
<span id="speaker-count">1 speaker</span>
</div>
</div>
<!-- Minutes Generation Section -->
<div class="bg-white border border-gray-200 rounded-lg p-4">
<div class="flex justify-between items-center mb-3">
<h2 class="text-lg font-semibold text-gray-800">Meeting Minutes</h2>
<button id="generate-minutes" class="bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-1 rounded text-sm font-medium">
<i class="fas fa-magic mr-1"></i> Generate
</button>
</div>
<div class="mb-3">
<label for="meeting-title" class="block text-sm font-medium text-gray-700 mb-1">Meeting Title</label>
<input type="text" id="meeting-title" class="w-full p-2 border border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500" placeholder="Weekly Team Sync">
</div>
<div class="mb-3">
<label for="attendees" class="block text-sm font-medium text-gray-700 mb-1">Attendees</label>
<input type="text" id="attendees" class="w-full p-2 border border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500" placeholder="John, Sarah, Mike">
</div>
<div class="bg-gray-50 p-3 rounded-lg min-h-40">
<div id="minutes-content" class="text-gray-700">
<p>Key discussion points, decisions, and action items will be summarized here...</p>
</div>
</div>
<div class="mt-3 flex justify-end space-x-2">
<button id="save-minutes" class="bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded text-sm font-medium">
<i class="fas fa-save mr-1"></i> Save
</button>
<button id="share-minutes" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-sm font-medium">
<i class="fas fa-share-alt mr-1"></i> Share
</button>
</div>
</div>
</main>
<!-- Bottom Navigation -->
<nav class="bg-white border-t border-gray-200 p-2">
<div class="flex justify-around">
<button class="p-2 text-indigo-600 rounded-full">
<i class="fas fa-home text-xl"></i>
</button>
<button class="p-2 text-gray-500 hover:text-indigo-600 rounded-full">
<i class="fas fa-history text-xl"></i>
</button>
<button class="p-2 text-gray-500 hover:text-indigo-600 rounded-full">
<i class="fas fa-folder text-xl"></i>
</button>
<button class="p-2 text-gray-500 hover:text-indigo-600 rounded-full">
<i class="fas fa-user text-xl"></i>
</button>
</div>
</nav>
</div>
<script>
// DOM Elements
const recordBtn = document.getElementById('record-btn');
const stopBtn = document.getElementById('stop-btn');
const pauseBtn = document.getElementById('pause-btn');
const recordingStatus = document.getElementById('recording-status');
const recordingTime = document.getElementById('recording-time');
const transcriptText = document.getElementById('transcript-text');
const wordCount = document.getElementById('word-count');
const speakerCount = document.getElementById('speaker-count');
const copyTranscript = document.getElementById('copy-transcript');
const generateMinutes = document.getElementById('generate-minutes');
const minutesContent = document.getElementById('minutes-content');
const saveMinutes = document.getElementById('save-minutes');
const shareMinutes = document.getElementById('share-minutes');
const waveform = document.getElementById('waveform');
// App State
let isRecording = false;
let isPaused = false;
let recordingStartTime;
let timerInterval;
let transcript = '';
let speakers = 1;
// Create waveform bars
for (let i = 0; i < 50; i++) {
const bar = document.createElement('div');
bar.className = 'waveform-bar';
bar.style.height = `${Math.random() * 10 + 5}px`;
waveform.appendChild(bar);
}
// Update waveform animation
function updateWaveform() {
const bars = document.querySelectorAll('.waveform-bar');
bars.forEach(bar => {
bar.style.height = `${Math.random() * 20 + 5}px`;
});
if (isRecording && !isPaused) {
requestAnimationFrame(updateWaveform);
}
}
// Update recording timer
function updateTimer() {
const now = new Date();
const elapsed = new Date(now - recordingStartTime);
const hours = elapsed.getUTCHours().toString().padStart(2, '0');
const minutes = elapsed.getUTCMinutes().toString().padStart(2, '0');
const seconds = elapsed.getUTCSeconds().toString().padStart(2, '0');
recordingTime.textContent = `${hours}:${minutes}:${seconds}`;
}
// Start recording
recordBtn.addEventListener('click', () => {
if (!isRecording) {
// Start recording
isRecording = true;
recordingStartTime = new Date();
recordBtn.innerHTML = '<i class="fas fa-microphone text-2xl pulse-animation"></i>';
recordBtn.classList.add('ring-4', 'ring-indigo-300');
stopBtn.classList.remove('opacity-50', 'cursor-not-allowed');
pauseBtn.classList.remove('opacity-50', 'cursor-not-allowed');
recordingStatus.textContent = 'Recording in progress...';
recordingStatus.classList.add('text-indigo-600');
// Start timer
timerInterval = setInterval(updateTimer, 1000);
// Start waveform animation
updateWaveform();
// Simulate transcription (in a real app, this would come from a speech-to-text API)
simulateTranscription();
}
});
// Stop recording
stopBtn.addEventListener('click', () => {
if (isRecording) {
// Stop recording
isRecording = false;
clearInterval(timerInterval);
recordBtn.innerHTML = '<i class="fas fa-microphone text-2xl"></i>';
recordBtn.classList.remove('ring-4', 'ring-indigo-300', 'pulse-animation');
stopBtn.classList.add('opacity-50', 'cursor-not-allowed');
pauseBtn.classList.add('opacity-50', 'cursor-not-allowed');
recordingStatus.textContent = 'Recording saved';
recordingStatus.classList.remove('text-indigo-600');
recordingStatus.classList.add('text-green-600');
// Reset waveform
const bars = document.querySelectorAll('.waveform-bar');
bars.forEach(bar => {
bar.style.height = '5px';
});
}
});
// Pause/resume recording
pauseBtn.addEventListener('click', () => {
if (isRecording) {
if (isPaused) {
// Resume recording
isPaused = false;
pauseBtn.innerHTML = '<i class="fas fa-pause text-2xl"></i>';
pauseBtn.classList.remove('bg-gray-500');
pauseBtn.classList.add('bg-yellow-500');
recordingStatus.textContent = 'Recording in progress...';
recordingStatus.classList.add('text-indigo-600');
recordingStartTime = new Date(new Date() - (new Date() - recordingStartTime));
timerInterval = setInterval(updateTimer, 1000);
updateWaveform();
} else {
// Pause recording
isPaused = true;
clearInterval(timerInterval);
pauseBtn.innerHTML = '<i class="fas fa-play text-2xl"></i>';
pauseBtn.classList.remove('bg-yellow-500');
pauseBtn.classList.add('bg-gray-500');
recordingStatus.textContent = 'Recording paused';
recordingStatus.classList.remove('text-indigo-600');
recordingStatus.classList.add('text-gray-600');
}
}
});
// Simulate transcription (in a real app, this would use Web Speech API or a service like Google Speech-to-Text)
function simulateTranscription() {
if (!isRecording || isPaused) return;
// Sample meeting phrases
const phrases = [
"Let's start with the project updates.",
"The design phase is 80% complete.",
"We need to address the budget concerns.",
"The deadline has been moved to next Friday.",
"Action item: John will follow up with the client.",
"Sarah mentioned the API integration is delayed.",
"Decision: We'll proceed with option B.",
"Mike raised concerns about the timeline.",
"Next steps: Finalize the requirements document.",
"The team agreed on the new feature priorities."
];
// Randomly select a phrase
const phrase = phrases[Math.floor(Math.random() * phrases.length)];
// Sometimes detect a new speaker (randomly)
if (Math.random() > 0.7) {
speakers++;
speakerCount.textContent = `${speakers} speakers`;
transcript += `\n\nSpeaker ${speakers}: ${phrase}`;
} else {
transcript += ` ${phrase}`;
}
// Update UI
transcriptText.textContent = transcript;
wordCount.textContent = `${transcript.split(/\s+/).length} words`;
// Continue simulating until recording stops
if (isRecording && !isPaused) {
setTimeout(simulateTranscription, Math.random() * 3000 + 1000);
}
}
// Copy transcript to clipboard
copyTranscript.addEventListener('click', () => {
navigator.clipboard.writeText(transcript).then(() => {
const originalText = copyTranscript.innerHTML;
copyTranscript.innerHTML = '<i class="fas fa-check mr-1"></i> Copied!';
setTimeout(() => {
copyTranscript.innerHTML = originalText;
}, 2000);
});
});
// Generate meeting minutes
generateMinutes.addEventListener('click', () => {
if (!transcript.trim()) {
minutesContent.innerHTML = '<p class="text-red-500">No transcription available to generate minutes.</p>';
return;
}
// Simulate AI processing
minutesContent.innerHTML = '<div class="flex items-center justify-center py-4"><i class="fas fa-spinner fa-spin text-indigo-600 text-2xl mr-2"></i><span>Generating minutes...</span></div>';
// Simulate API call delay
setTimeout(() => {
// This would be replaced with actual AI processing in a real app
const summary = `
<h3 class="font-bold text-lg mb-2">Meeting Summary</h3>
<ul class="list-disc pl-5 mb-4 space-y-1">
<li>Project updates were shared with the team</li>
<li>Design phase is nearing completion</li>
<li>Budget concerns need to be addressed</li>
<li>Deadline adjusted to next Friday</li>
</ul>
<h3 class="font-bold text-lg mb-2">Key Decisions</h3>
<ul class="list-disc pl-5 mb-4 space-y-1">
<li>Proceeding with option B for the new feature</li>
<li>Revised timeline approved by the team</li>
</ul>
<h3 class="font-bold text-lg mb-2">Action Items</h3>
<ol class="list-decimal pl-5 space-y-1">
<li><strong>John:</strong> Follow up with client about requirements</li>
<li><strong>Sarah:</strong> Resolve API integration issues</li>
<li><strong>Mike:</strong> Update project timeline document</li>
</ol>
`;
minutesContent.innerHTML = summary;
}, 2000);
});
// Save minutes
saveMinutes.addEventListener('click', () => {
const title = document.getElementById('meeting-title').value || 'Untitled Meeting';
const attendees = document.getElementById('attendees').value || 'Not specified';
// In a real app, this would save to a database or local storage
alert(`Minutes saved for "${title}" with attendees: ${attendees}`);
});
// Share minutes
shareMinutes.addEventListener('click', () => {
// In a real app, this would use the Web Share API or other sharing methods
alert('Sharing functionality would be implemented here');
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=naresh10/myexperiments" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>