-
Notifications
You must be signed in to change notification settings - Fork 1
/
web.html
113 lines (102 loc) · 7.95 KB
/
web.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<!DOCTYPE html>
<html>
<head>
<title>Live Transcription</title>
<script src="https://cdn.socket.io/4.2.0/socket.io.min.js"></script>
<script src="https://cdn.webrtc-experiment.com/MediaStreamRecorder.js"></script>
</head>
<body>
<button id="start-btn">Start Recording</button>
<button id="stop-btn" disabled>Stop Recording</button>
<button id="save-btn">Save Recording</button>
<select id="lang-select"></select>
<p id="status">Not recording</p>
<p>Transcript:</p>
<div id="transcript"></div>
<script>
// Get audio data from the recorder every 1000ms (1s)
const dataInterval = 1000;
const startButton = document.getElementById('start-btn');
const stopButton = document.getElementById('stop-btn');
const saveButton = document.getElementById('save-btn');
const langSelect = document.getElementById('lang-select')
const statusParagraph = document.getElementById('status');
const transcriptDiv = document.getElementById('transcript');
// Source: https://learn.microsoft.com/en-us/azure/cognitive-services/speech-service/language-support?tabs=stt
const langs = { "af-ZA": "Afrikaans (South Africa)", "am-ET": "Amharic (Ethiopia)", "ar-AE": "Arabic (United Arab Emirates)", "ar-BH": "Arabic (Bahrain)", "ar-DZ": "Arabic (Algeria)", "ar-EG": "Arabic (Egypt)", "ar-IL": "Arabic (Israel)", "ar-IQ": "Arabic (Iraq)", "ar-JO": "Arabic (Jordan)", "ar-KW": "Arabic (Kuwait)", "ar-LB": "Arabic (Lebanon)", "ar-LY": "Arabic (Libya)", "ar-MA": "Arabic (Morocco)", "ar-OM": "Arabic (Oman)", "ar-PS": "Arabic (Palestinian Territories)", "ar-QA": "Arabic (Qatar)", "ar-SA": "Arabic (Saudi Arabia)", "ar-SY": "Arabic (Syria)", "ar-TN": "Arabic (Tunisia)", "ar-YE": "Arabic (Yemen)", "az-AZ": "Azerbaijani (Latin, Azerbaijan)", "bg-BG": "Bulgarian (Bulgaria)", "bn-IN": "Bengali (India)", "bs-BA": "Bosnian (Bosnia and Herzegovina)", "ca-ES": "Catalan (Spain)", "cs-CZ": "Czech (Czechia)", "cy-GB": "Welsh (United Kingdom)", "da-DK": "Danish (Denmark)", "de-AT": "German (Austria)", "de-CH": "German (Switzerland)", "de-DE": "German (Germany)", "el-GR": "Greek (Greece)", "en-AU": "English (Australia)", "en-CA": "English (Canada)", "en-GB": "English (United Kingdom)", "en-GH": "English (Ghana)", "en-HK": "English (Hong Kong SAR)", "en-IE": "English (Ireland)", "en-IN": "English (India)", "en-KE": "English (Kenya)", "en-NG": "English (Nigeria)", "en-NZ": "English (New Zealand)", "en-PH": "English (Philippines)", "en-SG": "English (Singapore)", "en-TZ": "English (Tanzania)", "en-US": "English (United States)", "en-ZA": "English (South Africa)", "es-AR": "Spanish (Argentina)", "es-BO": "Spanish (Bolivia)", "es-CL": "Spanish (Chile)", "es-CO": "Spanish (Colombia)", "es-CR": "Spanish (Costa Rica)", "es-CU": "Spanish (Cuba)", "es-DO": "Spanish (Dominican Republic)", "es-EC": "Spanish (Ecuador)", "es-ES": "Spanish (Spain)", "es-GQ": "Spanish (Equatorial Guinea)", "es-GT": "Spanish (Guatemala)", "es-HN": "Spanish (Honduras)", "es-MX": "Spanish (Mexico)", "es-NI": "Spanish (Nicaragua)", "es-PA": "Spanish (Panama)", "es-PE": "Spanish (Peru)", "es-PR": "Spanish (Puerto Rico)", "es-PY": "Spanish (Paraguay)", "es-SV": "Spanish (El Salvador)", "es-US": "Spanish (United States)", "es-UY": "Spanish (Uruguay)", "es-VE": "Spanish (Venezuela)", "et-EE": "Estonian (Estonia)", "eu-ES": "Basque", "fa-IR": "Persian (Iran)", "fi-FI": "Finnish (Finland)", "fil-PH": "Filipino (Philippines)", "fr-BE": "French (Belgium)", "fr-CA": "French (Canada)", "fr-CH": "French (Switzerland)", "fr-FR": "French (France)", "ga-IE": "Irish (Ireland)", "gl-ES": "Galician", "gu-IN": "Gujarati (India)", "he-IL": "Hebrew (Israel)", "hi-IN": "Hindi (India)", "hr-HR": "Croatian (Croatia)", "hu-HU": "Hungarian (Hungary)", "hy-AM": "Armenian (Armenia)", "id-ID": "Indonesian (Indonesia)", "is-IS": "Icelandic (Iceland)", "it-CH": "Italian (Switzerland)", "it-IT": "Italian (Italy)", "ja-JP": "Japanese (Japan)", "jv-ID": "Javanese (Latin, Indonesia)", "ka-GE": "Georgian (Georgia)", "kk-KZ": "Kazakh (Kazakhstan)", "km-KH": "Khmer (Cambodia)", "kn-IN": "Kannada (India)", "ko-KR": "Korean (Korea)", "lo-LA": "Lao (Laos)", "lt-LT": "Lithuanian (Lithuania)", "lv-LV": "Latvian (Latvia)", "mk-MK": "Macedonian (North Macedonia)", "ml-IN": "Malayalam (India)", "mn-MN": "Mongolian (Mongolia)", "mr-IN": "Marathi (India)", "ms-MY": "Malay (Malaysia)", "mt-MT": "Maltese (Malta)", "my-MM": "Burmese (Myanmar)", "nb-NO": "Norwegian Bokm\\u00e5l (Norway)", "ne-NP": "Nepali (Nepal)", "nl-BE": "Dutch (Belgium)", "nl-NL": "Dutch (Netherlands)", "pl-PL": "Polish (Poland)", "ps-AF": "Pashto (Afghanistan)", "pt-BR": "Portuguese (Brazil)", "pt-PT": "Portuguese (Portugal)", "ro-RO": "Romanian (Romania)", "ru-RU": "Russian (Russia)", "si-LK": "Sinhala (Sri Lanka)", "sk-SK": "Slovak (Slovakia)", "sl-SI": "Slovenian (Slovenia)", "so-SO": "Somali (Somalia)", "sq-AL": "Albanian (Albania)", "sr-RS": "Serbian (Cyrillic, Serbia)", "sv-SE": "Swedish (Sweden)", "sw-KE": "Swahili (Kenya)", "sw-TZ": "Swahili (Tanzania)", "ta-IN": "Tamil (India)", "te-IN": "Telugu (India)", "th-TH": "Thai (Thailand)", "tr-TR": "Turkish (Turkey)", "uk-UA": "Ukrainian (Ukraine)", "uz-UZ": "Uzbek (Latin, Uzbekistan)", "vi-VN": "Vietnamese (Vietnam)", "wuu-CN": "Chinese (Wu, Simplified)", "yue-CN": "Chinese (Cantonese, Simplified)", "zh-CN": "Chinese (Mandarin, Simplified)", "zh-CN-shandong": "Chinese (Jilu Mandarin, Simplified)", "zh-CN-sichuan": "Chinese (Southwestern Mandarin, Simplified)", "zh-HK": "Chinese (Cantonese, Traditional)", "zh-TW": "Chinese (Taiwanese Mandarin, Traditional)", "zu-ZA": "Zulu (South Africa)" };
Object.keys(langs).forEach((lang) => {
const optionEle = document.createElement('option');
optionEle.setAttribute('value', lang);
if (lang === 'en-US') {
optionEle.setAttribute('selected', '');
}
optionEle.innerText = langs[lang];
langSelect.appendChild(optionEle);
});
let socket = null;
let mediaRecorder = null;
let audioChunks = [];
let sendDataIntervalId;
let currStream = null;
const toggleRecordingStatus = (recording) => {
if (recording) {
statusParagraph.textContent = 'Recording...';
startButton.disabled = true;
stopButton.disabled = false;
langSelect.disabled = true;
} else {
statusParagraph.textContent = 'Not recording';
startButton.disabled = false;
stopButton.disabled = true;
langSelect.disabled = false;
}
}
startButton.onclick = () => {
navigator.mediaDevices.getUserMedia({
audio: true,
video: false
}).then((stream) => {
socket = io();
socket.emit('init', {
language: langSelect.value
});
currStream = stream;
socket.on('ready', () => {
// Start recording after the server is ready
mediaRecorder = new MediaStreamRecorder(stream);
mediaRecorder.recorderType = StereoAudioRecorder;
mediaRecorder.mimeType = 'audio/wav';
mediaRecorder.audioChannels = 1;
mediaRecorder.ondataavailable = (blob) => {
// On new audio clip, send it to the server using Socket.IO
socket.emit('audio', blob);
};
socket.on('transcript', (res) => {
// Upon receiving transcription from the server
transcriptDiv.innerText = res;
});
// Start recording
mediaRecorder.start(dataInterval);
toggleRecordingStatus(true);
});
}).catch((err) => {
console.error(err);
alert('Unable to record.');
});
}
stopButton.onclick = () => {
mediaRecorder.stop();
currStream.getTracks().forEach((track) => {
track.stop();
});
currStream = null;
socket.disconnect();
socket = null;
toggleRecordingStatus(false);
}
saveButton.onclick = () => {
mediaRecorder.save();
}
</script>
</body>
</html>