|
|
import whisper |
|
|
import streamlit as st |
|
|
import librosa |
|
|
import numpy as np |
|
|
import matplotlib.pyplot as plt |
|
|
from pydub import AudioSegment |
|
|
from transformers import pipeline |
|
|
import os |
|
|
|
|
|
|
|
|
sentiment_analyzer = pipeline("sentiment-analysis") |
|
|
|
|
|
|
|
|
st.title("🎤 Audio Sentiment Analysis") |
|
|
st.write("Upload multiple MP3 files to analyze sentiment and tone.") |
|
|
|
|
|
|
|
|
uploaded_files = st.file_uploader("Choose MP3 files", type=["mp3"], accept_multiple_files=True) |
|
|
|
|
|
|
|
|
def analyze_audio(file_path): |
|
|
|
|
|
audio = AudioSegment.from_mp3(file_path) |
|
|
wav_path = file_path.replace(".mp3", ".wav") |
|
|
audio.export(wav_path, format="wav") |
|
|
|
|
|
|
|
|
y, sr = librosa.load(wav_path, sr=None) |
|
|
|
|
|
|
|
|
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13) |
|
|
mfccs_mean = np.mean(mfccs, axis=1) |
|
|
|
|
|
|
|
|
model = whisper.load_model("base") |
|
|
result = model.transcribe(wav_path) |
|
|
transcription = result['text'] |
|
|
|
|
|
|
|
|
sentiment_result = sentiment_analyzer(transcription) if transcription else [{"label": "NEGATIVE", "score": 0.5}] |
|
|
|
|
|
|
|
|
os.remove(wav_path) |
|
|
|
|
|
return sentiment_result[0], mfccs_mean, mfccs, y, sr, transcription |
|
|
|
|
|
|
|
|
if uploaded_files: |
|
|
|
|
|
os.makedirs("temp", exist_ok=True) |
|
|
|
|
|
|
|
|
fig, ax = plt.subplots(figsize=(10, 6)) |
|
|
|
|
|
for uploaded_file in uploaded_files: |
|
|
|
|
|
file_path = f"temp/{uploaded_file.name}" |
|
|
with open(file_path, "wb") as f: |
|
|
f.write(uploaded_file.getbuffer()) |
|
|
|
|
|
|
|
|
sentiment, mfccs_mean, mfccs, audio_data, sample_rate, transcription = analyze_audio(file_path) |
|
|
|
|
|
|
|
|
st.subheader(f"📊 Sentiment Analysis Result for {uploaded_file.name}") |
|
|
st.write(f"**Transcription:** {transcription}") |
|
|
st.write(f"**Sentiment:** {sentiment['label']}") |
|
|
st.write(f"**Confidence:** {sentiment['score']:.2f}") |
|
|
|
|
|
|
|
|
sentiment_score = sentiment['score'] if sentiment['label'] == 'POSITIVE' else 1 - sentiment['score'] |
|
|
|
|
|
|
|
|
ax.plot(np.linspace(0, len(audio_data) / sample_rate, len(audio_data)), [sentiment_score] * len(audio_data), label="Agent's Tone", linestyle='-', color='b') |
|
|
|
|
|
|
|
|
|
|
|
mfccs_mean = np.mean(mfccs, axis=1) |
|
|
|
|
|
|
|
|
ax.plot(np.linspace(0, len(mfccs_mean), len(mfccs_mean)), mfccs_mean, label="Patient's Tone Curve (MFCCs)", linestyle='--', color='r') |
|
|
|
|
|
|
|
|
ax.set_xlabel("Time (seconds) / MFCC Coefficients") |
|
|
ax.set_ylabel("Score / Mean MFCC Value") |
|
|
ax.set_title("Agent Tone & Patient Tone Curve") |
|
|
ax.legend() |
|
|
|
|
|
|
|
|
st.pyplot(fig) |
|
|
|
|
|
|
|
|
os.remove(file_path) |
|
|
|