109 lines
3.3 KiB
JavaScript
109 lines
3.3 KiB
JavaScript
// offscreen.js - Handles webkitSpeechRecognition in isolation
|
|
|
|
let recognition = null;
|
|
let isRecording = false;
|
|
|
|
// Initialize recognition early if possible, or wait until start
|
|
function initRecognition(language) {
|
|
if (recognition) return recognition;
|
|
|
|
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
|
if (!SpeechRecognition) {
|
|
throw new Error('Speech recognition not supported');
|
|
}
|
|
|
|
recognition = new SpeechRecognition();
|
|
recognition.continuous = true;
|
|
recognition.interimResults = true;
|
|
recognition.lang = language || 'ar-SA';
|
|
recognition.maxAlternatives = 1;
|
|
|
|
recognition.onresult = (event) => {
|
|
let interimText = '';
|
|
let finalText = '';
|
|
|
|
for (let i = event.resultIndex; i < event.results.length; i++) {
|
|
const result = event.results[i];
|
|
if (result.isFinal) {
|
|
finalText += result[0].transcript + ' ';
|
|
} else {
|
|
interimText += result[0].transcript;
|
|
}
|
|
}
|
|
|
|
// Send results back to background script
|
|
chrome.runtime.sendMessage({
|
|
type: 'OFFSCREEN_RECORDING_RESULT',
|
|
payload: { interimText, finalText }
|
|
});
|
|
};
|
|
|
|
recognition.onerror = (event) => {
|
|
console.error('[Offscreen] Recognition error:', event.error);
|
|
|
|
// Prevent infinite restart loop on fatal errors
|
|
if (event.error !== 'no-speech') {
|
|
isRecording = false;
|
|
}
|
|
|
|
chrome.runtime.sendMessage({
|
|
type: 'OFFSCREEN_RECORDING_ERROR',
|
|
payload: { error: event.error }
|
|
});
|
|
};
|
|
|
|
recognition.onend = () => {
|
|
// If we still want to be recording, restart
|
|
if (isRecording) {
|
|
try {
|
|
recognition.start();
|
|
} catch (e) {
|
|
console.warn('[Offscreen] Restart failed:', e);
|
|
}
|
|
} else {
|
|
chrome.runtime.sendMessage({ type: 'OFFSCREEN_RECORDING_END' });
|
|
}
|
|
};
|
|
|
|
return recognition;
|
|
}
|
|
|
|
// Listen for messages from background script
|
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
if (message.type === 'START_RECORDING') {
|
|
try {
|
|
const lang = message.payload?.language || 'ar-SA';
|
|
|
|
// Re-init if language changed or not init yet
|
|
if (!recognition || recognition.lang !== lang) {
|
|
recognition = initRecognition(lang);
|
|
}
|
|
|
|
if (!isRecording) {
|
|
recognition.start();
|
|
isRecording = true;
|
|
sendResponse({ success: true });
|
|
} else {
|
|
sendResponse({ success: true, warning: 'Already recording' });
|
|
}
|
|
} catch (e) {
|
|
console.error('[Offscreen] Failed to start:', e);
|
|
sendResponse({ success: false, error: e.message });
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (message.type === 'STOP_RECORDING') {
|
|
if (isRecording && recognition) {
|
|
isRecording = false;
|
|
try {
|
|
recognition.stop();
|
|
} catch (e) {
|
|
console.warn('[Offscreen] Stop failed:', e);
|
|
}
|
|
}
|
|
sendResponse({ success: true });
|
|
return true;
|
|
}
|
|
});
|