|
from flask import Flask, request, jsonify, render_template
|
|
from transformers import pipeline
|
|
import torch
|
|
import torchaudio
|
|
from pydub import AudioSegment
|
|
import os
|
|
import io
|
|
os.environ["HF_HUB_DISABLE_SYMLINKS_WARNING"] = "1"
|
|
from transformers import AutoModelForAudioClassification, AutoFeatureExtractor
|
|
|
|
app = Flask(__name__)
|
|
|
|
|
|
emotion_map = {
|
|
'joy': '😊 Радость',
|
|
'neutral': '😐 Нейтрально',
|
|
'anger': '😠 Злость',
|
|
'sadness': '😢 Грусть',
|
|
'surprise': '😲 Удивление'
|
|
}
|
|
|
|
|
|
os.environ["PATH"] = r"C:\ffmpeg\bin;" + os.environ["PATH"]
|
|
|
|
|
|
text_classifier = pipeline(
|
|
"text-classification",
|
|
model="cointegrated/rubert-tiny2-cedr-emotion-detection",
|
|
config="cointegrated/rubert-tiny2-cedr-emotion-detection",
|
|
tokenizer="cointegrated/rubert-tiny2-cedr-emotion-detection",
|
|
framework="pt"
|
|
)
|
|
|
|
|
|
|
|
audio_classifier = pipeline(
|
|
"audio-classification",
|
|
model="superb/hubert-large-superb-er",
|
|
device=0 if torch.cuda.is_available() else -1
|
|
)
|
|
|
|
|
|
@app.route("/")
|
|
def index():
|
|
return render_template("index.html")
|
|
|
|
@app.route("/analyze", methods=["POST"])
|
|
def analyze_text():
|
|
data = request.get_json()
|
|
text = data.get("text", "")
|
|
if not text.strip():
|
|
return jsonify({"error": "Пустой текст."}), 400
|
|
|
|
predictions = text_classifier(text)[0]
|
|
if not predictions:
|
|
return jsonify({"emotion": "❓ Не определено", "confidence": 0.0})
|
|
|
|
top_prediction = max(predictions, key=lambda x: x["score"])
|
|
label = top_prediction["label"]
|
|
confidence = round(top_prediction["score"], 2)
|
|
|
|
if confidence < 0.5:
|
|
return jsonify({"emotion": "🤔 Неуверенно", "confidence": confidence})
|
|
|
|
emotion = emotion_map.get(label, "❓ Неизвестно")
|
|
return jsonify({"emotion": emotion, "confidence": confidence})
|
|
|
|
from pydub.utils import which
|
|
|
|
|
|
if not which("ffmpeg"):
|
|
print("FFmpeg не найден в системе!")
|
|
|
|
|
|
@app.route('/analyze_audio', methods=['POST'])
|
|
def analyze_audio():
|
|
try:
|
|
if 'audio' not in request.files:
|
|
return jsonify({'error': 'Аудио файл обязателен'}), 400
|
|
|
|
audio_file = request.files['audio']
|
|
temp_path = "temp_audio.wav"
|
|
|
|
|
|
audio = AudioSegment.from_file(io.BytesIO(audio_file.read()))
|
|
audio = audio.set_frame_rate(16000).set_channels(1)
|
|
audio.export(temp_path, format="wav", codec="pcm_s16le")
|
|
|
|
|
|
result = audio_classifier(temp_path)
|
|
os.remove(temp_path)
|
|
|
|
|
|
print("Raw model output:", result)
|
|
|
|
|
|
|
|
emotion_mapping = {
|
|
'hap': 'happy',
|
|
'sad': 'sad',
|
|
'neu': 'neutral',
|
|
'ang': 'angry'
|
|
}
|
|
|
|
|
|
emotions = {v: 0.0 for v in emotion_mapping.values()}
|
|
|
|
for item in result:
|
|
label = item['label'].lower()
|
|
score = item['score']
|
|
if label in emotion_mapping:
|
|
key = emotion_mapping[label]
|
|
emotions[key] += score
|
|
|
|
|
|
total = sum(emotions.values())
|
|
if total == 0:
|
|
return jsonify({'error': 'Не удалось распознать эмоции'}), 500
|
|
|
|
emotions = {k: round(v / total, 4) for k, v in emotions.items()}
|
|
dominant_emotion = max(emotions.items(), key=lambda x: x[1])
|
|
|
|
|
|
response_map = {
|
|
'happy': '😊 Радость',
|
|
'sad': '😢 Грусть',
|
|
'angry': '😠 Злость',
|
|
'neutral': '😐 Нейтрально'
|
|
}
|
|
|
|
return jsonify({
|
|
'emotion': response_map.get(dominant_emotion[0], 'неизвестно'),
|
|
'confidence': dominant_emotion[1],
|
|
'details': emotions
|
|
})
|
|
|
|
except Exception as e:
|
|
print(f"Ошибка анализа аудио: {str(e)}")
|
|
return jsonify({'error': 'Ошибка обработки аудио'}), 500
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run(debug=True)
|
|
|
|
if __name__ == "__main__":
|
|
app.run(debug=True)
|
|
|