github-actions[bot] commited on
Commit
5ed4c17
·
1 Parent(s): aa3ab7e

Auto-deploy from GitHub: 5d667bf754bfbf65bb6436e5979903221a0ad738

Browse files
Files changed (3) hide show
  1. .gitattributes +1 -1
  2. app.py +58 -6
  3. index.html +62 -1
.gitattributes CHANGED
@@ -1,5 +1,5 @@
 
1
  *.mp3 filter=lfs diff=lfs merge=lfs -text
2
  *.flac filter=lfs diff=lfs merge=lfs -text
3
  *.pth filter=lfs diff=lfs merge=lfs -text
4
  *.bin filter=lfs diff=lfs merge=lfs -text
5
- *.wav filter=lfs diff=lfs merge=lfs -text
 
1
+ *.wav filter=lfs diff=lfs merge=lfs -text
2
  *.mp3 filter=lfs diff=lfs merge=lfs -text
3
  *.flac filter=lfs diff=lfs merge=lfs -text
4
  *.pth filter=lfs diff=lfs merge=lfs -text
5
  *.bin filter=lfs diff=lfs merge=lfs -text
 
app.py CHANGED
@@ -36,7 +36,10 @@ def init_db():
36
  output_file TEXT,
37
  created_at TEXT NOT NULL,
38
  processed_at TEXT,
39
- error TEXT)''')
 
 
 
40
  conn.commit()
41
  conn.close()
42
 
@@ -147,10 +150,15 @@ def worker_loop():
147
  "--speed", str(speed)
148
  ]
149
 
150
- subprocess.run(
 
 
151
  command,
152
- check=True,
 
153
  cwd=CWD,
 
 
154
  env={
155
  **os.environ,
156
  'PYTHONUNBUFFERED': '1',
@@ -158,6 +166,39 @@ def worker_loop():
158
  }
159
  )
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  # Check for output file
162
  output_filename = "output_audio.wav"
163
  if os.path.exists(output_filename):
@@ -186,6 +227,15 @@ def worker_loop():
186
  print(f"⚠️ Worker error: {str(e)}")
187
  time.sleep(POLL_INTERVAL)
188
 
 
 
 
 
 
 
 
 
 
189
  def update_status(task_id, status, output_file=None, error=None):
190
  """Update the status of a task in the database"""
191
  conn = sqlite3.connect('tts_tasks.db')
@@ -193,12 +243,12 @@ def update_status(task_id, status, output_file=None, error=None):
193
 
194
  if status == 'completed':
195
  c.execute('''UPDATE tasks
196
- SET status = ?, output_file = ?, processed_at = ?
197
  WHERE id = ?''',
198
  (status, output_file, datetime.now().isoformat(), task_id))
199
  elif status == 'failed':
200
  c.execute('''UPDATE tasks
201
- SET status = ?, error = ?, processed_at = ?
202
  WHERE id = ?''',
203
  (status, str(error), datetime.now().isoformat(), task_id))
204
  else:
@@ -276,7 +326,9 @@ def get_files():
276
  'output_file': row['output_file'],
277
  'created_at': row['created_at'],
278
  'processed_at': row['processed_at'],
279
- 'error': row['error']
 
 
280
  }
281
 
282
  # Add queue position for not_started tasks
 
36
  output_file TEXT,
37
  created_at TEXT NOT NULL,
38
  processed_at TEXT,
39
+ error TEXT,
40
+ progress INTEGER DEFAULT 0,
41
+ progress_text TEXT)''')
42
+
43
  conn.commit()
44
  conn.close()
45
 
 
150
  "--speed", str(speed)
151
  ]
152
 
153
+ # Run with output capture for progress tracking
154
+ import re
155
+ process = subprocess.Popen(
156
  command,
157
+ stdout=subprocess.PIPE,
158
+ stderr=subprocess.STDOUT,
159
  cwd=CWD,
160
+ text=True,
161
+ bufsize=1,
162
  env={
163
  **os.environ,
164
  'PYTHONUNBUFFERED': '1',
 
166
  }
167
  )
168
 
169
+ total_sentences = 0
170
+ current_sentence = 0
171
+
172
+ for line in process.stdout:
173
+ print(line, end='') # Echo to console
174
+
175
+ # Parse "Sentence X processed" lines
176
+ match = re.search(r'Sentence\s+(\d+)\s+processed', line)
177
+ if match:
178
+ current_sentence = int(match.group(1))
179
+ # Try to get total from "Combining X audio files"
180
+ if total_sentences > 0:
181
+ progress = int((current_sentence / total_sentences) * 100)
182
+ update_progress(task_id, progress, f"Processing sentence {current_sentence}/{total_sentences}")
183
+
184
+ # Parse "Combining X audio files" to get total count
185
+ combine_match = re.search(r'Combining\s+(\d+)\s+audio\s+files', line)
186
+ if combine_match:
187
+ total_sentences = int(combine_match.group(1))
188
+ update_progress(task_id, 90, "Combining audio files...")
189
+
190
+ # Parse "Processing text sentences..." as start
191
+ if 'Processing text sentences' in line:
192
+ update_progress(task_id, 5, "Processing text sentences...")
193
+
194
+ # Parse model loading
195
+ if 'Model loaded successfully' in line:
196
+ update_progress(task_id, 10, "Model loaded, starting TTS...")
197
+
198
+ process.wait()
199
+ if process.returncode != 0:
200
+ raise Exception(f"TTS process failed with return code {process.returncode}")
201
+
202
  # Check for output file
203
  output_filename = "output_audio.wav"
204
  if os.path.exists(output_filename):
 
227
  print(f"⚠️ Worker error: {str(e)}")
228
  time.sleep(POLL_INTERVAL)
229
 
230
+ def update_progress(task_id, progress, progress_text=None):
231
+ """Update the progress of a task"""
232
+ conn = sqlite3.connect('tts_tasks.db')
233
+ c = conn.cursor()
234
+ c.execute('UPDATE tasks SET progress = ?, progress_text = ? WHERE id = ?',
235
+ (progress, progress_text, task_id))
236
+ conn.commit()
237
+ conn.close()
238
+
239
  def update_status(task_id, status, output_file=None, error=None):
240
  """Update the status of a task in the database"""
241
  conn = sqlite3.connect('tts_tasks.db')
 
243
 
244
  if status == 'completed':
245
  c.execute('''UPDATE tasks
246
+ SET status = ?, output_file = ?, processed_at = ?, progress = 100, progress_text = 'Completed'
247
  WHERE id = ?''',
248
  (status, output_file, datetime.now().isoformat(), task_id))
249
  elif status == 'failed':
250
  c.execute('''UPDATE tasks
251
+ SET status = ?, error = ?, processed_at = ?, progress_text = 'Failed'
252
  WHERE id = ?''',
253
  (status, str(error), datetime.now().isoformat(), task_id))
254
  else:
 
326
  'output_file': row['output_file'],
327
  'created_at': row['created_at'],
328
  'processed_at': row['processed_at'],
329
+ 'error': row['error'],
330
+ 'progress': row['progress'] or 0,
331
+ 'progress_text': row['progress_text']
332
  }
333
 
334
  # Add queue position for not_started tasks
index.html CHANGED
@@ -350,6 +350,49 @@
350
  color: var(--text);
351
  }
352
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
353
  .text-cell {
354
  max-width: 300px;
355
  overflow: hidden;
@@ -798,6 +841,24 @@
798
  const escapedText = escapeHtml(file.text);
799
  const truncatedText = file.text.length > 50 ? file.text.substring(0, 50) + '...' : file.text;
800
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
801
  return `
802
  <tr>
803
  <td>
@@ -806,7 +867,7 @@
806
  <button class="btn btn-small btn-view-text" onclick="showTextPopup(${index})">👁️ View</button>
807
  </div>
808
  </td>
809
- <td><span class="status status-${file.status}">${file.status.replace('_', ' ')}</span></td>
810
  <td>
811
  ${file.status === 'completed' && file.output_file ?
812
  `<a href="${API_URL}/download/${file.id}" class="btn btn-small btn-secondary" target="_blank">⬇️</a>`
 
350
  color: var(--text);
351
  }
352
 
353
+ /* Progress display */
354
+ .status-progress {
355
+ display: flex;
356
+ flex-direction: column;
357
+ gap: 0.3rem;
358
+ min-width: 120px;
359
+ }
360
+
361
+ .progress-bar-container {
362
+ width: 100%;
363
+ height: 6px;
364
+ background: rgba(0, 212, 255, 0.2);
365
+ border: 1px solid var(--accent);
366
+ overflow: hidden;
367
+ }
368
+
369
+ .progress-bar {
370
+ height: 100%;
371
+ background: linear-gradient(90deg, var(--primary), var(--accent));
372
+ transition: width 0.3s ease;
373
+ animation: progressPulse 1.5s ease-in-out infinite;
374
+ }
375
+
376
+ @keyframes progressPulse {
377
+
378
+ 0%,
379
+ 100% {
380
+ opacity: 1;
381
+ }
382
+
383
+ 50% {
384
+ opacity: 0.7;
385
+ }
386
+ }
387
+
388
+ .progress-text {
389
+ font-size: 0.7rem;
390
+ color: var(--accent);
391
+ white-space: nowrap;
392
+ overflow: hidden;
393
+ text-overflow: ellipsis;
394
+ }
395
+
396
  .text-cell {
397
  max-width: 300px;
398
  overflow: hidden;
 
841
  const escapedText = escapeHtml(file.text);
842
  const truncatedText = file.text.length > 50 ? file.text.substring(0, 50) + '...' : file.text;
843
 
844
+ // Build status display with progress
845
+ let statusDisplay = '';
846
+ if (file.status === 'processing') {
847
+ const progressPercent = file.progress || 0;
848
+ const progressText = file.progress_text || 'Processing...';
849
+ statusDisplay = `
850
+ <div class="status-progress">
851
+ <span class="status status-${file.status}">${progressPercent}%</span>
852
+ <div class="progress-bar-container">
853
+ <div class="progress-bar" style="width: ${progressPercent}%"></div>
854
+ </div>
855
+ <span class="progress-text">${escapeHtml(progressText)}</span>
856
+ </div>
857
+ `;
858
+ } else {
859
+ statusDisplay = `<span class="status status-${file.status}">${file.status.replace('_', ' ')}</span>`;
860
+ }
861
+
862
  return `
863
  <tr>
864
  <td>
 
867
  <button class="btn btn-small btn-view-text" onclick="showTextPopup(${index})">👁️ View</button>
868
  </div>
869
  </td>
870
+ <td>${statusDisplay}</td>
871
  <td>
872
  ${file.status === 'completed' && file.output_file ?
873
  `<a href="${API_URL}/download/${file.id}" class="btn btn-small btn-secondary" target="_blank">⬇️</a>`