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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -153
app.py CHANGED
@@ -278,182 +278,79 @@ def update_all_users():
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('/')
 
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
 
355
  # ユーザー選択画面(テンプレート: userSelect.html)
356
  @app.route('/')