JustusI commited on
Commit
d37d466
·
verified ·
1 Parent(s): 51c63d2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -0
app.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import tempfile
3
+ import os
4
+ import yt_dlp
5
+ from moviepy.editor import VideoFileClip
6
+ import openai
7
+
8
+ # Set your OpenAI API key (make sure it's set in Hugging Face Spaces secrets)
9
+ openai.api_key = os.getenv("OPENAI_API_KEY")
10
+
11
+ # ---------------------------
12
+ # Helper Functions
13
+ # ---------------------------
14
+ def download_video(youtube_url: str, output_path: str) -> str:
15
+ """Download a YouTube video using yt-dlp and save it to the given output path."""
16
+ try:
17
+ ydl_opts = {
18
+ 'format': 'best',
19
+ 'outtmpl': os.path.join(output_path, '%(title)s.%(ext)s'),
20
+ 'noplaylist': True,
21
+ 'quiet': True
22
+ }
23
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
24
+ info = ydl.extract_info(youtube_url, download=True)
25
+ title = info.get('title', 'video')
26
+ video_path = os.path.join(output_path, f"{title}.mp4")
27
+ return video_path
28
+ except Exception as e:
29
+ st.error(f"Error downloading video: {e}")
30
+ return None
31
+
32
+ def extract_audio(video_path: str) -> str:
33
+ """Extract audio from the video file and save as MP3."""
34
+ try:
35
+ # Sanitize filename if needed (e.g., replace problematic characters)
36
+ safe_video_path = video_path.replace("|", "_").replace(":", "_")
37
+ clip = VideoFileClip(safe_video_path)
38
+ audio_path = safe_video_path.replace(".mp4", ".mp3")
39
+ clip.audio.write_audiofile(audio_path, codec='mp3')
40
+ clip.close()
41
+ return audio_path
42
+ except Exception as e:
43
+ st.error(f"Error extracting audio: {e}")
44
+ return None
45
+
46
+ def transcribe_audio(audio_path: str) -> str:
47
+ """Transcribe the audio to text using OpenAI's Whisper API."""
48
+ try:
49
+ with open(audio_path, "rb") as audio_file:
50
+ transcript = openai.Audio.transcribe("whisper-1", audio_file)
51
+ return transcript['text']
52
+ except Exception as e:
53
+ st.error(f"Error transcribing audio: {e}")
54
+ return ""
55
+
56
+ def generate_summary(transcript_text: str) -> str:
57
+ """Generate a concise summary of the transcript using OpenAI."""
58
+ prompt = f"Summarize the following document in a concise manner, highlighting the key points that a student should know:\n\n{transcript_text}"
59
+ messages = [
60
+ {"role": "system", "content": "You are an educational assistant."},
61
+ {"role": "user", "content": prompt}
62
+ ]
63
+ completion = openai.ChatCompletion.create(model="gpt-4o-mini", messages=messages)
64
+ return completion.choices[0].message.content.strip()
65
+
66
+ def get_chat_response(transcript_text: str, conversation_history: list, user_query: str) -> str:
67
+ """Generate a chat response using the transcript as context."""
68
+ messages = conversation_history + [
69
+ {"role": "user", "content": f"Based on the following document:\n\n{transcript_text}\n\nQuestion: {user_query}"}
70
+ ]
71
+ completion = openai.ChatCompletion.create(model="gpt-4o-mini", messages=messages)
72
+ return completion.choices[0].message.content.strip()
73
+
74
+ # ---------------------------
75
+ # Sidebar: Input Options
76
+ # ---------------------------
77
+ st.sidebar.title("Video Input Options")
78
+
79
+ input_mode = st.sidebar.radio("Select Input Type", ("Upload Video", "YouTube URL"))
80
+
81
+ transcript_text = ""
82
+ if input_mode == "Upload Video":
83
+ uploaded_video = st.sidebar.file_uploader("Upload a video file (MP4, max 50MB)", type="mp4")
84
+ elif input_mode == "YouTube URL":
85
+ youtube_url = st.sidebar.text_input("Enter YouTube video URL:")
86
+
87
+ # ---------------------------
88
+ # Process Video Input
89
+ # ---------------------------
90
+ if input_mode == "Upload Video" and uploaded_video is not None:
91
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp:
92
+ tmp.write(uploaded_video.read())
93
+ video_path = tmp.name
94
+ st.sidebar.success("Video uploaded successfully!")
95
+ audio_path = extract_audio(video_path)
96
+ if audio_path:
97
+ transcript_text = transcribe_audio(audio_path)
98
+ if transcript_text:
99
+ st.sidebar.success("Audio transcribed successfully!")
100
+ elif input_mode == "YouTube URL" and youtube_url:
101
+ with tempfile.TemporaryDirectory() as temp_dir:
102
+ video_path = download_video(youtube_url, temp_dir)
103
+ if video_path:
104
+ st.sidebar.success("Video downloaded successfully!")
105
+ audio_path = extract_audio(video_path)
106
+ if audio_path:
107
+ transcript_text = transcribe_audio(audio_path)
108
+ if transcript_text:
109
+ st.sidebar.success("Audio transcribed successfully!")
110
+
111
+ if transcript_text:
112
+ st.session_state.transcript_text = transcript_text
113
+
114
+ # ---------------------------
115
+ # Sidebar: Action Selection
116
+ # ---------------------------
117
+ st.sidebar.title("Select Action")
118
+ action_mode = st.sidebar.radio("Choose Action", ("Summary", "Chat"))
119
+
120
+ # ---------------------------
121
+ # Session State Initialization for Chat
122
+ # ---------------------------
123
+ if "chat_history" not in st.session_state:
124
+ st.session_state.chat_history = [{"role": "assistant", "content": "Hi, how can I help you with the video content?"}]
125
+
126
+ # ---------------------------
127
+ # Main Display Area
128
+ # ---------------------------
129
+ st.title("Video-based Study Companion")
130
+
131
+ if "transcript_text" not in st.session_state or not st.session_state.transcript_text:
132
+ st.info("Please provide a video input from the sidebar to begin.")
133
+ else:
134
+ transcript_text = st.session_state.transcript_text
135
+ if action_mode == "Summary":
136
+ st.header("Summary & Key Points")
137
+ with st.spinner("Generating summary..."):
138
+ summary = generate_summary(transcript_text)
139
+ st.write(summary)
140
+ elif action_mode == "Chat":
141
+ st.header("Chat with Your Study Companion")
142
+ for msg in st.session_state.chat_history:
143
+ st.chat_message(msg["role"]).write(msg["content"])
144
+ user_query = st.chat_input("Ask a question about the video content:")
145
+ if user_query:
146
+ st.session_state.chat_history.append({"role": "user", "content": user_query})
147
+ st.chat_message("user").write(user_query)
148
+ with st.spinner("Processing your question..."):
149
+ response = get_chat_response(transcript_text, st.session_state.chat_history, user_query)
150
+ st.session_state.chat_history.append({"role": "assistant", "content": response})
151
+ st.chat_message("assistant").write(response)