v15.1: CRITICAL FIX - TTS Preview + Browser Whisper actually working now
ROOT CAUSES FOUND AND FIXED: 1. TTS Preview not working: voicePreferences.js listening for wrong event - Was: 'tab-loaded' (never dispatched) - Now: 'tabChanged' (correct event name used by app.js) - Added immediate init if page already loaded - Added 500ms delay for DOM readiness 2. Browser Whisper CDN blocked: CSP too restrictive - Added 'unsafe-eval' to scriptSrc (required by transformers.js) - Added cdn.jsdelivr.net to connectSrc (worker importScripts) - Added childSrc directive for worker script loading - Better error messages in worker 3. Worker loading errors: Now logged with specific reasons - importScripts wrapped in try-catch - Posts error message to main thread - Verifies transformers object exists after load Testing: - TTS Preview should now work when clicking Settings tab - Browser Whisper should load from CDN (or show specific error) - Console logs will show exact init sequence
This commit is contained in:
parent
ee3729eb57
commit
88036a45c4
3 changed files with 45 additions and 9 deletions
|
|
@ -5,24 +5,37 @@
|
|||
(function() {
|
||||
var _inited = false;
|
||||
|
||||
window.addEventListener('tab-loaded', function(e) {
|
||||
// Listen for tab changes (correct event name is 'tabChanged' not 'tab-loaded')
|
||||
document.addEventListener('tabChanged', function(e) {
|
||||
if (e.detail.tab !== 'settings' || _inited) return;
|
||||
_inited = true;
|
||||
console.log('[VoicePrefs] Initializing...');
|
||||
initVoicePreferences();
|
||||
console.log('[VoicePrefs] Initializing on settings tab load...');
|
||||
// Small delay to ensure DOM is ready
|
||||
setTimeout(function() {
|
||||
initVoicePreferences();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// Also init on DOMContentLoaded as backup
|
||||
// Also init on DOMContentLoaded as backup for direct page load
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setTimeout(function() {
|
||||
if (!_inited && document.getElementById('btn-preview-voice')) {
|
||||
console.log('[VoicePrefs] Init via DOMContentLoaded');
|
||||
console.log('[VoicePrefs] Init via DOMContentLoaded (direct settings page load)');
|
||||
_inited = true;
|
||||
initVoicePreferences();
|
||||
}
|
||||
}, 1000);
|
||||
}, 500);
|
||||
});
|
||||
} else {
|
||||
// Page already loaded, init immediately if on settings
|
||||
setTimeout(function() {
|
||||
if (!_inited && document.getElementById('btn-preview-voice')) {
|
||||
console.log('[VoicePrefs] Init immediate (page already loaded)');
|
||||
_inited = true;
|
||||
initVoicePreferences();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function initVoicePreferences() {
|
||||
|
|
|
|||
|
|
@ -3,11 +3,29 @@
|
|||
// Audio never leaves the device. Model cached in IndexedDB.
|
||||
// ============================================================
|
||||
|
||||
importScripts('https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.2');
|
||||
console.log('[WhisperWorker] Starting worker initialization');
|
||||
console.log('[WhisperWorker] Attempting to load transformers from CDN...');
|
||||
|
||||
try {
|
||||
importScripts('https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.2');
|
||||
console.log('[WhisperWorker] Transformers library loaded successfully');
|
||||
} catch (err) {
|
||||
console.error('[WhisperWorker] Failed to load transformers library:', err);
|
||||
self.postMessage({
|
||||
type: 'error',
|
||||
message: 'Failed to load transformers library. Check network/firewall: ' + err.message
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
|
||||
var T = self.transformers || transformers;
|
||||
if (!T) {
|
||||
console.error('[WhisperWorker] Transformers object not found after import');
|
||||
throw new Error('Transformers library did not initialize');
|
||||
}
|
||||
T.env.allowLocalModels = false;
|
||||
T.env.useBrowserCache = true;
|
||||
console.log('[WhisperWorker] Transformers configured');
|
||||
|
||||
var _pipe = null;
|
||||
var _loadedModel = null;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ app.use(helmet({
|
|||
defaultSrc: ["'self'"],
|
||||
// 'wasm-unsafe-eval' required for WebAssembly (Whisper in-browser transcription)
|
||||
// cdn.jsdelivr.net required for @xenova/transformers worker script
|
||||
scriptSrc: ["'self'", "'wasm-unsafe-eval'", 'https://cdn.jsdelivr.net'],
|
||||
// 'unsafe-eval' needed for transformers.js dynamic imports in worker
|
||||
scriptSrc: ["'self'", "'wasm-unsafe-eval'", "'unsafe-eval'", 'https://cdn.jsdelivr.net'],
|
||||
scriptSrcAttr: ["'none'"],
|
||||
styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com', 'https://cdnjs.cloudflare.com'],
|
||||
fontSrc: ["'self'", 'https://fonts.gstatic.com', 'https://cdnjs.cloudflare.com'],
|
||||
|
|
@ -29,8 +30,12 @@ app.use(helmet({
|
|||
mediaSrc: ["'self'", 'blob:'],
|
||||
connectSrc: ["'self'", 'https://cdnjs.cloudflare.com', 'https://fonts.googleapis.com', 'https://fonts.gstatic.com', 'https://www.google.com', 'wss://www.google.com', 'https://clinicaltables.nlm.nih.gov',
|
||||
// HuggingFace CDN for Whisper model downloads
|
||||
'https://huggingface.co', 'https://cdn-lfs.huggingface.co', 'https://cdn-lfs-us-1.huggingface.co', 'https://cdn-lfs-us-2.huggingface.co'],
|
||||
'https://huggingface.co', 'https://cdn-lfs.huggingface.co', 'https://cdn-lfs-us-1.huggingface.co', 'https://cdn-lfs-us-2.huggingface.co',
|
||||
// jsdelivr for worker importScripts
|
||||
'https://cdn.jsdelivr.net'],
|
||||
workerSrc: ["'self'", 'blob:'],
|
||||
// Allow workers to load scripts from jsdelivr
|
||||
childSrc: ["'self'", 'blob:', 'https://cdn.jsdelivr.net'],
|
||||
frameSrc: ["'none'"],
|
||||
objectSrc: ["'none'"],
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue