rein0421 commited on
Commit
e5e61c7
·
verified ·
1 Parent(s): 1b7bec8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +153 -48
app.py CHANGED
@@ -278,77 +278,182 @@ def update_all_users():
278
  @app.route('/upload_audio', methods=['POST'])
279
  def upload_audio():
280
  global total_audio
281
- global users
282
-
283
  try:
284
  data = request.get_json()
285
  if not data or 'audio_data' not in data:
 
286
  return jsonify({"error": "音声データがありません"}), 400
287
-
288
- # リクエストからユーザーリストを取得(指定がなければ現在のusersを使用)
289
- if 'selected_users' in data and data['selected_users']:
290
- users = data['selected_users']
291
- print(f"選択されたユーザー: {users}")
292
 
293
- if not users:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  return jsonify({"error": "選択されたユーザーがいません"}), 400
295
 
296
  # Base64デコードして音声バイナリを取得
297
  audio_binary = base64.b64decode(data['audio_data'])
298
-
299
- upload_name = 'tmp'
300
- audio_dir = "/tmp/data"
 
301
  os.makedirs(audio_dir, exist_ok=True)
302
  audio_path = os.path.join(audio_dir, f"{upload_name}.wav")
303
  with open(audio_path, 'wb') as f:
304
  f.write(audio_binary)
305
-
306
- print(f"処理を行うユーザー: {users}")
307
-
308
- # ベース音声を一時ディレクトリにダウンロード
309
- temp_dir = "/tmp/data/base_audio"
310
- os.makedirs(temp_dir, exist_ok=True)
311
-
 
312
  # 各ユーザーの参照音声ファイルのパスをリストに格納
313
  reference_paths = []
314
- for user in users:
 
315
  try:
316
- ref_path = os.path.join(temp_dir, f"{user}.wav")
317
- if not os.path.exists(ref_path):
318
- # クラウドから取得
319
- download_from_cloud(f"{user}.wav", ref_path)
320
- print(f"クラウドから {user}.wav をダウンロードしました")
321
-
322
  if not os.path.exists(ref_path):
323
- return jsonify({"error": "参照音声ファイルが見つかりません", "details": ref_path}), 500
324
-
325
- reference_paths.append(ref_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  except Exception as e:
327
- return jsonify({"error": f"ユーザー {user} の音声取得に失敗しました", "details": str(e)}), 500
328
-
329
- # 複数人の場合は参照パスのリストを、1人の場合は単一のパスを渡す
330
- if len(users) > 1:
331
- print("複数人の場合の処理")
332
- matched_times, merged_segments = process.process_multi_audio(reference_paths, audio_path, users, threshold=0.05)
333
- total_audio = transcripter.save_marged_segments(merged_segments)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  # 各メンバーのrateを計算
335
- total_time = sum(matched_times)
336
- rates = [(time / total_time) * 100 if total_time > 0 else 0 for time in matched_times]
337
-
338
- # ユーザー名と話した割合をマッピング
339
- user_rates = {users[i]: rates[i] for i in range(len(users))}
340
- return jsonify({"rates": rates, "user_rates": user_rates}), 200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  else:
342
- matched_time, unmatched_time, merged_segments = process.process_audio(reference_paths[0], audio_path, users[0], threshold=0.05)
343
- total_audio = transcripter.save_marged_segments(merged_segments)
344
- print("単一ユーザーの処理")
 
 
 
 
 
 
 
 
 
345
  total_time = matched_time + unmatched_time
346
  rate = (matched_time / total_time) * 100 if total_time > 0 else 0
347
- return jsonify({"rate": rate, "user": users[0]}), 200
348
-
 
 
 
 
 
 
 
349
  except Exception as e:
350
- print("Error in /upload_audio:", str(e))
351
- return jsonify({"error": "サーバーエラー", "details": str(e)}), 500
 
 
352
 
353
  # ユーザー選択画面(テンプレート: userSelect.html)
354
  @app.route('/')
 
278
  @app.route('/upload_audio', methods=['POST'])
279
  def upload_audio():
280
  global total_audio
281
+ global users # グローバル変数のusersを更新する場合
282
+
283
  try:
284
  data = request.get_json()
285
  if not data or 'audio_data' not in data:
286
+ print("エラー: リクエストに audio_data が含まれていません。")
287
  return jsonify({"error": "音声データがありません"}), 400
 
 
 
 
 
288
 
289
+ # リクエストからユーザーリストを取得(指定がなければ現在のusersを使用)
290
+ # リクエストごとにユーザーを指定する方が安全
291
+ request_users = data.get('selected_users', []) # .getでキーが存在しない場合も安全に
292
+ if request_users:
293
+ current_users = request_users # リクエストで指定されたユーザーを使用
294
+ print(f"リクエストから選択されたユーザー: {current_users}")
295
+ else:
296
+ # グローバル変数を使う場合(非推奨)
297
+ # current_users = users
298
+ # print(f"グローバル変数からユーザーを使用: {current_users}")
299
+ # グローバル変数ではなく、エラーにする方が安全
300
+ print("エラー: リクエストに selected_users が指定されていません。")
301
+ return jsonify({"error": "選択されたユーザーが指定されていません"}), 400
302
+
303
+ if not current_users:
304
+ print("エラー: 処理対象のユーザーがいません。")
305
  return jsonify({"error": "選択されたユーザーがいません"}), 400
306
 
307
  # Base64デコードして音声バイナリを取得
308
  audio_binary = base64.b64decode(data['audio_data'])
309
+
310
+ # 一時ファイルに音声を保存
311
+ upload_name = 'uploaded_audio_segment' # 一時ファイル名
312
+ audio_dir = "/tmp/justalk_audio_data" # 一時ディレクトリ名(環境に合わせて変更可)
313
  os.makedirs(audio_dir, exist_ok=True)
314
  audio_path = os.path.join(audio_dir, f"{upload_name}.wav")
315
  with open(audio_path, 'wb') as f:
316
  f.write(audio_binary)
317
+ print(f"一時音声ファイルを保存: {audio_path}")
318
+
319
+ print(f"処理を実行するユーザー: {current_users}")
320
+
321
+ # 参照音声用の一時ディレクトリ
322
+ temp_ref_dir = os.path.join(audio_dir, "base_audio")
323
+ os.makedirs(temp_ref_dir, exist_ok=True)
324
+
325
  # 各ユーザーの参照音声ファイルのパスをリストに格納
326
  reference_paths = []
327
+ missing_files = []
328
+ for user in current_users:
329
  try:
330
+ ref_path = os.path.join(temp_ref_dir, f"{user}.wav")
331
+ # 参照ファイルがローカルになければクラウドから取得試行
 
 
 
 
332
  if not os.path.exists(ref_path):
333
+ print(f"参照音声 {ref_path} がローカルにありません。ダウンロードを試みます...")
334
+ if not download_from_cloud(f"{user}.wav", ref_path):
335
+ print(f"エラー: {user}.wav のダウンロードに失敗しました。")
336
+ missing_files.append(user)
337
+ continue # 次のユーザーへ
338
+ else:
339
+ print(f"クラウドから {user}.wav を {ref_path} にダウンロードしました")
340
+
341
+ # 再度存在確認 (ダウンロード成功したか)
342
+ if os.path.exists(ref_path):
343
+ reference_paths.append(ref_path)
344
+ else:
345
+ # 最終的にファイルが見つからなかった場合
346
+ print(f"エラー: ユーザー '{user}' の参照音���ファイルが見つかりません: {ref_path}")
347
+ missing_files.append(user)
348
+
349
  except Exception as e:
350
+ print(f"エラー: ユーザー '{user}' の参照音声準備中にエラーが発生しました: {e}")
351
+ # エラーが発生したユーザーをリストに追加
352
+ missing_files.append(user)
353
+ # エラーの詳細をログに出力
354
+ traceback.print_exc()
355
+
356
+ # 必要な参照ファイルが不足している場合はエラーを返す
357
+ if missing_files:
358
+ return jsonify({"error": f"一部ユーザーの参照音声が見つかりません: {', '.join(missing_files)}"}), 500
359
+ # 処理に必要なユーザー数と参照ファイル数が一致しない場合もエラー
360
+ if len(reference_paths) != len(current_users):
361
+ return jsonify({"error": f"参照音声ファイルの数({len(reference_paths)})がユーザー数({len(current_users)})と一致しません"}), 500
362
+
363
+
364
+ # --- ユーザー数に応じて処理分岐 ---
365
+ if len(current_users) > 1:
366
+ # --- 複数人処理 ---
367
+ print(f"複数人 ({len(current_users)}人) の音声処理を開始します。")
368
+ try:
369
+ matched_times, merged_segments = process.process_multi_audio(
370
+ reference_paths, audio_path, current_users, threshold=0.05
371
+ )
372
+ # total_audio = transcripter.save_marged_segments(merged_segments) # 必要なら有効化
373
+ except Exception as proc_e:
374
+ print(f"エラー: process_multi_audio でエラーが発生しました: {proc_e}")
375
+ traceback.print_exc()
376
+ return jsonify({"error": "音声処理中にエラーが発生しました(multi)", "details": str(proc_e)}), 500
377
+
378
  # 各メンバーのrateを計算
379
+ total_matched_time = sum(matched_times) # 発話時間の合計
380
+ user_rates = {} # { 'ユーザー名': rate } 形式の辞書
381
+
382
+ print(f"各ユーザーの発話時間 (秒): {dict(zip(current_users, matched_times))}")
383
+ print(f"発話時間の合計 (秒): {total_matched_time:.2f}")
384
+
385
+ # 各ユーザーの割合を計算
386
+ for i in range(len(current_users)):
387
+ user = current_users[i]
388
+ time = matched_times[i]
389
+ # 発話合計時間が0より大きい場合のみ割合計算
390
+ rate = (time / total_matched_time) * 100 if total_matched_time > 0 else 0
391
+ # 念のため rate が 0 未満にならないようにする
392
+ user_rates[user] = max(0, rate)
393
+
394
+ print(f"計算直後の user_rates: {user_rates}")
395
+
396
+ # --- 'その他' の計算と追加 ---
397
+ current_total_rate = sum(user_rates.values()) # 計算されたレートの合計
398
+ print(f"計算後の合計レート: {current_total_rate:.2f}%")
399
+
400
+ # 合計が100%未満の場合 (浮動小数点誤差を考慮)
401
+ # かつ合計が負でないことを確認(通常ありえないが念のため)
402
+ if current_total_rate < 99.99 and current_total_rate >= 0:
403
+ other_rate = 100.0 - current_total_rate
404
+ user_rates['その他'] = other_rate # 'その他' を追加
405
+ print(f"'その他' ({other_rate:.2f}%) を追加しました。")
406
+
407
+ # オプション: 合計が100%をわずかに超える場合の正規化 (必要に応じてコメント解除)
408
+ elif current_total_rate > 100.01:
409
+ print(f"警告: 合計レートが {current_total_rate:.2f}% で100%を超えました。正規化します。")
410
+ factor = 100.0 / current_total_rate
411
+ normalized_rates = {}
412
+ temp_sum = 0
413
+ keys = list(user_rates.keys())
414
+ for i, user in enumerate(keys):
415
+ if i < len(keys) - 1:
416
+ normalized_rate = user_rates[user] * factor
417
+ normalized_rates[user] = normalized_rate
418
+ temp_sum += normalized_rate
419
+ else:
420
+ normalized_rates[user] = max(0, 100.0 - temp_sum) # 最後の要素で調整、0未満防止
421
+ user_rates = normalized_rates
422
+ print(f"正規化後の user_rates: {user_rates}")
423
+
424
+ print(f"最終的に返す user_rates: {user_rates}")
425
+ # React側が扱いやすい user_rates 形式で返す
426
+ return jsonify({"user_rates": user_rates}), 200
427
+
428
  else:
429
+ # --- 単一ユーザー処理 ---
430
+ print(f"単一ユーザー ({current_users[0]}) の音声処理を開始します。")
431
+ try:
432
+ matched_time, unmatched_time, merged_segments = process.process_audio(
433
+ reference_paths[0], audio_path, current_users[0], threshold=0.05
434
+ )
435
+ # total_audio = transcripter.save_marged_segments(merged_segments) # 必要なら有効化
436
+ except Exception as proc_e:
437
+ print(f"エラー: process_audio でエラーが発生しました: {proc_e}")
438
+ traceback.print_exc()
439
+ return jsonify({"error": "音声処理中にエラーが発生しました(single)", "details": str(proc_e)}), 500
440
+
441
  total_time = matched_time + unmatched_time
442
  rate = (matched_time / total_time) * 100 if total_time > 0 else 0
443
+ # レートを 0-100 の範囲に収める
444
+ rate = max(0, min(100, rate))
445
+ silent_rate = 100.0 - rate
446
+
447
+ # シングルユーザーでも user_rates 形式で統一して返す
448
+ user_rates = {current_users[0]: rate, '無音': silent_rate}
449
+ print(f"単一ユーザー、user_rates形式で返す: {user_rates}")
450
+ return jsonify({"user_rates": user_rates}), 200
451
+
452
  except Exception as e:
453
+ print(f"エラー: /upload_audio の処理中に予期せぬエラーが発生しました: {e}")
454
+ # エラーの詳細をスタックトレース付きでログに出力
455
+ traceback.print_exc()
456
+ return jsonify({"error": "サーバー内部エラーが発生しました", "details": str(e)}), 500
457
 
458
  # ユーザー選択画面(テンプレート: userSelect.html)
459
  @app.route('/')