awacke1's picture
Create mycomponent/index.html
676cc2e verified
raw
history blame
6.32 kB
<!DOCTYPE html>
<html>
<head>
<style>
.speech-container {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
padding: 20px;
border-radius: 10px;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.controls {
display: flex;
gap: 10px;
margin-bottom: 15px;
}
button {
padding: 8px 16px;
border-radius: 5px;
border: none;
background: #2196F3;
color: white;
cursor: pointer;
transition: background 0.3s;
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
button:hover:not(:disabled) {
background: #1976D2;
}
#status {
margin: 10px 0;
padding: 10px;
border-radius: 5px;
background: #E3F2FD;
}
#output {
margin-top: 15px;
padding: 15px;
border-radius: 5px;
background: #F5F5F5;
min-height: 100px;
max-height: 300px;
overflow-y: auto;
white-space: pre-wrap;
}
</style>
</head>
<body>
<div class="speech-container">
<div class="controls">
<button id="start">Start Listening</button>
<button id="stop" disabled>Stop</button>
<button id="clear">Clear</button>
</div>
<div id="status">Ready</div>
<div id="output"></div>
</div>
<script>
// Streamlit Component Initialization
function sendMessageToStreamlit(type, data) {
const outData = Object.assign({
isStreamlitMessage: true,
type: type,
}, data);
window.parent.postMessage(outData, "*");
}
function init() {
sendMessageToStreamlit("streamlit:componentReady", {apiVersion: 1});
}
function setFrameHeight(height) {
sendMessageToStreamlit("streamlit:setFrameHeight", {height: height});
}
function sendDataToStreamlit(data) {
sendMessageToStreamlit("streamlit:setComponentValue", data);
}
// Speech Recognition Setup
if (!('webkitSpeechRecognition' in window)) {
document.getElementById('status').textContent = 'Speech recognition not supported';
} else {
const recognition = new webkitSpeechRecognition();
const startButton = document.getElementById('start');
const stopButton = document.getElementById('stop');
const clearButton = document.getElementById('clear');
const status = document.getElementById('status');
const output = document.getElementById('output');
let fullTranscript = '';
let lastUpdate = Date.now();
recognition.continuous = true;
recognition.interimResults = true;
startButton.onclick = () => {
try {
recognition.start();
status.textContent = 'Listening...';
startButton.disabled = true;
stopButton.disabled = false;
} catch (e) {
console.error('Recognition error:', e);
status.textContent = 'Error: ' + e.message;
}
};
stopButton.onclick = () => {
recognition.stop();
status.textContent = 'Stopped';
startButton.disabled = false;
stopButton.disabled = true;
};
clearButton.onclick = () => {
fullTranscript = '';
output.textContent = '';
sendDataToStreamlit({
value: '',
dataType: "json",
});
};
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 + '\n';
} else {
interimTranscript += transcript;
}
}
if (finalTranscript || (Date.now() - lastUpdate > 3000)) {
if (finalTranscript) {
fullTranscript += finalTranscript;
sendDataToStreamlit({
value: fullTranscript,
dataType: "json",
});
}
lastUpdate = Date.now();
}
output.textContent = fullTranscript + (interimTranscript ? '... ' + interimTranscript : '');
output.scrollTop = output.scrollHeight;
};
recognition.onend = () => {
if (!stopButton.disabled) {
try {
recognition.start();
} catch (e) {
console.error('Failed to restart recognition:', e);
status.textContent = 'Error restarting: ' + e.message;
startButton.disabled = false;
stopButton.disabled = true;
}
}
};
recognition.onerror = (event) => {
console.error('Recognition error:', event.error);
status.textContent = 'Error: ' + event.error;
if (event.error === 'not-allowed') {
startButton.disabled = false;
stopButton.disabled = true;
}
};
}
// Initialize component
init();
// Set initial height
window.addEventListener("load", () => {
setFrameHeight(document.documentElement.scrollHeight);
});
</script>
</body>
</html>