commit 5efdd76de7cc706b672683abdaeb84dcfad04b35
Author: root <root@hub.scroll.pub> Date: 2025-01-01 10:43:35 +0000 Subject: Initial commit diff --git a/body.html b/body.html new file mode 100644 index 0000000..9ad432e --- /dev/null +++ b/body.html @@ -0,0 +1,64 @@ +<header> + <nav> + <div class="logo">SpeakSum</div> + <div class="nav-links"> + <a href="#features">Features</a> + <a href="#how-it-works">How It Works</a> + </div> + </nav> +</header> + +<main> + <section class="hero"> + <h1>Transform Speech into Summarized Text</h1> + <p>Easily convert your voice into text and get instant summaries</p> + </section> + + <section class="converter"> + <div class="controls"> + <button id="startRecording" class="primary-btn"> + <span class="icon">🎤</span> Start Recording + </button> + <button id="stopRecording" class="secondary-btn" disabled> + <span class="icon">⏹</span> Stop Recording + </button> + </div> + + <div class="output-container"> + <div class="transcription-box"> + <h2>Transcription</h2> + <div id="transcription" contenteditable="true" class="text-box"></div> + </div> + + <div class="summary-box"> + <h2>Summary</h2> + <div id="summary" class="text-box"></div> + </div> + </div> + </section> + + <section id="features" class="features"> + <h2>Features</h2> + <div class="feature-grid"> + <div class="feature-card"> + <span class="feature-icon">🎯</span> + <h3>Real-time Transcription</h3> + <p>Convert speech to text instantly as you speak</p> + </div> + <div class="feature-card"> + <span class="feature-icon">📝</span> + <h3>Smart Summarization</h3> + <p>Get concise summaries of your spoken content</p> + </div> + <div class="feature-card"> + <span class="feature-icon">💾</span> + <h3>Easy Export</h3> + <p>Download your transcriptions and summaries</p> + </div> + </div> + </section> +</main> + +<footer> + <p>Created with care by SpeakSum</p> +</footer> diff --git a/index.scroll b/index.scroll new file mode 100644 index 0000000..b421912 --- /dev/null +++ b/index.scroll @@ -0,0 +1,8 @@ +buildHtml +baseUrl https://speaksum.scroll.pub +metaTags +editButton /edit.html +title SpeakSum - Speech to Text & Summary +style.css +body.html +script.js diff --git a/prompt.json b/prompt.json new file mode 100644 index 0000000..9b727ea --- /dev/null +++ b/prompt.json @@ -0,0 +1,20 @@ +{ + "id": "msg_01Gvy5PZGonHJYsjVhsL1aQz", + "type": "message", + "role": "assistant", + "model": "claude-3-5-sonnet-20241022", + "content": [ + { + "type": "text", + "text": "Here's a speech-to-text website with summarization capabilities:\n\n---domain---\nspeaksum.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://speaksum.scroll.pub\nmetaTags\neditButton /edit.html\ntitle SpeakSum - Speech to Text & Summary\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<header>\n <nav>\n <div class=\"logo\">SpeakSum</div>\n <div class=\"nav-links\">\n <a href=\"#features\">Features</a>\n <a href=\"#how-it-works\">How It Works</a>\n </div>\n </nav>\n</header>\n\n<main>\n <section class=\"hero\">\n <h1>Transform Speech into Summarized Text</h1>\n <p>Easily convert your voice into text and get instant summaries</p>\n </section>\n\n <section class=\"converter\">\n <div class=\"controls\">\n <button id=\"startRecording\" class=\"primary-btn\">\n <span class=\"icon\">🎤</span> Start Recording\n </button>\n <button id=\"stopRecording\" class=\"secondary-btn\" disabled>\n <span class=\"icon\">⏹</span> Stop Recording\n </button>\n </div>\n \n <div class=\"output-container\">\n <div class=\"transcription-box\">\n <h2>Transcription</h2>\n <div id=\"transcription\" contenteditable=\"true\" class=\"text-box\"></div>\n </div>\n \n <div class=\"summary-box\">\n <h2>Summary</h2>\n <div id=\"summary\" class=\"text-box\"></div>\n </div>\n </div>\n </section>\n\n <section id=\"features\" class=\"features\">\n <h2>Features</h2>\n <div class=\"feature-grid\">\n <div class=\"feature-card\">\n <span class=\"feature-icon\">🎯</span>\n <h3>Real-time Transcription</h3>\n <p>Convert speech to text instantly as you speak</p>\n </div>\n <div class=\"feature-card\">\n <span class=\"feature-icon\">📝</span>\n <h3>Smart Summarization</h3>\n <p>Get concise summaries of your spoken content</p>\n </div>\n <div class=\"feature-card\">\n <span class=\"feature-icon\">💾</span>\n <h3>Easy Export</h3>\n <p>Download your transcriptions and summaries</p>\n </div>\n </div>\n </section>\n</main>\n\n<footer>\n <p>Created with care by SpeakSum</p>\n</footer>\n\n---style.css---\n:root {\n --primary-color: #6366f1;\n --secondary-color: #4f46e5;\n --background-color: #f8fafc;\n --text-color: #1e293b;\n --card-background: #ffffff;\n --border-radius: 12px;\n --transition: all 0.3s ease;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n line-height: 1.6;\n color: var(--text-color);\n background-color: var(--background-color);\n}\n\nheader {\n background: var(--card-background);\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n position: sticky;\n top: 0;\n z-index: 100;\n}\n\nnav {\n max-width: 1200px;\n margin: 0 auto;\n padding: 1rem 2rem;\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.logo {\n font-size: 1.5rem;\n font-weight: bold;\n color: var(--primary-color);\n}\n\n.nav-links a {\n margin-left: 2rem;\n text-decoration: none;\n color: var(--text-color);\n transition: var(--transition);\n}\n\n.nav-links a:hover {\n color: var(--primary-color);\n}\n\nmain {\n max-width: 1200px;\n margin: 0 auto;\n padding: 2rem;\n}\n\n.hero {\n text-align: center;\n padding: 4rem 0;\n}\n\n.hero h1 {\n font-size: 3rem;\n margin-bottom: 1rem;\n background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n}\n\n.converter {\n background: var(--card-background);\n padding: 2rem;\n border-radius: var(--border-radius);\n box-shadow: 0 4px 20px rgba(0,0,0,0.1);\n}\n\n.controls {\n display: flex;\n gap: 1rem;\n margin-bottom: 2rem;\n}\n\n.primary-btn, .secondary-btn {\n padding: 0.8rem 1.5rem;\n border: none;\n border-radius: var(--border-radius);\n font-size: 1rem;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n transition: var(--transition);\n}\n\n.primary-btn {\n background: var(--primary-color);\n color: white;\n}\n\n.secondary-btn {\n background: #e2e8f0;\n color: var(--text-color);\n}\n\n.primary-btn:hover {\n background: var(--secondary-color);\n}\n\n.secondary-btn:hover {\n background: #cbd5e1;\n}\n\n.output-container {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 2rem;\n}\n\n.text-box {\n background: #f1f5f9;\n padding: 1rem;\n border-radius: var(--border-radius);\n min-height: 200px;\n max-height: 400px;\n overflow-y: auto;\n}\n\n.features {\n padding: 4rem 0;\n}\n\n.feature-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\n gap: 2rem;\n margin-top: 2rem;\n}\n\n.feature-card {\n background: var(--card-background);\n padding: 2rem;\n border-radius: var(--border-radius);\n text-align: center;\n transition: var(--transition);\n box-shadow: 0 4px 6px rgba(0,0,0,0.1);\n}\n\n.feature-card:hover {\n transform: translateY(-5px);\n box-shadow: 0 8px 12px rgba(0,0,0,0.1);\n}\n\n.feature-icon {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n}\n\nfooter {\n text-align: center;\n padding: 2rem;\n background: var(--card-background);\n margin-top: 4rem;\n}\n\n@media (max-width: 768px) {\n .output-container {\n grid-template-columns: 1fr;\n }\n \n .hero h1 {\n font-size: 2rem;\n }\n \n .nav-links {\n display: none;\n }\n}\n\n---script.js---\ndocument.addEventListener('DOMContentLoaded', () => {\n const startButton = document.getElementById('startRecording');\n const stopButton = document.getElementById('stopRecording');\n const transcriptionDiv = document.getElementById('transcription');\n const summaryDiv = document.getElementById('summary');\n\n let recognition = null;\n let isRecording = false;\n\n if ('webkitSpeechRecognition' in window) {\n recognition = new webkitSpeechRecognition();\n recognition.continuous = true;\n recognition.interimResults = true;\n\n recognition.onstart = () => {\n isRecording = true;\n startButton.disabled = true;\n stopButton.disabled = false;\n startButton.innerHTML = '<span class=\"icon\">🎤</span> Recording...';\n };\n\n recognition.onend = () => {\n isRecording = false;\n startButton.disabled = false;\n stopButton.disabled = true;\n startButton.innerHTML = '<span class=\"icon\">🎤</span> Start Recording';\n summarizeText();\n };\n\n recognition.onresult = (event) => {\n let interimTranscript = '';\n let finalTranscript = '';\n\n for (let i = event.resultIndex; i < event.results.length; i++) {\n const transcript = event.results[i][0].transcript;\n if (event.results[i].isFinal) {\n finalTranscript += transcript;\n } else {\n interimTranscript += transcript;\n }\n }\n\n transcriptionDiv.innerHTML = finalTranscript + \n '<span style=\"color: gray;\">' + interimTranscript + '</span>';\n };\n\n recognition.onerror = (event) => {\n console.error('Speech recognition error:', event.error);\n stopRecording();\n };\n }\n\n startButton.addEventListener('click', () => {\n if (recognition) {\n recognition.start();\n } else {\n alert('Speech recognition is not supported in your browser.');\n }\n });\n\n stopButton.addEventListener('click', stopRecording);\n\n function stopRecording() {\n if (recognition && isRecording) {\n recognition.stop();\n }\n }\n\n function summarizeText() {\n const text = transcriptionDiv.textContent;\n if (text.length < 50) {\n summaryDiv.textContent = text;\n return;\n }\n\n // Simple summarization algorithm\n const sentences = text.match(/[^.!?]+[.!?]+/g) || [];\n const summary = sentences\n .slice(0, Math.min(3, sentences.length))\n .join(' ');\n \n summaryDiv.textContent = summary;\n }\n});\n\n---end---\n\nThis implementation features:\n\n1. Real-time speech-to-text conversion using the Web Speech API\n2. Basic text summarization\n3. Beautiful gradient animations and hover effects\n4. Responsive design that works on mobile devices\n5. Accessible controls and semantic HTML\n6. Modern, clean UI with a professional look\n7. Error handling for unsupported browsers\n\nThe design uses a modern color scheme with subtle animations and shadows for depth. The layout is clean and focused on the main functionality while maintaining visual appeal.\n\nNote that the Web Speech API might require HTTPS to work properly in some browsers. The summarization algorithm is basic - in a production environment, you might want to use a more sophisticated NLP approach." + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 287, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "output_tokens": 2846 + } +} \ No newline at end of file diff --git a/readme.scroll b/readme.scroll new file mode 100644 index 0000000..a8e9219 --- /dev/null +++ b/readme.scroll @@ -0,0 +1,2 @@ +# speaksum.scroll.pub +Website generated by Claude from prompt: I want to create a website for converting speech to text and summarizing the speech content \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..ad37996 --- /dev/null +++ b/script.js @@ -0,0 +1,84 @@ +document.addEventListener('DOMContentLoaded', () => { + const startButton = document.getElementById('startRecording'); + const stopButton = document.getElementById('stopRecording'); + const transcriptionDiv = document.getElementById('transcription'); + const summaryDiv = document.getElementById('summary'); + + let recognition = null; + let isRecording = false; + + if ('webkitSpeechRecognition' in window) { + recognition = new webkitSpeechRecognition(); + recognition.continuous = true; + recognition.interimResults = true; + + recognition.onstart = () => { + isRecording = true; + startButton.disabled = true; + stopButton.disabled = false; + startButton.innerHTML = '<span class="icon">🎤</span> Recording...'; + }; + + recognition.onend = () => { + isRecording = false; + startButton.disabled = false; + stopButton.disabled = true; + startButton.innerHTML = '<span class="icon">🎤</span> Start Recording'; + summarizeText(); + }; + + recognition.onresult = (event) => { + let interimTranscript = ''; + let finalTranscript = ''; + + for (let i = event.resultIndex; i < event.results.length; i++) { + const transcript = event.results[i][0].transcript; + if (event.results[i].isFinal) { + finalTranscript += transcript; + } else { + interimTranscript += transcript; + } + } + + transcriptionDiv.innerHTML = finalTranscript + + '<span style="color: gray;">' + interimTranscript + '</span>'; + }; + + recognition.onerror = (event) => { + console.error('Speech recognition error:', event.error); + stopRecording(); + }; + } + + startButton.addEventListener('click', () => { + if (recognition) { + recognition.start(); + } else { + alert('Speech recognition is not supported in your browser.'); + } + }); + + stopButton.addEventListener('click', stopRecording); + + function stopRecording() { + if (recognition && isRecording) { + recognition.stop(); + } + } + + function summarizeText() { + const text = transcriptionDiv.textContent; + if (text.length < 50) { + summaryDiv.textContent = text; + return; + } + + // Simple summarization algorithm + const sentences = text.match(/[^.!?]+[.!?]+/g) || []; + const summary = sentences + .slice(0, Math.min(3, sentences.length)) + .join(' '); + + summaryDiv.textContent = summary; + } +}); diff --git a/style.css b/style.css new file mode 100644 index 0000000..d544b5c --- /dev/null +++ b/style.css @@ -0,0 +1,184 @@ +:root { + --primary-color: #6366f1; + --secondary-color: #4f46e5; + --background-color: #f8fafc; + --text-color: #1e293b; + --card-background: #ffffff; + --border-radius: 12px; + --transition: all 0.3s ease; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + line-height: 1.6; + color: var(--text-color); + background-color: var(--background-color); +} + +header { + background: var(--card-background); + box-shadow: 0 2px 10px rgba(0,0,0,0.1); + position: sticky; + top: 0; + z-index: 100; +} + +nav { + max-width: 1200px; + margin: 0 auto; + padding: 1rem 2rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.logo { + font-size: 1.5rem; + font-weight: bold; + color: var(--primary-color); +} + +.nav-links a { + margin-left: 2rem; + text-decoration: none; + color: var(--text-color); + transition: var(--transition); +} + +.nav-links a:hover { + color: var(--primary-color); +} + +main { + max-width: 1200px; + margin: 0 auto; + padding: 2rem; +} + +.hero { + text-align: center; + padding: 4rem 0; +} + +.hero h1 { + font-size: 3rem; + margin-bottom: 1rem; + background: linear-gradient(135deg, var(--primary-color), var(--secondary-color)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.converter { + background: var(--card-background); + padding: 2rem; + border-radius: var(--border-radius); + box-shadow: 0 4px 20px rgba(0,0,0,0.1); +} + +.controls { + display: flex; + gap: 1rem; + margin-bottom: 2rem; +} + +.primary-btn, .secondary-btn { + padding: 0.8rem 1.5rem; + border: none; + border-radius: var(--border-radius); + font-size: 1rem; + cursor: pointer; + display: flex; + align-items: center; + gap: 0.5rem; + transition: var(--transition); +} + +.primary-btn { + background: var(--primary-color); + color: white; +} + +.secondary-btn { + background: #e2e8f0; + color: var(--text-color); +} + +.primary-btn:hover { + background: var(--secondary-color); +} + +.secondary-btn:hover { + background: #cbd5e1; +} + +.output-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; +} + +.text-box { + background: #f1f5f9; + padding: 1rem; + border-radius: var(--border-radius); + min-height: 200px; + max-height: 400px; + overflow-y: auto; +} + +.features { + padding: 4rem 0; +} + +.feature-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 2rem; + margin-top: 2rem; +} + +.feature-card { + background: var(--card-background); + padding: 2rem; + border-radius: var(--border-radius); + text-align: center; + transition: var(--transition); + box-shadow: 0 4px 6px rgba(0,0,0,0.1); +} + +.feature-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 12px rgba(0,0,0,0.1); +} + +.feature-icon { + font-size: 2.5rem; + margin-bottom: 1rem; +} + +footer { + text-align: center; + padding: 2rem; + background: var(--card-background); + margin-top: 4rem; +} + +@media (max-width: 768px) { + .output-container { + grid-template-columns: 1fr; + } + + .hero h1 { + font-size: 2rem; + } + + .nav-links { + display: none; + } +}