pvanand commited on
Commit
f317957
1 Parent(s): 508be3f

Update static/indic-text-to-speech.html

Browse files
Files changed (1) hide show
  1. static/indic-text-to-speech.html +143 -8
static/indic-text-to-speech.html CHANGED
@@ -3,20 +3,71 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Indic Text-to-Speech</title>
7
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
8
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/@sanskrit-coders/[email protected]/sanscript.min.js"></script>
10
  <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
11
- <!-- Plyr CSS -->
12
  <link rel="stylesheet" href="https://cdn.plyr.io/3.6.8/plyr.css" />
13
- <!-- Plyr JS -->
14
  <script src="https://cdn.plyr.io/3.6.8/plyr.polyfilled.js"></script>
15
  </head>
16
  <body class="bg-gray-100">
17
  <div id="app" class="container mx-auto px-4 py-8">
18
- <h1 class="text-3xl font-bold text-center mb-8 text-indigo-600">Indic Text-to-Speech</h1>
19
- <div class="max-w-2xl mx-auto bg-white rounded-lg shadow-md p-6">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  <div class="mb-4">
21
  <label for="language" class="block text-sm font-medium text-gray-700 mb-2">Select Language</label>
22
  <select id="language" v-model="selectedLanguage" @change="updateExample" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
@@ -56,11 +107,22 @@
56
  new Vue({
57
  el: '#app',
58
  data: {
 
 
 
 
 
 
 
 
 
 
 
 
59
  languages: [],
60
  selectedLanguage: '',
61
  inputText: '',
62
  audioUrl: null,
63
- isLoading: false,
64
  player: null,
65
  examples: {
66
  hin: "भारत विविधता में एकता का देश है। यहाँ अनेक भाषाएँ, धर्म और संस्कृतियाँ एक साथ फलती-फूलती हैं।",
@@ -93,6 +155,81 @@
93
  });
94
  },
95
  methods: {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  fetchLanguages() {
97
  axios.get('https://pvanand-audio-chat-indic.hf.space/languages')
98
  .then(response => {
@@ -113,7 +250,6 @@
113
  this.isLoading = true;
114
  let text = this.inputText.trim() || this.currentExample;
115
  let lang = this.selectedLanguage;
116
-
117
  if (this.selectedLanguage === 'san') {
118
  if (typeof Sanscript !== 'undefined') {
119
  text = Sanscript.t(text, 'devanagari', 'kannada');
@@ -125,7 +261,6 @@
125
  return;
126
  }
127
  }
128
-
129
  const url = `https://pvanand-audio-chat-indic.hf.space/tts?text=${encodeURIComponent(text)}&lang=${lang}`;
130
  axios.get(url, { responseType: 'blob' })
131
  .then(response => {
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Indic Audio Tools</title>
7
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
8
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/@sanskrit-coders/[email protected]/sanscript.min.js"></script>
10
  <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
11
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet">
12
  <link rel="stylesheet" href="https://cdn.plyr.io/3.6.8/plyr.css" />
 
13
  <script src="https://cdn.plyr.io/3.6.8/plyr.polyfilled.js"></script>
14
  </head>
15
  <body class="bg-gray-100">
16
  <div id="app" class="container mx-auto px-4 py-8">
17
+ <h1 class="text-3xl font-bold text-center mb-8 text-indigo-600">Indic Audio Tools</h1>
18
+
19
+ <!-- Tabs -->
20
+ <div class="flex justify-center mb-6">
21
+ <div class="inline-flex rounded-md shadow-sm" role="group">
22
+ <button @click="activeTab = 'transcription'"
23
+ :class="{ 'bg-indigo-600 text-white': activeTab === 'transcription', 'bg-white text-indigo-600': activeTab !== 'transcription' }"
24
+ class="px-4 py-2 text-sm font-medium border border-indigo-600 rounded-l-lg focus:z-10 focus:ring-2 focus:ring-indigo-500 focus:text-indigo-100 transition-colors duration-200">
25
+ Audio Transcription
26
+ </button>
27
+ <button @click="activeTab = 'tts'"
28
+ :class="{ 'bg-indigo-600 text-white': activeTab === 'tts', 'bg-white text-indigo-600': activeTab !== 'tts' }"
29
+ class="px-4 py-2 text-sm font-medium border border-indigo-600 rounded-r-lg focus:z-10 focus:ring-2 focus:ring-indigo-500 focus:text-indigo-100 transition-colors duration-200">
30
+ Text-to-Speech
31
+ </button>
32
+ </div>
33
+ </div>
34
+
35
+ <!-- Transcription Tab Content -->
36
+ <div v-if="activeTab === 'transcription'" class="max-w-2xl mx-auto bg-white rounded-lg shadow-md p-6">
37
+ <!-- Transcription content here -->
38
+ <div class="mb-4">
39
+ <label for="audioFile" class="block text-sm font-medium text-gray-700 mb-2">Select Audio File</label>
40
+ <input type="file" id="audioFile" @change="handleFileChange" accept="audio/*" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
41
+ </div>
42
+ <div class="mb-4 flex items-center">
43
+ <button @click="toggleRecording" class="mr-4 px-4 py-2 bg-red-500 text-white rounded-md hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500" :class="{ 'bg-gray-600 hover:bg-gray-700': isRecording }">
44
+ <i class="fas" :class="isRecording ? 'fa-stop' : 'fa-microphone'"></i>
45
+ {{ isRecording ? 'Stop Recording' : 'Record Audio' }}
46
+ </button>
47
+ <span v-if="isRecording" class="text-red-500">Recording... {{ recordingTime }}s</span>
48
+ <span v-else-if="audioBlob" class="text-green-600">Recording complete ({{ recordingTime }}s)</span>
49
+ </div>
50
+ <div class="flex justify-center" v-if="audioFile">
51
+ <button @click="transcribeAudio" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" :disabled="isLoading">
52
+ <span v-if="!isLoading">Transcribe Uploaded Audio</span>
53
+ <span v-else class="flex items-center">
54
+ <svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
55
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
56
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
57
+ </svg>
58
+ Transcribing...
59
+ </span>
60
+ </button>
61
+ </div>
62
+ <div v-if="transcription" class="mt-6 bg-gray-100 p-4 rounded-lg">
63
+ <h3 class="text-lg font-semibold text-gray-700 mb-2">Transcription Result</h3>
64
+ <p class="text-gray-600">{{ transcription }}</p>
65
+ </div>
66
+ </div>
67
+
68
+ <!-- Text-to-Speech Tab Content -->
69
+ <div v-if="activeTab === 'tts'" class="max-w-2xl mx-auto bg-white rounded-lg shadow-md p-6">
70
+ <!-- TTS content here -->
71
  <div class="mb-4">
72
  <label for="language" class="block text-sm font-medium text-gray-700 mb-2">Select Language</label>
73
  <select id="language" v-model="selectedLanguage" @change="updateExample" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500">
 
107
  new Vue({
108
  el: '#app',
109
  data: {
110
+ activeTab: 'transcription',
111
+ // Transcription data
112
+ audioFile: null,
113
+ audioBlob: null,
114
+ transcription: '',
115
+ isLoading: false,
116
+ isRecording: false,
117
+ mediaRecorder: null,
118
+ audioChunks: [],
119
+ recordingTime: 0,
120
+ recordingInterval: null,
121
+ // TTS data
122
  languages: [],
123
  selectedLanguage: '',
124
  inputText: '',
125
  audioUrl: null,
 
126
  player: null,
127
  examples: {
128
  hin: "भारत विविधता में एकता का देश है। यहाँ अनेक भाषाएँ, धर्म और संस्कृतियाँ एक साथ फलती-फूलती हैं।",
 
155
  });
156
  },
157
  methods: {
158
+ // Transcription methods
159
+ handleFileChange(event) {
160
+ this.audioFile = event.target.files[0];
161
+ this.audioBlob = null;
162
+ this.transcription = '';
163
+ },
164
+ async toggleRecording() {
165
+ if (this.isRecording) {
166
+ this.stopRecording();
167
+ } else {
168
+ await this.startRecording();
169
+ }
170
+ },
171
+ async startRecording() {
172
+ try {
173
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
174
+ this.mediaRecorder = new MediaRecorder(stream);
175
+ this.audioChunks = [];
176
+ this.mediaRecorder.ondataavailable = (event) => {
177
+ this.audioChunks.push(event.data);
178
+ };
179
+ this.mediaRecorder.onstop = () => {
180
+ this.audioBlob = new Blob(this.audioChunks, { type: 'audio/wav' });
181
+ this.audioFile = null;
182
+ this.transcribeAudio(); // Automatically transcribe after recording stops
183
+ };
184
+ this.mediaRecorder.start();
185
+ this.isRecording = true;
186
+ this.recordingTime = 0;
187
+ this.recordingInterval = setInterval(() => {
188
+ this.recordingTime++;
189
+ }, 1000);
190
+ } catch (error) {
191
+ console.error('Error accessing microphone:', error);
192
+ alert('Unable to access the microphone. Please make sure it\'s connected and you\'ve granted permission.');
193
+ }
194
+ },
195
+ stopRecording() {
196
+ if (this.mediaRecorder) {
197
+ this.mediaRecorder.stop();
198
+ this.isRecording = false;
199
+ clearInterval(this.recordingInterval);
200
+ }
201
+ },
202
+ transcribeAudio() {
203
+ if (!this.audioFile && !this.audioBlob) {
204
+ alert('Please select an audio file or record audio');
205
+ return;
206
+ }
207
+
208
+ this.isLoading = true;
209
+ const formData = new FormData();
210
+ if (this.audioFile) {
211
+ formData.append('file', this.audioFile);
212
+ } else {
213
+ formData.append('file', this.audioBlob, 'recorded_audio.wav');
214
+ }
215
+
216
+ axios.post('https://pvanand-audio-chat-indic.hf.space/transcribe/', formData, {
217
+ headers: {
218
+ 'Content-Type': 'multipart/form-data'
219
+ }
220
+ })
221
+ .then(response => {
222
+ this.transcription = response.data.transcript;
223
+ this.isLoading = false;
224
+ })
225
+ .catch(error => {
226
+ console.error('Error transcribing audio:', error);
227
+ alert('Error transcribing audio. Please try again.');
228
+ this.isLoading = false;
229
+ });
230
+ },
231
+
232
+ // TTS methods
233
  fetchLanguages() {
234
  axios.get('https://pvanand-audio-chat-indic.hf.space/languages')
235
  .then(response => {
 
250
  this.isLoading = true;
251
  let text = this.inputText.trim() || this.currentExample;
252
  let lang = this.selectedLanguage;
 
253
  if (this.selectedLanguage === 'san') {
254
  if (typeof Sanscript !== 'undefined') {
255
  text = Sanscript.t(text, 'devanagari', 'kannada');
 
261
  return;
262
  }
263
  }
 
264
  const url = `https://pvanand-audio-chat-indic.hf.space/tts?text=${encodeURIComponent(text)}&lang=${lang}`;
265
  axios.get(url, { responseType: 'blob' })
266
  .then(response => {