developer28 commited on
Commit
91c1296
Β·
verified Β·
1 Parent(s): 172f5c9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -116
app.py CHANGED
@@ -1,155 +1,156 @@
1
- # βœ… Gemini-Based Stock Recommendation Extractor (Debug-Enhanced with Fallback)
2
 
3
- import gradio as gr
4
  import os
 
5
  import tempfile
6
- import json
 
7
  import traceback
8
- import google.generativeai as genai
9
  from yt_dlp import YoutubeDL
10
 
11
- # βœ… Gemini Configuration
12
- GEMINI_MODEL = None
 
 
 
 
13
 
14
- def configure_gemini(api_key):
15
- try:
16
- genai.configure(api_key=api_key)
17
- global GEMINI_MODEL
18
- GEMINI_MODEL = genai.GenerativeModel("gemini-1.5-flash-latest")
19
- return "βœ… Gemini API key configured successfully."
20
- except Exception as e:
21
- return f"❌ Gemini configuration failed: {str(e)}"
22
 
23
- # βœ… Robust metadata extraction with fallback
 
 
 
24
 
25
- def extract_metadata(url, cookies_file=None):
26
- def run_yt_dlp(with_cookies):
27
  ydl_opts = {
28
- 'quiet': False,
29
- 'skip_download': True,
 
30
  'noplaylist': True,
31
- 'extract_flat': False,
32
- 'force_ipv4': True,
33
  'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
34
- 'referer': 'https://www.youtube.com/'
 
 
 
 
 
 
 
35
  }
36
- if with_cookies and cookies_file and os.path.exists(cookies_file):
37
- with open(cookies_file, "r", encoding="utf-8", errors="ignore") as f:
38
- header = f.readline().strip()
39
- if "# Netscape HTTP Cookie File" in header:
40
- ydl_opts['cookiefile'] = cookies_file
41
- print("βœ… Using valid cookies file")
42
- else:
43
- print("⚠️ Invalid cookies format. Skipping cookies.")
44
- else:
45
- print("πŸ”“ Proceeding without cookies")
46
 
47
  with YoutubeDL(ydl_opts) as ydl:
48
- return ydl.extract_info(url, download=False)
49
 
50
- try:
51
- # Try with cookies first
52
- try:
53
- info = run_yt_dlp(with_cookies=True)
54
- except Exception as e:
55
- print("⚠️ First attempt with cookies failed, retrying without cookies...", e)
56
- info = run_yt_dlp(with_cookies=False)
57
-
58
- print("βœ… Metadata fetched successfully")
59
-
60
- return {
61
- 'title': info.get("title", ""),
62
- 'description': info.get("description", ""),
63
- 'duration': info.get("duration", 0),
64
- 'uploader': info.get("uploader", ""),
65
- 'view_count': info.get("view_count", 0),
66
- 'upload_date': info.get("upload_date", "")
67
- }, "βœ… Video metadata extracted"
68
 
69
  except Exception as e:
70
  traceback.print_exc()
71
- return None, f"❌ Metadata extraction failed: {str(e)}"
72
-
73
- # βœ… Gemini Prompt for Stock Extraction
74
 
75
- def query_gemini_stock_analysis(meta):
76
- if GEMINI_MODEL is None:
77
- return "❌ Gemini model is not initialized."
78
 
79
- prompt = f"""
80
- Analyze the following YouTube video metadata and extract any stock trading recommendations:
81
-
82
- Title: {meta['title']}
83
- Description: {meta['description']}
 
 
 
 
 
84
 
85
- Please extract:
86
- - Mentioned companies or stock symbols
87
- - Any price targets, buy/sell/hold recommendations
88
- - Bullish/bearish sentiments if expressed
89
- - If no stock info is present, clearly say "No financial or trading recommendations found."
90
- - Keep the output short and to the point
91
- """
92
 
 
93
  try:
94
- response = GEMINI_MODEL.generate_content(prompt)
95
- if response and response.text:
96
- return response.text.strip()
97
- else:
98
- return "⚠️ Gemini returned no content."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  except Exception as e:
100
- traceback.print_exc()
101
- return f"❌ Gemini query failed: {str(e)}"
 
 
 
 
 
 
 
 
 
102
 
103
- # βœ… Main Pipeline
104
 
105
- def run_pipeline(api_key, url, cookies):
106
- print("πŸš€ Starting analysis...")
107
- if not url or not api_key:
108
- return "❌ Please provide both API key and YouTube URL", ""
 
109
 
110
- status = configure_gemini(api_key)
111
- if not status.startswith("βœ…"):
 
112
  return status, ""
113
 
114
- # Save cookies if provided
115
- cookie_path = None
116
- if cookies:
117
- try:
118
- cookie_path = tempfile.mktemp(suffix=".txt")
119
- with open(cookie_path, "wb") as f:
120
- f.write(cookies.read())
121
- print(f"βœ… Saved uploaded cookies to: {cookie_path}")
122
- except Exception as e:
123
- print(f"❌ Failed to save cookies: {e}")
124
-
125
- metadata, meta_status = extract_metadata(url, cookie_path)
126
- if not metadata:
127
- return meta_status, ""
128
-
129
- print(f"πŸ“„ Title: {metadata['title']}")
130
- print(f"πŸ“ Description length: {len(metadata['description'])} characters")
131
-
132
- result = query_gemini_stock_analysis(metadata)
133
- return meta_status, result
134
-
135
- # βœ… Gradio UI
136
- with gr.Blocks(title="Gemini Stock Extractor (Debug Mode)") as demo:
137
  gr.Markdown("""
138
- # πŸ“ˆ Gemini-Based Stock Recommendation Extractor
139
- Paste a YouTube link and get stock-related insights using only the title + description.
140
- No audio, no transcription required. Fast and simple.
141
  """)
142
 
143
  with gr.Row():
144
- api_input = gr.Textbox(label="πŸ”‘ Gemini API Key", type="password")
145
- url_input = gr.Textbox(label="YouTube Video URL")
146
- cookies_input = gr.File(label="cookies.txt (optional)", file_types=[".txt"])
147
 
148
- go_btn = gr.Button("πŸš€ Analyze")
149
- status_box = gr.Textbox(label="Status", lines=1)
150
- output_box = gr.Textbox(label="Extracted Stock Insights", lines=12)
151
 
152
- go_btn.click(fn=run_pipeline, inputs=[api_input, url_input, cookies_input], outputs=[status_box, output_box])
153
 
154
  if __name__ == "__main__":
155
  demo.launch(debug=True)
 
1
+ # βœ… Stock Recommendation Extractor from YouTube Audio (Working Pipeline)
2
 
 
3
  import os
4
+ import gradio as gr
5
  import tempfile
6
+ import shutil
7
+ import re
8
  import traceback
 
9
  from yt_dlp import YoutubeDL
10
 
11
+ # Optional: use OpenAI Whisper if available
12
+ try:
13
+ import whisper
14
+ WHISPER_AVAILABLE = True
15
+ except:
16
+ WHISPER_AVAILABLE = False
17
 
18
+ # βœ… Download audio using working logic
 
 
 
 
 
 
 
19
 
20
+ def download_audio(url, cookies_path=None):
21
+ try:
22
+ temp_dir = tempfile.mkdtemp()
23
+ output_path = os.path.join(temp_dir, "audio")
24
 
 
 
25
  ydl_opts = {
26
+ 'format': 'bestaudio[ext=m4a]/bestaudio/best',
27
+ 'outtmpl': output_path + '.%(ext)s',
28
+ 'quiet': True,
29
  'noplaylist': True,
30
+ 'cookiefile': cookies_path if cookies_path else None,
 
31
  'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
32
+ 'referer': 'https://www.youtube.com/',
33
+ 'force_ipv4': True,
34
+ 'http_headers': {
35
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
36
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
37
+ 'Accept-Language': 'en-US,en;q=0.5',
38
+ 'Referer': 'https://www.youtube.com/'
39
+ },
40
  }
 
 
 
 
 
 
 
 
 
 
41
 
42
  with YoutubeDL(ydl_opts) as ydl:
43
+ ydl.download([url])
44
 
45
+ for ext in [".m4a", ".webm", ".mp3"]:
46
+ final_path = output_path + ext
47
+ if os.path.exists(final_path):
48
+ return final_path, "βœ… Audio downloaded successfully"
49
+
50
+ return None, "❌ Audio file not found"
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
  except Exception as e:
53
  traceback.print_exc()
54
+ return None, f"❌ Download error: {str(e)}"
 
 
55
 
56
+ # βœ… Transcribe audio using Whisper
 
 
57
 
58
+ def transcribe_audio(path):
59
+ if not WHISPER_AVAILABLE:
60
+ return "❌ Whisper not available. Please install openai-whisper."
61
+ try:
62
+ model = whisper.load_model("tiny")
63
+ result = model.transcribe(path)
64
+ return result["text"]
65
+ except Exception as e:
66
+ traceback.print_exc()
67
+ return f"❌ Transcription failed: {str(e)}"
68
 
69
+ # βœ… Extract stock-related information from transcript
 
 
 
 
 
 
70
 
71
+ def extract_stock_info(text):
72
  try:
73
+ companies = re.findall(r'\b[A-Z][a-z]+(?: [A-Z][a-z]+)*\b', text)
74
+ symbols = re.findall(r'\b[A-Z]{2,5}\b', text)
75
+ prices = re.findall(r'\$\d+(?:\.\d{1,2})?', text)
76
+ actions = re.findall(r'\b(buy|sell|hold|target|bullish|bearish|stop loss)\b', text, re.IGNORECASE)
77
+
78
+ result = "=== STOCK RECOMMENDATION ANALYSIS ===\n\n"
79
+ if companies:
80
+ result += f"🏒 Companies Mentioned: {', '.join(set(companies[:10]))}\n"
81
+ if symbols:
82
+ result += f"πŸ”  Symbols: {', '.join(set(symbols[:10]))}\n"
83
+ if prices:
84
+ result += f"πŸ’² Prices: {', '.join(set(prices[:10]))}\n"
85
+ if actions:
86
+ result += f"πŸ“Š Actions: {', '.join(set(actions[:10]))}\n"
87
+
88
+ # Highlight potential recommendations
89
+ recommendations = []
90
+ for line in text.split("."):
91
+ if any(word in line.lower() for word in ['buy', 'sell', 'target', 'hold']):
92
+ recommendations.append(line.strip())
93
+
94
+ if recommendations:
95
+ result += "\n🎯 Potential Recommendations:\n"
96
+ for r in recommendations[:5]:
97
+ result += f"β€’ {r}\n"
98
+
99
+ if not any([companies, symbols, prices, actions]):
100
+ result += "\n⚠️ No stock-related insights detected."
101
+
102
+ return result
103
+
104
  except Exception as e:
105
+ return f"❌ Stock info extraction failed: {str(e)}"
106
+
107
+ # βœ… Save uploaded cookies.txt
108
+
109
+ def save_cookies(file):
110
+ if file is None:
111
+ return None
112
+ temp_path = tempfile.mktemp(suffix=".txt")
113
+ with open(temp_path, "wb") as f:
114
+ f.write(file.read())
115
+ return temp_path
116
 
117
+ # βœ… Full pipeline
118
 
119
+ def run_pipeline(url, cookies_file):
120
+ if not WHISPER_AVAILABLE:
121
+ return "❌ Whisper is not installed. Run: pip install openai-whisper", ""
122
+ if not url:
123
+ return "❌ YouTube URL required", ""
124
 
125
+ cookie_path = save_cookies(cookies_file)
126
+ audio_path, status = download_audio(url, cookie_path)
127
+ if not audio_path:
128
  return status, ""
129
 
130
+ transcript = transcribe_audio(audio_path)
131
+ if transcript.startswith("❌"):
132
+ return transcript, ""
133
+
134
+ stock_info = extract_stock_info(transcript)
135
+ return "βœ… Complete", stock_info
136
+
137
+ # βœ… Gradio Interface
138
+ with gr.Blocks(title="Stock Insights from YouTube Audio") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  gr.Markdown("""
140
+ # 🎧 Extract Stock Recommendations from YouTube Audio
141
+ This app downloads the audio from a YouTube video, transcribes it with Whisper,
142
+ and extracts stock trading recommendations, sentiments, and symbols.
143
  """)
144
 
145
  with gr.Row():
146
+ url_input = gr.Textbox(label="πŸŽ₯ YouTube Video URL")
147
+ cookie_input = gr.File(label="cookies.txt (optional)", file_types=[".txt"])
 
148
 
149
+ run_btn = gr.Button("πŸš€ Extract Stock Info")
150
+ status_output = gr.Textbox(label="Status")
151
+ result_output = gr.Textbox(label="Stock Info", lines=12)
152
 
153
+ run_btn.click(fn=run_pipeline, inputs=[url_input, cookie_input], outputs=[status_output, result_output])
154
 
155
  if __name__ == "__main__":
156
  demo.launch(debug=True)