nolahardika's picture
Update app.py
3837e66 verified
Raw
History Blame
5.15 kB
import gradio as gr
import whisper
import subprocess
import os
import uuid
import wave
import contextlib
from validation import validate_transcription
from transformers import pipeline
# Load model NLP emosi
emotion_model = pipeline("text-classification", model="cardiffnlp/twitter-roberta-base-emotion", top_k=1)
# Cek ffmpeg
def ffmpeg_available():
try:
subprocess.run(["ffmpeg", "-version"], capture_output=True)
return True
except FileNotFoundError:
return False
# Load Whisper
model = whisper.load_model("base")
# Analisis emosi sederhana
def detect_emotion(text):
emotions = {
"sedih": "sedih",
"lelah": "lelah",
"bingung": "bingung",
"tidak semangat": "putus asa",
"baik-baik saja": "positif"
}
for keyword, label in emotions.items():
if keyword in text.lower():
return label
return "netral"
# Respons chatbot berdasarkan emosi
def generate_response(text, emotion):
responses = {
"sedih": "Terima kasih sudah berbagi. Apa yang membuatmu merasa sedih?",
"lelah": "Kamu merasa lelah ya... Mau cerita lebih lanjut?",
"bingung": "Wajar kok merasa bingung. Aku di sini untuk mendengarkan.",
"putus asa": "Aku paham. Kadang kita butuh waktu untuk memulihkan diri.",
"positif": "Senang mendengarnya. Kalau ada yang ingin dibicarakan, aku siap mendengarkan.",
"netral": "Terima kasih sudah berbagi. Aku di sini kalau kamu ingin cerita lebih banyak."
}
return responses.get(emotion, responses["netral"])
# Durasi audio
def get_audio_duration(audio_path):
try:
with contextlib.closing(wave.open(audio_path, 'r')) as f:
frames = f.getnframes()
rate = f.getframerate()
duration = frames / float(rate)
return round(duration, 2)
except Exception:
return None
# Fungsi utama
def transcribe_audio(audio_file):
ffmpeg_ok = ffmpeg_available()
file_ext = os.path.splitext(audio_file)[1].lower()
safe_formats = [".wav", ".flac"]
if not ffmpeg_ok and file_ext not in safe_formats:
return (
f"⚠️ Format {file_ext} tidak didukung tanpa ffmpeg.",
None,
None,
None,
None
)
duration = get_audio_duration(audio_file)
if duration is None:
return "❌ Gagal membaca durasi audio.", None, None, None, None
if duration < 1.5:
return f"⚠️ Audio terlalu pendek ({duration} detik).", None, None, None, None
try:
result = model.transcribe(audio_file)
raw_text = result["text"]
language = result["language"]
# Validasi transkripsi
is_valid, validated_text_or_msg = validate_transcription(raw_text)
if not is_valid:
return (
f"⚠️ Transkripsi tidak valid: {validated_text_or_msg}",
raw_text,
None,
validated_text_or_msg,
"tidak terdeteksi"
)
# Simpan ke file
file_id = str(uuid.uuid4())[:8]
output_path = f"/tmp/transcript_{file_id}.txt"
with open(output_path, "w", encoding="utf-8") as f:
f.write(validated_text_or_msg)
# Analisis emosi
emotion = detect_emotion(validated_text_or_msg)
# Respons chatbot
response = generate_response(validated_text_or_msg, emotion)
return (
f"βœ… Transkripsi selesai. Bahasa: **{language}**, Durasi: **{duration} detik**",
validated_text_or_msg,
output_path,
response,
f"🧠 Emosi terdeteksi: **{emotion}**"
)
except Exception as e:
return f"❌ Gagal transkripsi: {str(e)}", None, None, None, None
# UI dengan tema khas Indonesia
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("## πŸ—£οΈ Chatbot Suara Empatik untuk Skrining Awal Depresi")
gr.Markdown(
"""
Rekam suara langsung dari mikrofon. Chatbot akan mengenali isi percakapan,
menganalisis emosi, dan memberikan respons empatik.
Cocok untuk skrining awal kondisi psikologis secara anonim.
"""
)
gr.Markdown(
"⚠️ *Percakapan ini bersifat anonim dan hanya untuk keperluan skrining awal. "
"Tidak menggantikan diagnosis profesional.*"
)
with gr.Row():
audio_input = gr.Audio(source="microphone", type="filepath", label="πŸŽ™οΈ Rekam Suara")
file_output = gr.File(label="πŸ“„ Unduh Transkripsi")
with gr.Row():
transcript_output = gr.Textbox(label="πŸ“ Hasil Transkripsi", lines=4)
emotion_output = gr.Markdown(label="πŸ” Analisis Emosi")
response_output = gr.Textbox(label="πŸ’¬ Respons Chatbot", lines=3)
status_output = gr.Markdown(label="πŸ“Œ Status")
def chatbot_ui(audio):
return transcribe_audio(audio)
audio_input.change(fn=chatbot_ui, inputs=audio_input, outputs=[
status_output,
transcript_output,
file_output,
response_output,
emotion_output
])
demo.launch()