suprimedev commited on
Commit
32b5663
·
verified ·
1 Parent(s): 8864734

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -214
app.py CHANGED
@@ -1,239 +1,132 @@
1
- import streamlit as st
2
  import requests
3
  import json
4
  import os
5
- import io
6
- import base64
7
 
8
- # --- Configuration ---
9
- TALKBOT_TTS_URL = "https://talkbot.ir/TTS-tkun"
10
- TALKBOT_CHAT_API_URL = "https://talkbot.ir/api/v1/chat/completions"
11
- DEEPSEEK_API_KEY = "sk-4fb61f56acfccf731e801b904cd89f5" # This key is publicly visible, consider environment variables for production!
12
 
13
- # --- Helper Functions ---
14
-
15
- @st.cache_data
16
- def get_tts_audio_url(text: str) -> str:
17
- """Fetches a WAV audio URL from Talkbot TTS."""
18
- try:
19
- params = {"text": text}
20
- response = requests.get(TALKBOT_TTS_URL, params=params)
21
- response.raise_for_status() # Raise an exception for bad status codes
22
- return response.text.strip()
23
- except requests.exceptions.RequestException as e:
24
- st.error(f"Error fetching TTS audio URL for '{text}': {e}")
25
- return ""
26
-
27
- @st.cache_data
28
- def generate_podcast_script_ai(topic: str, num_sections: int = 3) -> str:
29
- """Generates a podcast script using the Talkbot Deepseek API."""
30
- prompt = (
31
- f"Generate a concise podcast script about '{topic}'. "
32
- f"The script should have {num_sections} main sections, each starting with a clear heading. "
33
- "Each section should contain interesting facts or engaging discussions. "
34
- "Conclude with a short outro. The script should be conversational and engaging. "
35
- "Keep the total length reasonable for a short podcast (e.g., 300-500 words)."
36
- "\n\nFormat your response as follows:\n\n"
37
- "Section 1: [Title of Section 1]\n[Content of Section 1]\n\n"
38
- "Section 2: [Title of Section 2]\n[Content of Section 2]\n\n"
39
- # Add more sections as needed based on num_sections if hardcoding
40
- # For simplicity, we'll let the AI decide the exact number based on prompt
41
- "..."
42
- "Outro:\n[Outro content]"
43
- )
44
 
 
 
 
 
45
  headers = {
46
- "Content-Type": "application/json",
47
- "Authorization": f"Bearer {DEEPSEEK_API_KEY}"
48
  }
49
 
50
  payload = {
51
- "model": "deepseek-v3-0324",
52
  "messages": [
53
- {"role": "system", "content": "You are a helpful podcast script writer."},
54
- {"role": "user", "content": prompt}
55
  ],
56
- "max_tokens": 700,
57
- "temperature": 0.7,
58
- "top_p": 1,
59
- "frequency_penalty": 0,
60
- "presence_penalty": 0
61
  }
62
 
63
  try:
64
- response = requests.post(TALKBOT_CHAT_API_URL, headers=headers, json=payload)
65
- response.raise_for_status()
66
- result = response.json()
67
- if result and 'choices' in result and result['choices']:
68
- return result['choices'][0]['message']['content'].strip()
69
  else:
70
- st.error("AI response did not contain content.")
71
- return "Could not generate podcast script. Please try again."
72
  except requests.exceptions.RequestException as e:
73
- st.error(f"Error generating podcast script with AI: {e}")
74
- return "Could not generate podcast script. API error."
75
  except json.JSONDecodeError:
76
- st.error("Could not parse AI response JSON.")
77
- return "Could not generate podcast script. Invalid AI response."
78
-
79
- def create_audio_player_from_url(audio_url: str, caption: str = ""):
80
- """Creates an HTML audio player for a given URL."""
81
- if audio_url:
82
- st.audio(audio_url, format="audio/wav", caption=caption)
83
- else:
84
- st.write(f"No audio available for: {caption}")
85
-
86
- def get_audio_from_url_as_download(audio_url: str, filename: str):
87
- """Fetches audio from a URL and returns it as a bytes object for download."""
88
  try:
89
- response = requests.get(audio_url, stream=True)
90
- response.raise_for_status()
91
- audio_bytes = io.BytesIO(response.content).read()
92
- return audio_bytes
 
 
 
 
 
 
93
  except requests.exceptions.RequestException as e:
94
- st.error(f"Error downloading audio from {audio_url}: {e}")
95
  return None
96
 
97
- # --- Streamlit UI ---
98
-
99
- st.set_page_config(
100
- page_title="پادکست ساز هوشمند",
101
- page_icon="🎙️",
102
- layout="centered"
103
- )
104
-
105
- st.title("🎙️ پادکست ساز هوشمند")
106
- st.markdown("پادکست خود را با هوش مصنوعی و صدای طبیعی بسازید!")
107
-
108
- with st.expander("درباره این ابزار"):
109
- st.write(
110
- """
111
- این ابزار به شما کمک می‌کند تا به راحتی پادکست تولید کنید:
112
- 1. **ایده پادکست**: موضوع پادکست خود را وارد کنید.
113
- 2. **تولید متن**: هوش مصنوعی (Deepseek) متنی جذاب برای پادکست شما تولید می‌کند.
114
- 3. **تولید صدا**: متن تولید شده به دو صدای مجزا (صدای اول و صدای دوم) تبدیل می‌شود.
115
- 4. **پخش و دانلود**: می‌توانید پادکست را گوش دهید یا فایل‌های صوتی آن را دانلود کنید.
116
-
117
- **توجه**: کلید API شما برای Talkbot Deepseek باید معتبر باشد.
118
- """
119
- )
120
- st.markdown("[سورس کد در گیتهاب](لینک-گیتهاب-خود-را-اینجا-قرار-دهید)") # Add your GitHub link here
121
-
122
- # --- Input Section ---
123
- st.header("۱. موضوع پادکست را وارد کنید")
124
- podcast_topic = st.text_input(
125
- "موضوع پادکست چیست؟",
126
- placeholder="مثال: تاریخچه قهوه، فیزیک کوانتوم به زبان ساده، مزایای مدیتیشن"
127
- )
128
-
129
- if st.button("تولید پادکست", type="primary") and podcast_topic:
130
- st.session_state['podcast_generated'] = False
131
- st.session_state['script'] = None
132
- st.session_state['audio1_url'] = None
133
- st.session_state['audio2_url'] = None
134
-
135
- with st.spinner(" در حال تولید متن پادکست با هوش مصنوعی..."):
136
- script_content = generate_podcast_script_ai(podcast_topic)
137
- st.session_state['script'] = script_content
138
-
139
- if script_content and script_content != "Could not generate podcast script. Please try again.":
140
- st.success("متن پادکست با موفقیت تولید شد!")
141
- st.subheader("۲. متن پادکست تولید شده:")
142
- st.code(script_content, language="text")
143
-
144
- st.info("💡 می‌توانید متن را ویرایش کنید تا برای تولید صدا بهتر باشد.")
145
- # Allow editing the script
146
- edited_script = st.text_area("ویرایش متن پادکست (اختیاری):", value=script_content, height=300)
147
- st.session_state['edited_script'] = edited_script
148
-
149
- # Split script for two voices
150
- # A simple split strategy:
151
- # Voice 1 takes the first half, Voice 2 takes the second half.
152
- # This can be made more sophisticated (e.g., based on paragraphs, specific markers).
153
- lines = edited_script.split('\n')
154
- mid_point = len(lines) // 2
155
- voice1_text = "\n".join(lines[:mid_point])
156
- voice2_text = "\n".join(lines[mid_point:])
157
-
158
- st.subheader("۳. تولید صدا")
159
-
160
- col1, col2 = st.columns(2)
161
-
162
- with col1:
163
- st.write("**صدای اول:**")
164
- st.write(voice1_text)
165
- if st.button("تولید صدای اول"):
166
- with st.spinner("در حال تولید صدای اول..."):
167
- audio1_url = get_tts_audio_url(voice1_text)
168
- st.session_state['audio1_url'] = audio1_url
169
- if audio1_url:
170
- st.session_state['podcast_generated'] = True
171
- st.success("صدای اول با موفقیت تولید شد!")
172
- else:
173
- st.error("خطا در تولید صدای اول. لطفاً دوباره تلاش کنید.")
174
-
175
- with col2:
176
- st.write("**صدای دوم:**")
177
- st.write(voice2_text)
178
- if st.button("تولید صدای دوم"):
179
- with st.spinner("در حال تولید صدای دوم..."):
180
- audio2_url = get_tts_audio_url(voice2_text)
181
- st.session_state['audio2_url'] = audio2_url
182
- if audio2_url:
183
- st.session_state['podcast_generated'] = True
184
- st.success("صدای دوم با موفقیت تولید شد!")
185
- else:
186
- st.error("خطا در تولید صدای دوم. لطفاً دوباره تلاش کنید.")
187
-
188
- elif script_content: # This means an error message was returned
189
- st.error("خطا در تولید متن پادکست.")
190
-
191
- # --- Display Section (rendered after the script is generated) ---
192
- if 'podcast_generated' in st.session_state and st.session_state['podcast_generated']:
193
- st.subheader("۴. پادکست شما آماده است!")
194
-
195
- col1_player, col2_player = st.columns(2)
196
-
197
- with col1_player:
198
- if st.session_state['audio1_url']:
199
- st.markdown("### صدای اول")
200
- create_audio_player_from_url(st.session_state['audio1_url'], "صدای اول")
201
- audio1_bytes = get_audio_from_url_as_download(st.session_state['audio1_url'], "podcast_voice1.wav")
202
- if audio1_bytes:
203
- st.download_button(
204
- label="دانلود صدای اول",
205
- data=audio1_bytes,
206
- file_name="podcast_voice1.wav",
207
- mime="audio/wav"
208
- )
209
  else:
210
- st.warning("صدای اول هنوز تولید نشده یا با خطا مواجه شده است.")
211
-
212
- with col2_player:
213
- if st.session_state['audio2_url']:
214
- st.markdown("### صدای دوم")
215
- create_audio_player_from_url(st.session_state['audio2_url'], "صدای دوم")
216
- audio2_bytes = get_audio_from_url_as_download(st.session_state['audio2_url'], "podcast_voice2.wav")
217
- if audio2_bytes:
218
- st.download_button(
219
- label="دانلود صدای دوم",
220
- data=audio2_bytes,
221
- file_name="podcast_voice2.wav",
222
- mime="audio/wav"
223
- )
224
- else:
225
- st.warning("صدای دوم هنوز تولید نشده یا با خطا مواجه شده است.")
226
-
227
- st.markdown("---")
228
- st.info("برای تولید پادکست جدید، موضوع جدیدی وارد کنید و دکمه 'تولید پادکست' را بزنید.")
229
 
230
- # --- How to run this app ---
231
- # 1. Save the code as `app.py`.
232
- # 2. Make sure you have Streamlit installed: `pip install streamlit requests`
233
- # 3. Run from your terminal: `streamlit run app.py`
234
 
235
- # IMPORTANT SECURITY NOTE:
236
- # The Deepseek API key is hardcoded directly in the Python script.
237
- # For production applications, it's highly recommended to use environment variables
238
- # (e.g., `os.getenv("DEEPSEEK_API_KEY")`) and set them outside of your code
239
- # for security and flexibility. For this simple example as requested, it's left as is.
 
 
1
  import requests
2
  import json
3
  import os
 
 
4
 
5
+ # اطلاعات API TTS
6
+ TTS_API_BASE_URL = "https://talkbot.ir/TTS-tkun"
7
+ TTS_API_FORMAT = "?text="
 
8
 
9
+ # اطلاعات API OpenAI (برای Talkbot.ir)
10
+ OPENAI_API_BASE_URL = "https://talkbot.ir/api/v1/chat/completions"
11
+ OPENAI_API_KEY = "sk-4fb61f56acfcc731e801b904cd89f5" # دقت کنید که این کلید API از Talkbot.ir است و ممکن است با OpenAI اصلی متفاوت باشد.
12
+ OPENAI_MODEL = "deepseek-v3-0324"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ def get_text_from_ai(prompt_text):
15
+ """
16
+ تولید متن پادکست با استفاده از API هوش مصنوعی.
17
+ """
18
  headers = {
19
+ "Authorization": f"Bearer {OPENAI_API_KEY}",
20
+ "Content-Type": "application/json"
21
  }
22
 
23
  payload = {
24
+ "model": OPENAI_MODEL,
25
  "messages": [
26
+ {"role": "system", "content": "You are a helpful assistant that generates podcast scripts."},
27
+ {"role": "user", "content": f"Generate a short podcast script about: {prompt_text}"}
28
  ],
29
+ "max_tokens": 500,
30
+ "temperature": 0.7
 
 
 
31
  }
32
 
33
  try:
34
+ response = requests.post(OPENAI_API_BASE_URL, headers=headers, json=payload)
35
+ response.raise_for_status() # Raises an HTTPError for bad responses (4xx or 5xx)
36
+ data = response.json()
37
+ if data and data.get("choices"):
38
+ return data["choices"][0]["message"]["content"].strip()
39
  else:
40
+ print("AI response did not contain expected data.")
41
+ return None
42
  except requests.exceptions.RequestException as e:
43
+ print(f"Error connecting to AI API: {e}")
44
+ return None
45
  except json.JSONDecodeError:
46
+ print("Error decoding JSON response from AI API.")
47
+ return None
48
+
49
+ def get_audio_wav_link(text):
50
+ """
51
+ دریافت لینک فایل WAV از API تبدیل متن به گفتار.
52
+ """
53
+ encoded_text = requests.utils.quote(text) # Encode URL-unsafe characters
54
+ tts_url = f"{TTS_API_BASE_URL}{TTS_API_FORMAT}{encoded_text}"
55
+
 
 
56
  try:
57
+ # برای این API، فقط ساختار URL مهم است، نیازی به درخواست مستقیم برای دریافت لینک نیست.
58
+ # فرض می‌شود که API بلافاصله لینک wav را به عنوان پاسخ GET برمی‌گرداند.
59
+ # اما طبق توضیحات شما، خروجی به صورت لینک wav است.
60
+ # این یعنی درخواست GET به آن URL، مستقیماً لینک را برمی‌گرداند.
61
+ # اگر API مستقیماً لینک WAV را در بدنه پاسخ برمی‌گرداند، می‌توان از request.text استفاده کرد.
62
+ # در غیر این صورت، شاید باید یک درخواست واقعی انجام داد.
63
+ # با توجه به "خروجی صوت به صورت لینک wav است"، فرض می‌شود که خود URL ورودی، لینک WAV خروجی است.
64
+ # اگر API یک JSON با لینک wav برمی‌گرداند، باید کد را تغییر داد.
65
+ return tts_url
66
+
67
  except requests.exceptions.RequestException as e:
68
+ print(f"Error generating TTS link: {e}")
69
  return None
70
 
71
+ def main():
72
+ print("--------------------------------------------------")
73
+ print(" Talkbot Podcast Generator ")
74
+ print("--------------------------------------------------")
75
+ print("این اسکریپت یک متن پادکست تولید و لینک‌های صوتی را فراهم می‌کند.")
76
+ print(" برای خروج، 'exit' را تایپ کنید.")
77
+ print("--------------------------------------------------")
78
+
79
+ while True:
80
+ topic = input("\nموضوع پادکست را وارد کنید (یا 'exit' برای خروج): ")
81
+ if topic.lower() == 'exit':
82
+ break
83
+
84
+ print(f"\nدر حال تولید اسکریپت پادکست برای '{topic}' با هوش مصنوعی...")
85
+ podcast_script = get_text_from_ai(topic)
86
+
87
+ if podcast_script:
88
+ print("\n------------------- اسکریپت پادکست -------------------")
89
+ print(podcast_script)
90
+ print("------------------------------------------------------")
91
+
92
+ # تقسیم متن به دو بخش برای صدای اول و صدای دوم
93
+ # این یک تقسیم‌بندی ساده است. ممکن است نیاز به منطق دقیق‌تری داشته باشید.
94
+ sentences = [s.strip() for s in podcast_script.split('.') if s.strip()]
95
+
96
+ if len(sentences) >= 2:
97
+ speaker1_text = sentences[0]
98
+ speaker2_text = sentences[1]
99
+ elif len(sentences) == 1:
100
+ speaker1_text = sentences[0]
101
+ speaker2_text = "" # یا بخشی از جمله اول
102
+ else:
103
+ print("متن کافی برای تقسیم بین دو گوینده وجود ندارد.")
104
+ speaker1_text = podcast_script
105
+ speaker2_text = ""
106
+
107
+ print("\nدر حال ساخت لینک‌های صوتی...")
108
+
109
+ audio_link_speaker1 = get_audio_wav_link(speaker1_text)
110
+ audio_link_speaker2 = get_audio_wav_link(speaker2_text) # اگر speaker2_text خالی باشد، لینک معناداری تولید نمی‌شود.
111
+
112
+ if audio_link_speaker1:
113
+ print(f"لینک صدای اول (Speaker 1): {audio_link_speaker1}")
114
+ else:
115
+ print("خطا در تولید لینک صدای اول.")
116
+
117
+ if audio_link_speaker2 and speaker2_text: # فقط اگر متن برای گوینده دوم وجود داشته باشد
118
+ print(f"لینک صدای دوم (Speaker 2): {audio_link_speaker2}")
119
+ elif speaker2_text: # اگر speaker2_text داشتیم و لینکی تولید نشد
120
+ print("خطا در تولید لینک صدای دوم.")
121
+ else:
122
+ print("متن کافی برای تولید صدای دوم وجود نداشت.")
123
+
124
+ print("\n------------------------------------------------------")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  else:
126
+ print("متن پادکست از هوش مصنوعی دریافت نشد.")
127
+ print("لطفاً اتصال به اینترنت و کلید API را بررسی کنید.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
+ print("\nخروج از برنامه. موفق باشید!")
 
 
 
130
 
131
+ if __name__ == "__main__":
132
+ main()