Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -27,16 +27,6 @@ from qa import transcribe_audio_deepgram, handle_qa_exchange
|
|
27 |
MAX_QA_QUESTIONS = 5 # up to 5 voice/text questions
|
28 |
|
29 |
def parse_user_edited_transcript(edited_text: str, host_name: str, guest_name: str):
|
30 |
-
"""
|
31 |
-
Looks for lines like:
|
32 |
-
**Angela**: Hello
|
33 |
-
**Dimitris**: Great topic...
|
34 |
-
We treat 'Angela' as the raw display_speaker, 'Hello' as text.
|
35 |
-
Then we map 'Angela' -> speaker='Jane' (if it matches host_name),
|
36 |
-
'Dimitris' -> speaker='John' (if it matches guest_name), etc.
|
37 |
-
|
38 |
-
Returns a list of DialogueItem.
|
39 |
-
"""
|
40 |
pattern = r"\*\*(.+?)\*\*:\s*(.+)"
|
41 |
matches = re.findall(pattern, edited_text)
|
42 |
|
@@ -71,11 +61,6 @@ def parse_user_edited_transcript(edited_text: str, host_name: str, guest_name: s
|
|
71 |
return items
|
72 |
|
73 |
def regenerate_audio_from_dialogue(dialogue_items, custom_bg_music_path=None):
|
74 |
-
"""
|
75 |
-
Re-generates multi-speaker audio from user-edited DialogueItems,
|
76 |
-
then mixes with background music or custom music.
|
77 |
-
Returns (audio_bytes, transcript_str).
|
78 |
-
"""
|
79 |
audio_segments = []
|
80 |
transcript = ""
|
81 |
crossfade_duration = 50 # ms
|
@@ -122,12 +107,6 @@ def generate_podcast(
|
|
122 |
sponsor_style,
|
123 |
custom_bg_music_path
|
124 |
):
|
125 |
-
"""
|
126 |
-
Creates a multi-speaker podcast from PDF, URL, YouTube, or a research topic.
|
127 |
-
Ensures female voice for host (Jane), male voice for guest (John).
|
128 |
-
Sponsor content is either separate or blended based on sponsor_style.
|
129 |
-
Returns (audio_bytes, transcript_str).
|
130 |
-
"""
|
131 |
sources = [bool(file), bool(url), bool(video_url), bool(research_topic_input)]
|
132 |
if sum(sources) > 1:
|
133 |
return None, "Provide only one input (PDF, URL, YouTube, or Topic)."
|
@@ -255,32 +234,65 @@ def main():
|
|
255 |
layout="centered"
|
256 |
)
|
257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
logo_col, title_col = st.columns([1, 10])
|
259 |
with logo_col:
|
260 |
st.image("logomypod.jpg", width=60)
|
261 |
with title_col:
|
262 |
st.markdown("## MyPod v2: AI powered Podcast Generator")
|
263 |
|
264 |
-
|
265 |
-
|
266 |
-
"
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
"
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
|
|
|
|
|
|
284 |
|
285 |
col1, col2 = st.columns(2)
|
286 |
with col1:
|
@@ -302,8 +314,9 @@ def main():
|
|
302 |
|
303 |
user_specs = st.text_area("Any special instructions or prompts for the script? (Optional)", "")
|
304 |
sponsor_content = st.text_area("Sponsored Content / Ad (Optional)", "")
|
305 |
-
|
306 |
-
|
|
|
307 |
["Separate Break", "Blended"]
|
308 |
)
|
309 |
|
@@ -326,7 +339,7 @@ def main():
|
|
326 |
if "conversation_history" not in st.session_state:
|
327 |
st.session_state["conversation_history"] = ""
|
328 |
|
329 |
-
generate_button = st.button("Generate Podcast")
|
330 |
|
331 |
if generate_button:
|
332 |
progress_bar = st.progress(0)
|
@@ -500,6 +513,8 @@ def main():
|
|
500 |
else:
|
501 |
st.write("You have used all 5 Q&A opportunities.")
|
502 |
|
|
|
|
|
503 |
|
504 |
if __name__ == "__main__":
|
505 |
main()
|
|
|
27 |
MAX_QA_QUESTIONS = 5 # up to 5 voice/text questions
|
28 |
|
29 |
def parse_user_edited_transcript(edited_text: str, host_name: str, guest_name: str):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
pattern = r"\*\*(.+?)\*\*:\s*(.+)"
|
31 |
matches = re.findall(pattern, edited_text)
|
32 |
|
|
|
61 |
return items
|
62 |
|
63 |
def regenerate_audio_from_dialogue(dialogue_items, custom_bg_music_path=None):
|
|
|
|
|
|
|
|
|
|
|
64 |
audio_segments = []
|
65 |
transcript = ""
|
66 |
crossfade_duration = 50 # ms
|
|
|
107 |
sponsor_style,
|
108 |
custom_bg_music_path
|
109 |
):
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
sources = [bool(file), bool(url), bool(video_url), bool(research_topic_input)]
|
111 |
if sum(sources) > 1:
|
112 |
return None, "Provide only one input (PDF, URL, YouTube, or Topic)."
|
|
|
234 |
layout="centered"
|
235 |
)
|
236 |
|
237 |
+
# Inject custom CSS for styling adjustments
|
238 |
+
st.markdown("""
|
239 |
+
<style>
|
240 |
+
/* Shrink file uploader button */
|
241 |
+
.stFileUploader>div>div>div {
|
242 |
+
transform: scale(0.9);
|
243 |
+
}
|
244 |
+
/* Style for "Generate Podcast" button */
|
245 |
+
.generate-button > button {
|
246 |
+
background-color: grey;
|
247 |
+
color: white;
|
248 |
+
width: 100%;
|
249 |
+
padding: 0.5em;
|
250 |
+
font-size: 1.2em;
|
251 |
+
}
|
252 |
+
/* Make radio buttons horizontal */
|
253 |
+
div[role="radiogroup"] > label {
|
254 |
+
display: inline-block;
|
255 |
+
margin-right: 1em;
|
256 |
+
}
|
257 |
+
/* Footer styling */
|
258 |
+
footer {
|
259 |
+
text-align: center;
|
260 |
+
padding: 1em 0;
|
261 |
+
font-size: 0.8em;
|
262 |
+
color: #888;
|
263 |
+
}
|
264 |
+
</style>
|
265 |
+
""", unsafe_allow_html=True)
|
266 |
+
|
267 |
logo_col, title_col = st.columns([1, 10])
|
268 |
with logo_col:
|
269 |
st.image("logomypod.jpg", width=60)
|
270 |
with title_col:
|
271 |
st.markdown("## MyPod v2: AI powered Podcast Generator")
|
272 |
|
273 |
+
# "How to use" as an expander
|
274 |
+
with st.expander("How to use"):
|
275 |
+
st.markdown("""
|
276 |
+
Provide one source: PDF Files, Website URL, YouTube videos, or a Topic to Research.
|
277 |
+
Choose the tone and the target duration.
|
278 |
+
Add custom names and descriptions for the speakers if you wish.
|
279 |
+
Add sponsored content as a separate break or blended into the script.
|
280 |
+
Click 'Generate Podcast' to produce your podcast. Post generation you can edit the transcript and re-generate the audio with your edits if needed.
|
281 |
+
Ask Follow-up Questions via text or voice and get immediate answers.
|
282 |
+
""")
|
283 |
+
|
284 |
+
# Retained text below "How to use"
|
285 |
+
st.markdown("""
|
286 |
+
**Research a Topic:** If it's too niche or specific, you might not get the desired outcome.
|
287 |
+
|
288 |
+
**Token Limit:** Up to ~2,048 tokens are supported. Long inputs may be truncated.
|
289 |
+
|
290 |
+
**Note:** YouTube videos will only work if they have captions built in.
|
291 |
+
|
292 |
+
⏳**Please be patient while your podcast is being generated.** This process involves content analysis, script creation, and high-quality audio synthesis, which may take a few minutes.
|
293 |
+
|
294 |
+
🔥 **Ready to create your personalized podcast?** Give it a try now and let the magic happen! 🔥
|
295 |
+
""")
|
296 |
|
297 |
col1, col2 = st.columns(2)
|
298 |
with col1:
|
|
|
314 |
|
315 |
user_specs = st.text_area("Any special instructions or prompts for the script? (Optional)", "")
|
316 |
sponsor_content = st.text_area("Sponsored Content / Ad (Optional)", "")
|
317 |
+
st.markdown("#### Sponsor Integration Style")
|
318 |
+
sponsor_style = st.radio(
|
319 |
+
"",
|
320 |
["Separate Break", "Blended"]
|
321 |
)
|
322 |
|
|
|
339 |
if "conversation_history" not in st.session_state:
|
340 |
st.session_state["conversation_history"] = ""
|
341 |
|
342 |
+
generate_button = st.button("Generate Podcast", key="generate", help="Click to generate your podcast", css_class="generate-button")
|
343 |
|
344 |
if generate_button:
|
345 |
progress_bar = st.progress(0)
|
|
|
513 |
else:
|
514 |
st.write("You have used all 5 Q&A opportunities.")
|
515 |
|
516 |
+
# Footer
|
517 |
+
st.markdown("<footer>©2025 MyPod</footer>", unsafe_allow_html=True)
|
518 |
|
519 |
if __name__ == "__main__":
|
520 |
main()
|