JusTalk / app.py
buletomato25
multi_reset
776d9ef
raw
history blame
9.53 kB
from flask import Flask, request, jsonify, render_template, send_from_directory
import base64
from pydub import AudioSegment # 変換用にpydubをインポート
import os
import shutil
from process import AudioProcessor
from transcription import TranscriptionMaker
from analyze import TextAnalyzer
import json
process=AudioProcessor()
transcripter = TranscriptionMaker()
app = Flask(__name__)
users = []
transcription_text=""
harassment_keywords = [
"バカ", "馬鹿", "アホ", "死ね", "クソ", "うざい",
"きもい", "キモい", "ブス", "デブ", "ハゲ",
"セクハラ", "パワハラ", "モラハラ"
]
total_audio = ""
# トップページ(テンプレート: index.html)
@app.route('/')
@app.route('/index', methods=['GET', 'POST'])
def index():
return render_template('index.html', users = users)
# フィードバック画面(テンプレート: feedback.html)
@app.route('/feedback', methods=['GET', 'POST'])
def feedback():
return render_template('feedback.html')
# 会話詳細画面(テンプレート: talkDetail.html)
@app.route('/talk_detail', methods=['GET', 'POST'])
def talk_detail():
return render_template('talkDetail.html')
# 音声登録画面(テンプレート: userRegister.html)
@app.route('/userregister', methods=['GET', 'POST'])
def userregister():
return render_template('userRegister.html')
#人数確認
@app.route('/confirm', methods=['GET']) # 基本的にGETで取得する想定なので、GETのみに変更
def confirm():
return jsonify({'members': users}), 200
#リセット画面(テンプレート: reset.html)
@app.route('/reset_html', methods=['GET', 'POST'])
def reset_html():
return render_template('reset.html')
#メンバー削除&累積音声削除
@app.route('/reset_member', methods=['GET', 'POST'])
def reset_member():
global users
global total_audio
print(total_audio)
process.delete_files_in_directory(total_audio)
try:
data = request.get_json()
if not data or "names" not in data:
return jsonify({"status": "error", "message": "Invalid request body"}), 400 # 400 Bad Request
names = data.get("names", [])
base_audio_dir = "/tmp/data/base_audio"
for name in names:
file_path = os.path.join(base_audio_dir, f"{name}.wav")
if os.path.exists(file_path):
try:
os.remove(file_path)
print(f"{file_path} を削除しました。")
except Exception as e:
print(f"削除中にエラーが発生しました: {e}")
# ファイル削除に失敗した場合も、エラーを返す
return jsonify({"status": "error", "message": f"Failed to delete {name}: {e}"}), 500
else:
print(f"ファイルが存在しません: {file_path}")
# usersリストを更新
users = [u for u in users if u not in names]
# 成功した場合のレスポンス
return jsonify({"status": "success", "message": "Members deleted successfully", "users": users}), 200 # 200 OK
except Exception as e:
print(f"An unexpected error occurred: {e}")
return jsonify({"status": "error", "message": f"Internal server error: {e}"}), 500 # 500 Internal Server Error
# 書き起こし作成エンドポイント
@app.route('/transcription',methods =['GET','POST'])
def transcription():
global transcription_text
global total_audio
print(total_audio)
try:
transcription_text = transcripter.create_transcription(total_audio)
print(transcription_text)
with open(transcription_text,'r',encoding='utf-8') as file:
file_content = file.read()
print(file_content)
return jsonify({'transcription': file_content}),200
except Exception as e:
return jsonify({"error": str(e)}),500
# AI分析エンドポイント
@app.route('/analyze',methods =['GET','POST'])
def analyze():
global transcription_text
analyzer = TextAnalyzer(transcription_text, harassment_keywords)
api_key = os.environ.get("DEEPSEEK")
if api_key is None:
raise ValueError("DEEPSEEK_API_KEY が設定されていません。")
results = analyzer.analyze(api_key=api_key)
print(json.dumps(results, ensure_ascii=False, indent=2))
if "deepseek_analysis" in results and results["deepseek_analysis"]:
deepseek_data = results["deepseek_analysis"]
conversation_level = deepseek_data.get("conversationLevel")
harassment_present = deepseek_data.get("harassmentPresent")
harassment_type = deepseek_data.get("harassmentType")
repetition = deepseek_data.get("repetition")
pleasantConversation = deepseek_data.get("pleasantConversation")
blameOrHarassment = deepseek_data.get("blameOrHarassment")
print("\n--- DeepSeek 分析結果 ---")
print(f"会話レベル: {conversation_level}")
print(f"ハラスメントの有無: {harassment_present}")
print(f"ハラスメントの種類: {harassment_type}")
print(f"繰り返しの程度: {repetition}")
print(f"会話の心地よさ: {pleasantConversation}")
print(f"非難またはハラスメントの程度: {blameOrHarassment}")
return jsonify({"results": results}),200
# 音声アップロード&解析エンドポイント
@app.route('/upload_audio', methods=['POST'])
def upload_audio():
global total_audio
try:
data = request.get_json()
# name か users のいずれかが必須。どちらも無い場合はエラー
if not data or 'audio_data' not in data or ('name' not in data and 'users' not in data):
return jsonify({"error": "音声データまたは名前がありません"}), 400
# Base64デコードして音声バイナリを取得
audio_binary = base64.b64decode(data['audio_data'])
upload_name = 'tmp'
audio_dir = "/tmp/data"
os.makedirs(audio_dir, exist_ok=True)
audio_path = os.path.join(audio_dir, f"{upload_name}.wav")
with open(audio_path, 'wb') as f:
f.write(audio_binary)
print(users)
# 各ユーザーの参照音声ファイルのパスをリストに格納
reference_paths = []
base_audio_dir = "/tmp/data/base_audio"
for user in users:
ref_path = os.path.abspath(os.path.join(base_audio_dir, f"{user}.wav"))
if not os.path.exists(ref_path):
return jsonify({"error": "参照音声ファイルが見つかりません", "details": ref_path}), 500
reference_paths.append(ref_path)
# 複数人の場合は参照パスのリストを、1人の場合は単一のパスを渡す
if len(users) > 1:
print("複数人の場合の処理")
matched_times, segments_dir = process.process_multi_audio(reference_paths, audio_path, threshold=0.05)
total_audio = transcripter.merge_segments(segments_dir)
# 各メンバーのrateを計算
total_time = sum(matched_times)
rates = [(time / total_time) * 100 if total_time > 0 else 0 for time in matched_times]
return jsonify({"rates": rates}), 200
else:
matched_time, unmatched_time, segments_dir = process.process_audio(reference_paths[0], audio_path, threshold=0.05)
total_audio = transcripter.merge_segments(segments_dir)
total_time = matched_time + unmatched_time
rate = (matched_time / total_time) * 100 if total_time > 0 else 0
return jsonify({"rate": rate}), 200
except Exception as e:
print("Error in /upload_audio:", str(e))
return jsonify({"error": "サーバーエラー", "details": str(e)}), 500
@app.route('/reset', methods=['GET'])
def reset():
global users
users=[]
return 200
@app.route('/upload_base_audio', methods=['POST'])
def upload_base_audio():
global users#グローバル変数を編集できるようにする
try:
data = request.get_json()
if not data or 'audio_data' not in data or 'name' not in data:
return jsonify({"error": "音声データまたは名前がありません"}), 400
name = data['name'] # 名前を取得
print(name)
users.append(name)
users=list(set(users))#重複排除
print(users)
audio_path=process.save_audio_from_base64(
base64_audio=data['audio_data'], # 音声データ
output_dir= "/tmp/data/base_audio", #保存先
output_filename=f"{name}.wav" # 固定ファイル名(必要に応じて generate_filename() で一意のファイル名に変更可能)
)
return jsonify({"state": "Registration Success!", "path": audio_path}), 200
except Exception as e:
print("Error in /upload_base_audio:", str(e))
return jsonify({"error": "サーバーエラー", "details": str(e)}), 500
if __name__ == '__main__':
port = int(os.environ.get("PORT", 7860))
app.run(debug=True, host="0.0.0.0", port=port)