Skip to content

Commit 34b2242

Browse files
Merge remote-tracking branch 'origin/main' into smonga/wispr_flow_clone
2 parents 51fd218 + 39f4865 commit 34b2242

61 files changed

Lines changed: 3958 additions & 610 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Binary file not shown.

examples/react-native/RunAnywhereAI/yarn.lock

Lines changed: 162 additions & 262 deletions
Large diffs are not rendered by default.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
.vercel
22
.env*.local
3+
4+
# Emscripten test compile outputs
5+
a.out.js
6+
a.out.wasm

examples/web/RunAnywhereAI/src/main.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,12 @@ async function initializeSDK(): Promise<void> {
118118

119119
console.log(
120120
'[RunAnywhere] SDK initialized, version:', RunAnywhere.version,
121-
'| acceleration:', RunAnywhere.accelerationMode,
121+
'| acceleration:', LlamaCPP.accelerationMode,
122122
'| local storage:', localRestored ? RunAnywhere.localStorageDirectoryName : 'OPFS',
123123
);
124124

125125
// Show an acceleration badge so the user knows which backend is active
126-
showAccelerationBadge(RunAnywhere.accelerationMode);
126+
showAccelerationBadge(LlamaCPP.accelerationMode);
127127
} catch (err) {
128128
// SDK not built or WASM not available -- continue in demo mode
129129
console.warn('[RunAnywhere] SDK not available, running in demo mode:', err);

examples/web/RunAnywhereAI/src/styles/components.css

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,6 +1682,44 @@ input[type="range"]::-webkit-slider-thumb {
16821682
height: 72px;
16831683
}
16841684

1685+
/** Drag-and-drop file zone for STT */
1686+
.stt-drop-zone {
1687+
border: 2px dashed var(--border-color);
1688+
border-radius: 12px;
1689+
padding: 18px 16px;
1690+
text-align: center;
1691+
cursor: pointer;
1692+
transition: border-color 0.2s, background 0.2s, color 0.2s;
1693+
margin-top: 16px;
1694+
color: var(--text-tertiary);
1695+
font-size: 13px;
1696+
line-height: 1.5;
1697+
user-select: none;
1698+
}
1699+
1700+
.stt-drop-zone:hover,
1701+
.stt-drop-zone.drag-over {
1702+
border-color: var(--color-blue);
1703+
background: rgba(59, 130, 246, 0.06);
1704+
color: var(--color-blue);
1705+
}
1706+
1707+
.stt-drop-zone-icon {
1708+
font-size: 22px;
1709+
margin-bottom: 4px;
1710+
}
1711+
1712+
.stt-drop-zone-label {
1713+
font-weight: 500;
1714+
font-size: 13px;
1715+
}
1716+
1717+
.stt-drop-zone-hint {
1718+
font-size: 11px;
1719+
opacity: 0.7;
1720+
margin-top: 2px;
1721+
}
1722+
16851723
/* =============================================================================
16861724
* TTS (Speak) Sub-view Specifics
16871725
* ============================================================================= */

examples/web/RunAnywhereAI/src/views/transcribe.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ export function initTranscribeTab(el: HTMLElement): TabLifecycle {
7777
</div>
7878
<h3 class="font-semibold">Ready to transcribe</h3>
7979
<p id="stt-mode-desc" class="helper-text text-center">Record first, then transcribe</p>
80+
81+
<!-- File drop zone — visible in batch mode only -->
82+
<div id="stt-drop-zone" class="stt-drop-zone">
83+
<div class="stt-drop-zone-icon">📂</div>
84+
<div class="stt-drop-zone-label">Drop audio file or click to browse</div>
85+
<div class="stt-drop-zone-hint">wav · mp3 · m4a · ogg · flac</div>
86+
</div>
87+
<input type="file" id="stt-file-input" accept="audio/*" style="display:none">
8088
</div>
8189
8290
<!-- Transcription result area -->
@@ -119,6 +127,9 @@ export function initTranscribeTab(el: HTMLElement): TabLifecycle {
119127
showModelSelectionSheet(ModelCategory.SpeechRecognition),
120128
);
121129

130+
// File drop zone
131+
wireDropZone();
132+
122133
// Subscribe to model changes so the pill label stays current
123134
ModelManager.onChange(onSTTModelsChanged);
124135
onSTTModelsChanged(ModelManager.getModels());
@@ -343,6 +354,67 @@ function stopLiveVAD(): void {
343354
if (unsubscribeVAD) { unsubscribeVAD(); unsubscribeVAD = null; }
344355
}
345356

357+
// ---------------------------------------------------------------------------
358+
// File Drop Zone (delegates all conversion + transcription to SDK)
359+
// ---------------------------------------------------------------------------
360+
361+
function wireDropZone(): void {
362+
const dropZone = container.querySelector('#stt-drop-zone') as HTMLElement;
363+
const fileInput = container.querySelector('#stt-file-input') as HTMLInputElement;
364+
365+
// Click → open file picker
366+
dropZone.addEventListener('click', () => fileInput.click());
367+
368+
// File picker selection
369+
fileInput.addEventListener('change', () => {
370+
const file = fileInput.files?.[0];
371+
if (file) {
372+
fileInput.value = '';
373+
void transcribeFromFile(file);
374+
}
375+
});
376+
377+
// Drag events
378+
dropZone.addEventListener('dragover', (e) => {
379+
e.preventDefault();
380+
dropZone.classList.add('drag-over');
381+
});
382+
dropZone.addEventListener('dragleave', () => dropZone.classList.remove('drag-over'));
383+
dropZone.addEventListener('drop', (e) => {
384+
e.preventDefault();
385+
dropZone.classList.remove('drag-over');
386+
const file = e.dataTransfer?.files[0];
387+
if (file) void transcribeFromFile(file);
388+
});
389+
}
390+
391+
async function transcribeFromFile(file: File): Promise<void> {
392+
if (sttState !== 'idle') return;
393+
394+
sttError = '';
395+
sttTranscription = '';
396+
sttState = 'transcribing';
397+
renderSTTUI();
398+
399+
try {
400+
const model = await ModelManager.ensureLoaded(ModelCategory.SpeechRecognition);
401+
if (!model) throw new Error('No STT model loaded. Tap the model button to download one.');
402+
403+
const { STT } = await import('../../../../../sdk/runanywhere-web/packages/onnx/src/index');
404+
if (!STT.isModelLoaded) throw new Error('STT model not loaded. Select a model first.');
405+
406+
// SDK handles all decoding, resampling, and transcription
407+
const result = await STT.transcribeFile(file);
408+
sttTranscription = result.text.trim() || '';
409+
if (!sttTranscription) sttError = 'No speech detected in the audio file.';
410+
} catch (err) {
411+
sttError = err instanceof Error ? err.message : String(err);
412+
}
413+
414+
sttState = 'idle';
415+
renderSTTUI();
416+
}
417+
346418
// ---------------------------------------------------------------------------
347419
// UI Rendering
348420
// ---------------------------------------------------------------------------
@@ -382,6 +454,12 @@ function renderSTTUI(): void {
382454
resultArea.style.display = hasResult ? 'flex' : 'none';
383455
if (hasResult) resultText.textContent = sttTranscription || 'Transcribing...';
384456

457+
// Drop zone: visible only in batch idle state
458+
const dropZone = container.querySelector('#stt-drop-zone') as HTMLElement | null;
459+
if (dropZone) {
460+
dropZone.style.display = (sttMode === 'batch' && sttState === 'idle') ? '' : 'none';
461+
}
462+
385463
// Level bars
386464
levelBars.style.display = sttState === 'recording' ? '' : 'none';
387465

examples/web/RunAnywhereAI/tests/web-sdk-bugs.md

Lines changed: 0 additions & 96 deletions
This file was deleted.

0 commit comments

Comments
 (0)