import os import json import re import streamlit as st import plotly.graph_objects as go from google.cloud import storage from google.auth import credentials from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer from scipy.ndimage import gaussian_filter1d from datetime import timedelta, datetime gcp_credentials = os.getenv('GCP_CREDENTIALS') credentials_dict = json.loads(gcp_credentials) creds = credentials.Credentials.from_service_account_info(credentials_dict) client = storage.Client(credentials=creds) bucket_name = "kapnotes" bucket = client.bucket(bucket_name) def get_client_names(): blobs = list(bucket.list_blobs(prefix="")) client_names = set() for blob in blobs: client_name = blob.name.split("/")[0] client_names.add(client_name) return sorted(client_names) def login(): st.markdown(""" """, unsafe_allow_html=True) st.markdown("

KAP NOTES

", unsafe_allow_html=True) client_names = get_client_names() with st.form(key="login_form"): client_name = st.selectbox("Select Client", client_names) min_date = datetime(2000, 1, 1) date_input = st.date_input("Enter the Date", min_value=min_date, max_value=datetime.today()) submit_button = st.form_submit_button("Sign In") if submit_button: date_str = date_input.strftime("%d-%m-%Y") date_str = date_str.replace("-", "_") st.session_state.client_name = client_name st.session_state.date = date_str st.session_state.logged_in = True st.rerun() if 'logged_in' not in st.session_state: st.session_state.logged_in = False if not st.session_state.logged_in: login() else: st.set_page_config(page_title="Kap Notes", layout="wide") css = ''' ''' st.markdown(css, unsafe_allow_html=True) client_name = st.session_state.client_name date = st.session_state.date summary_blob_name = f"{client_name}/{date.replace('_', '-')}/summary.txt" transcription_blob_name = f"{client_name}/{date.replace('_', '-')}/transcription.txt" audio_blob_name = f"{client_name}/{date.replace('_', '-')}/audio/audio.wav" bucket = client.bucket(bucket_name) summary_blob = bucket.blob(summary_blob_name) summary_content = summary_blob.download_as_text() audio_blob = bucket.blob(audio_blob_name) audio_url = audio_blob.generate_signed_url(expiration=timedelta(hours=1), method='GET') summary = re.search(r"\*\*Summary\*\*\n(.*?)\n\n", summary_content, re.DOTALL).group(1).strip() key_points = re.findall(r"- (.*?)\n", re.search(r"\*\*Key Points\*\*\n(.*?)\n\n", summary_content, re.DOTALL).group(1)) action_items = re.findall(r"- (.*?)\n", re.search(r"\*\*Action Items\*\*\n(.*)", summary_content, re.DOTALL).group(1)) transcription_blob = bucket.blob(transcription_blob_name) with transcription_blob.open("r") as file: meeting_data = json.load(file) speaker_data = {} total_talktime = 0 for entry in meeting_data: speaker = entry["speaker"] duration = entry["end"] - entry["start"] text = entry["text"] total_talktime += duration if speaker not in speaker_data: speaker_data[speaker] = {"talktime": 0, "text": "", "words": 0} speaker_data[speaker]["talktime"] += duration speaker_data[speaker]["text"] += " " + text speaker_data[speaker]["words"] += len(text.split()) for speaker, data in speaker_data.items(): data["word_per_minute"] = round((data["words"] / data["talktime"] * 60), 2) data["talktime_percentage"] = round((data["talktime"] / total_talktime * 100), 2) combined_text = " ".join(data["text"] for data in speaker_data.values()) analyzer = SentimentIntensityAnalyzer() sentences = combined_text.split('.') sentiment_polarity = [analyzer.polarity_scores(sentence)["compound"] for sentence in sentences if sentence.strip()] smoothed_polarity = gaussian_filter1d(sentiment_polarity, sigma=2) st.title("Kap Notes - Unveiling the story behind your meeting") st.markdown(f"### Summary\n
{summary}
", unsafe_allow_html=True) st.markdown("### Meeting Highlights") st.markdown( f"
" + "
".join(f"• {point}" for point in key_points) + "
", unsafe_allow_html=True ) st.markdown("### Actionable Items") st.markdown( f"
" + "
".join(f"• {item}" for item in action_items) + "
", unsafe_allow_html=True ) st.markdown("### Comments") if 'comments' not in st.session_state: st.session_state.comments = [] def add_comment(comment): st.session_state.comments.append({"name": "", "comment": comment, "date": datetime.now().strftime("%d, %b %Y")}) if 'name' not in st.session_state: st.session_state.name = "" if 'comment' not in st.session_state: st.session_state.comment = "" for comment in st.session_state.comments: st.markdown( f"""
Admin {comment['date']}
{comment['comment']}
""", unsafe_allow_html=True) with st.form(key="comment_form"): st.markdown('
', unsafe_allow_html=True) comment_input = st.text_area("Your Comment", height=100, value=st.session_state.comment) submit_button = st.form_submit_button("Submit") st.markdown('
', unsafe_allow_html=True) if submit_button: if not comment_input: st.error("Enter your comment") else: add_comment(comment_input) st.session_state.comment = "" with st.sidebar: speaker_names = list(speaker_data.keys()) talk_time_percentages = [data["talktime_percentage"] for data in speaker_data.values()] color_palette = ["#A3BFF1", "#F4A7B9", "#C4F1D2", "#D6A7F2", "#FFD5A6", "#9BE1E6", "#F4A3C0", "#C1E7B4", "#F1D0FF", "#F9E9A6"] speaker_colors = {speaker: color_palette[i % len(color_palette)] for i, speaker in enumerate(speaker_names)} st.markdown(f"""

Listen to the Meeting Audio

""", unsafe_allow_html=True) st.title("Chat Conversation") with st.expander("Click to view the chat conversation", expanded=False): chat_conversation = "" for index, entry in enumerate(meeting_data): speaker = entry["speaker"] text = entry["text"] talk_time = entry["end"] - entry["start"] speaker_color = speaker_colors[speaker] chat_conversation += f"""
{speaker} {talk_time:.2f} mins
{text}
""" st.markdown(chat_conversation, unsafe_allow_html=True) fig = go.Figure(data=[go.Pie(labels=speaker_names, values=talk_time_percentages, marker=dict(colors=list(speaker_colors.values())), hole=0.3)]) fig.update_layout( title="Speaker Analytics", showlegend=True, legend=dict( orientation="h", yanchor="top", y=-0.2, xanchor="center", x=0.5 ) ) st.plotly_chart(fig) st.markdown("### Sentiment Analysis of the Meeting") fig = go.Figure() fig.add_trace(go.Scatter(x=list(range(len(smoothed_polarity))), y=smoothed_polarity, mode='lines', name='Sentiment', line=dict(color='blue'))) fig.update_layout( xaxis=dict(title="Time (in seconds)"), yaxis=dict(title="Sentiment Score", range=[-1, 1]), ) st.plotly_chart(fig)