mirror of
https://github.com/k2-fsa/icefall.git
synced 2025-12-11 06:55:27 +00:00
Begin to add recorder.
This commit is contained in:
parent
9b5c18438d
commit
30b2626172
@ -14,7 +14,7 @@
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
||||
|
||||
<title>Hello next-gen Kaldi</title>
|
||||
<title>Next-gen Kaldi demo</title>
|
||||
</head>
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
<li class="media">
|
||||
<div class="media-body">
|
||||
<h5 class="mt-0 mb-1">Record</h5>
|
||||
<p>Recognition from real-time recording</p>
|
||||
<p>Recognition from real-time recordings</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -14,7 +14,9 @@
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="record.html">Record</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
64
egs/librispeech/ASR/transducer_emformer/client/record.html
Normal file
64
egs/librispeech/ASR/transducer_emformer/client/record.html
Normal file
@ -0,0 +1,64 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8"></meta>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"></meta>
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css"
|
||||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
|
||||
crossorigin="anonymous">
|
||||
</link>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
||||
|
||||
<title>Next-gen Kaldi demo (Upload file for recognition)</title>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<div id="nav"></div>
|
||||
<script>
|
||||
$(function(){
|
||||
$("#nav").load("nav-partial.html");
|
||||
});
|
||||
</script>
|
||||
|
||||
<h3>Recognition from real-time recordings</h3>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<canvas id="canvas" height="60px" display="block" margin-bottom="0.5rem"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button class="btn btn-primary btn-block" id="record">Record</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn btn-primary btn-block" id="stop">Stop</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section flex="1" overflow="auto" id="sound-clips">
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Optional JavaScript -->
|
||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.7/dist/umd/popper.min.js"
|
||||
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
|
||||
crossorigin="anonymous">
|
||||
</script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.min.js"
|
||||
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
|
||||
crossorigin="anonymous">
|
||||
</script>
|
||||
|
||||
<script src="./record.js"> </script>
|
||||
</body>
|
||||
</html>
|
||||
189
egs/librispeech/ASR/transducer_emformer/client/record.js
Normal file
189
egs/librispeech/ASR/transducer_emformer/client/record.js
Normal file
@ -0,0 +1,189 @@
|
||||
// see https://mdn.github.io/web-dictaphone/scripts/app.js
|
||||
// and https://gist.github.com/meziantou/edb7217fddfbb70e899e
|
||||
|
||||
const record = document.getElementById('record');
|
||||
const stop = document.getElementById('stop');
|
||||
const soundClips = document.getElementById('sound-clips');
|
||||
const canvas = document.getElementById('canvas');
|
||||
|
||||
soundClips.innerHTML = "hello";
|
||||
|
||||
stop.disabled = true;
|
||||
|
||||
let audioCtx;
|
||||
const canvasCtx = canvas.getContext("2d");
|
||||
|
||||
let sampleRate;
|
||||
|
||||
if (navigator.mediaDevices.getUserMedia) {
|
||||
console.log('getUserMedia supported.');
|
||||
|
||||
// see https://w3c.github.io/mediacapture-main/#dom-mediadevices-getusermedia
|
||||
const constraints = {
|
||||
// does not work
|
||||
// audio : {sampleRate : 16000, sampleSize : 16, channelCount : 1}
|
||||
audio : true,
|
||||
};
|
||||
let chunks = [];
|
||||
|
||||
let onSuccess = function(stream) {
|
||||
var settings = stream.getAudioTracks()[0].getSettings();
|
||||
sampleRate = settings.sampleRate;
|
||||
console.log(settings);
|
||||
console.log('sample rate ' + settings.sampleRate);
|
||||
console.log('channel count ' + settings.channelCount);
|
||||
console.log('sample size ' + settings.sampleSize);
|
||||
const mediaRecorder = new MediaRecorder(stream);
|
||||
console.log('mime type ' + mediaRecorder.mimeType);
|
||||
console.log('audio bits per second ' + mediaRecorder.audioBitsPerSecond);
|
||||
console.log(mediaRecorder)
|
||||
|
||||
visualize(stream);
|
||||
|
||||
record.onclick = function() {
|
||||
mediaRecorder.start(10); // 10ms period to send data
|
||||
console.log(mediaRecorder.state);
|
||||
console.log("recorder started");
|
||||
record.style.background = "red";
|
||||
|
||||
stop.disabled = false;
|
||||
record.disabled = true;
|
||||
};
|
||||
|
||||
stop.onclick = function() {
|
||||
mediaRecorder.stop();
|
||||
console.log(mediaRecorder.state);
|
||||
console.log("recorder stopped");
|
||||
record.style.background = "";
|
||||
record.style.color = "";
|
||||
// mediaRecorder.requestData();
|
||||
|
||||
stop.disabled = true;
|
||||
record.disabled = false;
|
||||
};
|
||||
|
||||
mediaRecorder.onstop = function(e) {
|
||||
console.log("data available after MediaRecorder.stop() called.");
|
||||
|
||||
const clipName =
|
||||
prompt('Enter a name for your sound clip?', 'My unnamed clip');
|
||||
|
||||
const clipContainer = document.createElement('article');
|
||||
const clipLabel = document.createElement('p');
|
||||
const audio = document.createElement('audio');
|
||||
const deleteButton = document.createElement('button');
|
||||
|
||||
clipContainer.classList.add('clip');
|
||||
audio.setAttribute('controls', '');
|
||||
deleteButton.textContent = 'Delete';
|
||||
deleteButton.className = 'delete';
|
||||
|
||||
if (clipName === null) {
|
||||
clipLabel.textContent = 'My unnamed clip';
|
||||
} else {
|
||||
clipLabel.textContent = clipName;
|
||||
}
|
||||
|
||||
clipContainer.appendChild(audio);
|
||||
clipContainer.appendChild(clipLabel);
|
||||
clipContainer.appendChild(deleteButton);
|
||||
soundClips.appendChild(clipContainer);
|
||||
|
||||
audio.controls = true;
|
||||
const blob = new Blob(chunks, {'type' : 'audio/ogg; codecs=opus'});
|
||||
chunks = [];
|
||||
const audioURL = window.URL.createObjectURL(blob);
|
||||
audio.src = audioURL;
|
||||
console.log("recorder stopped");
|
||||
|
||||
deleteButton.onclick =
|
||||
function(e) {
|
||||
let evtTgt = e.target;
|
||||
evtTgt.parentNode.parentNode.removeChild(evtTgt.parentNode);
|
||||
}
|
||||
|
||||
clipLabel.onclick = function() {
|
||||
const existingName = clipLabel.textContent;
|
||||
const newClipName = prompt('Enter a new name for your sound clip?');
|
||||
if (newClipName === null) {
|
||||
clipLabel.textContent = existingName;
|
||||
} else {
|
||||
clipLabel.textContent = newClipName;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mediaRecorder.ondataavailable = function(e) {
|
||||
console.log('size ' + e.data.size);
|
||||
console.log(e.data);
|
||||
chunks.push(e.data);
|
||||
}
|
||||
};
|
||||
|
||||
let onError = function(
|
||||
err) { console.log('The following error occured: ' + err); };
|
||||
|
||||
navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
|
||||
|
||||
} else {
|
||||
console.log('getUserMedia not supported on your browser!');
|
||||
}
|
||||
|
||||
function visualize(stream) {
|
||||
if (!audioCtx) {
|
||||
audioCtx = new AudioContext();
|
||||
}
|
||||
|
||||
const source = audioCtx.createMediaStreamSource(stream);
|
||||
|
||||
const analyser = audioCtx.createAnalyser();
|
||||
analyser.fftSize = 2048;
|
||||
const bufferLength = analyser.frequencyBinCount;
|
||||
const dataArray = new Uint8Array(bufferLength);
|
||||
|
||||
source.connect(analyser);
|
||||
// analyser.connect(audioCtx.destination);
|
||||
|
||||
draw()
|
||||
|
||||
function draw() {
|
||||
const WIDTH = canvas.width
|
||||
const HEIGHT = canvas.height;
|
||||
|
||||
requestAnimationFrame(draw);
|
||||
|
||||
analyser.getByteTimeDomainData(dataArray);
|
||||
|
||||
canvasCtx.fillStyle = 'rgb(200, 200, 200)';
|
||||
canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
|
||||
|
||||
canvasCtx.lineWidth = 2;
|
||||
canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
|
||||
|
||||
canvasCtx.beginPath();
|
||||
|
||||
let sliceWidth = WIDTH * 1.0 / bufferLength;
|
||||
let x = 0;
|
||||
|
||||
for (let i = 0; i < bufferLength; i++) {
|
||||
|
||||
let v = dataArray[i] / 128.0;
|
||||
let y = v * HEIGHT / 2;
|
||||
|
||||
if (i === 0) {
|
||||
canvasCtx.moveTo(x, y);
|
||||
} else {
|
||||
canvasCtx.lineTo(x, y);
|
||||
}
|
||||
|
||||
x += sliceWidth;
|
||||
}
|
||||
|
||||
canvasCtx.lineTo(canvas.width, canvas.height / 2);
|
||||
canvasCtx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
window.onresize = function() { canvas.width = mainSection.offsetWidth; };
|
||||
|
||||
window.onresize();
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
||||
|
||||
<title>Hello next-gen Kaldi (Upload file for recognition)</title>
|
||||
<title>Next-gen Kaldi demo (Upload file for recognition)</title>
|
||||
</head>
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user