Update app.py
Browse files
app.py
CHANGED
@@ -142,23 +142,35 @@ async def get_home():
|
|
142 |
<head>
|
143 |
<meta charset="UTF-8">
|
144 |
<title>AssemblyAI Realtime Transcription</title>
|
|
|
145 |
</head>
|
146 |
-
<body>
|
147 |
-
<
|
148 |
-
<
|
149 |
-
<
|
|
|
150 |
<option value="tiny">Tiny Model</option>
|
151 |
<option value="base">Base Model</option>
|
152 |
</select>
|
153 |
-
<p id="status">Click start to begin transcription.</p>
|
154 |
-
<div id="transcription"
|
|
|
|
|
|
|
|
|
155 |
<script>
|
156 |
let ws;
|
157 |
let audioContext;
|
158 |
let scriptProcessor;
|
159 |
let mediaStream;
|
160 |
let currentLine = document.createElement('span');
|
|
|
|
|
|
|
161 |
document.getElementById('transcription').appendChild(currentLine);
|
|
|
|
|
|
|
162 |
async function startTranscription() {
|
163 |
document.getElementById("status").innerText = "Connecting...";
|
164 |
ws = new WebSocket("wss://" + location.host + "/ws/transcribe");
|
@@ -169,6 +181,11 @@ async def get_home():
|
|
169 |
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
170 |
audioContext = new AudioContext({ sampleRate: 16000 });
|
171 |
const source = audioContext.createMediaStreamSource(mediaStream);
|
|
|
|
|
|
|
|
|
|
|
172 |
scriptProcessor = audioContext.createScriptProcessor(512, 1, 1);
|
173 |
scriptProcessor.onaudioprocess = function(event) {
|
174 |
const inputData = event.inputBuffer.getChannelData(0);
|
@@ -176,6 +193,26 @@ async def get_home():
|
|
176 |
if (ws.readyState === WebSocket.OPEN) {
|
177 |
ws.send(pcm16);
|
178 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
};
|
180 |
source.connect(scriptProcessor);
|
181 |
scriptProcessor.connect(audioContext.destination);
|
@@ -203,6 +240,7 @@ async def get_home():
|
|
203 |
document.getElementById("status").innerText = "Closed";
|
204 |
};
|
205 |
}
|
|
|
206 |
function switchModel() {
|
207 |
const model = document.getElementById("modelSelect").value;
|
208 |
if (ws && ws.readyState === WebSocket.OPEN) {
|
@@ -213,6 +251,7 @@ async def get_home():
|
|
213 |
}
|
214 |
}
|
215 |
}
|
|
|
216 |
function floatTo16BitPCM(input) {
|
217 |
const buffer = new ArrayBuffer(input.length * 2);
|
218 |
const output = new DataView(buffer);
|
@@ -229,4 +268,4 @@ async def get_home():
|
|
229 |
|
230 |
if __name__ == "__main__":
|
231 |
import uvicorn
|
232 |
-
uvicorn.run(app, host="0.0.0.0", port=7860)
|
|
|
142 |
<head>
|
143 |
<meta charset="UTF-8">
|
144 |
<title>AssemblyAI Realtime Transcription</title>
|
145 |
+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
|
146 |
</head>
|
147 |
+
<body class="bg-gray-100 p-6">
|
148 |
+
<div class="max-w-3xl mx-auto bg-white p-6 rounded-lg shadow-md">
|
149 |
+
<h1 class="text-2xl font-bold mb-4">Realtime Transcription</h1>
|
150 |
+
<button onclick="startTranscription()" class="bg-blue-500 text-white px-4 py-2 rounded mb-4">Start Transcription</button>
|
151 |
+
<select id="modelSelect" onchange="switchModel()" class="bg-gray-200 px-4 py-2 rounded mb-4">
|
152 |
<option value="tiny">Tiny Model</option>
|
153 |
<option value="base">Base Model</option>
|
154 |
</select>
|
155 |
+
<p id="status" class="text-gray-600 mb-4">Click start to begin transcription.</p>
|
156 |
+
<div id="transcription" class="border p-4 rounded mb-4 h-64 overflow-auto"></div>
|
157 |
+
<div id="visualizer" class="border p-4 rounded h-64">
|
158 |
+
<canvas id="audioCanvas" class="w-full h-full"></canvas>
|
159 |
+
</div>
|
160 |
+
</div>
|
161 |
<script>
|
162 |
let ws;
|
163 |
let audioContext;
|
164 |
let scriptProcessor;
|
165 |
let mediaStream;
|
166 |
let currentLine = document.createElement('span');
|
167 |
+
let analyser;
|
168 |
+
let canvas, canvasContext;
|
169 |
+
|
170 |
document.getElementById('transcription').appendChild(currentLine);
|
171 |
+
canvas = document.getElementById('audioCanvas');
|
172 |
+
canvasContext = canvas.getContext('2d');
|
173 |
+
|
174 |
async function startTranscription() {
|
175 |
document.getElementById("status").innerText = "Connecting...";
|
176 |
ws = new WebSocket("wss://" + location.host + "/ws/transcribe");
|
|
|
181 |
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
182 |
audioContext = new AudioContext({ sampleRate: 16000 });
|
183 |
const source = audioContext.createMediaStreamSource(mediaStream);
|
184 |
+
analyser = audioContext.createAnalyser();
|
185 |
+
analyser.fftSize = 2048;
|
186 |
+
const bufferLength = analyser.frequencyBinCount;
|
187 |
+
const dataArray = new Uint8Array(bufferLength);
|
188 |
+
source.connect(analyser);
|
189 |
scriptProcessor = audioContext.createScriptProcessor(512, 1, 1);
|
190 |
scriptProcessor.onaudioprocess = function(event) {
|
191 |
const inputData = event.inputBuffer.getChannelData(0);
|
|
|
193 |
if (ws.readyState === WebSocket.OPEN) {
|
194 |
ws.send(pcm16);
|
195 |
}
|
196 |
+
analyser.getByteTimeDomainData(dataArray);
|
197 |
+
canvasContext.fillStyle = 'rgb(200, 200, 200)';
|
198 |
+
canvasContext.fillRect(0, 0, canvas.width, canvas.height);
|
199 |
+
canvasContext.lineWidth = 2;
|
200 |
+
canvasContext.strokeStyle = 'rgb(0, 0, 0)';
|
201 |
+
canvasContext.beginPath();
|
202 |
+
let sliceWidth = canvas.width * 1.0 / bufferLength;
|
203 |
+
let x = 0;
|
204 |
+
for (let i = 0; i < bufferLength; i++) {
|
205 |
+
let v = dataArray[i] / 128.0;
|
206 |
+
let y = v * canvas.height / 2;
|
207 |
+
if (i === 0) {
|
208 |
+
canvasContext.moveTo(x, y);
|
209 |
+
} else {
|
210 |
+
canvasContext.lineTo(x, y);
|
211 |
+
}
|
212 |
+
x += sliceWidth;
|
213 |
+
}
|
214 |
+
canvasContext.lineTo(canvas.width, canvas.height / 2);
|
215 |
+
canvasContext.stroke();
|
216 |
};
|
217 |
source.connect(scriptProcessor);
|
218 |
scriptProcessor.connect(audioContext.destination);
|
|
|
240 |
document.getElementById("status").innerText = "Closed";
|
241 |
};
|
242 |
}
|
243 |
+
|
244 |
function switchModel() {
|
245 |
const model = document.getElementById("modelSelect").value;
|
246 |
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
|
251 |
}
|
252 |
}
|
253 |
}
|
254 |
+
|
255 |
function floatTo16BitPCM(input) {
|
256 |
const buffer = new ArrayBuffer(input.length * 2);
|
257 |
const output = new DataView(buffer);
|
|
|
268 |
|
269 |
if __name__ == "__main__":
|
270 |
import uvicorn
|
271 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|