Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import requests | |
| import json | |
| import os | |
| import io | |
| import base64 | |
| # --- Configuration --- | |
| TALKBOT_TTS_URL = "https://talkbot.ir/TTS-tkun" | |
| TALKBOT_CHAT_API_URL = "https://talkbot.ir/api/v1/chat/completions" | |
| DEEPSEEK_API_KEY = "sk-4fb61f56acfccf731e801b904c89f5" # Replace with your actual key if different | |
| DEEPSEEK_MODEL = "deepseek-v3-0324" | |
| # --- Functions --- | |
| def get_tts_audio_url(text: str) -> str: | |
| """Gets a WAV audio URL from Talkbot TTS.""" | |
| params = {"text": text} | |
| response = requests.get(TALKBOT_TTS_URL, params=params) | |
| response.raise_for_status() # Raise an exception for bad status codes | |
| return response.text.strip() # The response directly contains the URL | |
| def generate_podcast_script_deepseek(prompt: str) -> str: | |
| """Generates a podcast script using DeepSeek API.""" | |
| headers = { | |
| "Authorization": f"Bearer {DEEPSEEK_API_KEY}", | |
| "Content-Type": "application/json" | |
| } | |
| data = { | |
| "model": DEEPSEEK_MODEL, | |
| "messages": [ | |
| {"role": "system", "content": "You are a helpful assistant for generating podcast scripts."}, | |
| {"role": "user", "content": f"Generate a short podcast script on the following topic:\n\n{prompt}\n\nPlease include a clear introduction, 2-3 main points, and a conclusion. Divide the script into two distinct voices (Voice 1 and Voice 2). Label each part with 'Voice 1:' or 'Voice 2:'."} | |
| ], | |
| "temperature": 0.7, | |
| "max_tokens": 500, | |
| "n": 1, | |
| "stop": None | |
| } | |
| try: | |
| response = requests.post(TALKBOT_CHAT_API_URL, headers=headers, data=json.dumps(data)) | |
| response.raise_for_status() # Raise an exception for bad status codes | |
| result = response.json() | |
| if result and result.get("choices"): | |
| return result["choices"][0]["message"]["content"] | |
| else: | |
| st.error("DeepSeek API did not return valid choices.") | |
| return "Error: Could not generate script." | |
| except requests.exceptions.HTTPError as e: | |
| st.error(f"HTTP Error: {e.response.status_code} - {e.response.text}") | |
| return f"Error: Could not generate script (HTTP Error)." | |
| except requests.exceptions.RequestException as e: | |
| st.error(f"Request Error: {e}") | |
| return "Error: Could not generate script (Request Error)." | |
| except json.JSONDecodeError as e: | |
| st.error(f"JSON Decode Error: {e} - Response content: {response.text}") | |
| return "Error: Could not generate script (JSON Error)." | |
| def download_audio_from_url(url: str) -> bytes: | |
| """Downloads audio content from a given URL.""" | |
| try: | |
| response = requests.get(url) | |
| response.raise_for_status() | |
| return response.content | |
| except requests.exceptions.RequestException as e: | |
| st.error(f"Error downloading audio from {url}: {e}") | |
| return b"" | |
| def create_audio_player_from_bytes(audio_bytes: bytes, key_suffix: str): | |
| """Creates an audio player for bytes data.""" | |
| if audio_bytes: | |
| # Encode bytes to base64 for embedding in HTML audio tag | |
| b64_audio = base64.b64encode(audio_bytes).decode("utf-8") | |
| st.markdown( | |
| f""" | |
| <audio controls key="{key_suffix}"> | |
| <source src="data:audio/wav;base64,{b64_audio}" type="audio/wav"> | |
| Your browser does not support the audio element. | |
| </audio> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| else: | |
| st.warning("No audio data available to play.") | |
| # --- Streamlit UI --- | |
| st.set_page_config(page_title="Podcast Generator", layout="centered") | |
| st.title("🎙️ AI Podcast Generator") | |
| st.markdown("Generate and listen to your custom podcasts using AI!") | |
| # Input for podcast topic | |
| podcast_topic = st.text_input("Enter your podcast topic:", "The future of AI in daily life") | |
| if st.button("Generate Podcast"): | |
| if not podcast_topic: | |
| st.warning("Please enter a podcast topic.") | |
| else: | |
| st.subheader("Generating Podcast Script...") | |
| with st.spinner("AI is thinking... this might take a moment."): | |
| script = generate_podcast_script_deepseek(podcast_topic) | |
| st.session_state.script = script # Store script in session state | |
| if st.session_state.script and "Error" not in st.session_state.script: | |
| st.success("Script Generated!") | |
| st.subheader("Generated Podcast Script:") | |
| st.text_area("Script", st.session_state.script, height=300) | |
| st.markdown("---") | |
| st.subheader("Generating Audio for Voices...") | |
| # Split script into Voice 1 and Voice 2 parts | |
| voice_1_lines = [] | |
| voice_2_lines = [] | |
| current_voice = None | |
| for line in st.session_state.script.split('\n'): | |
| line_stripped = line.strip() | |
| if line_stripped.lower().startswith("voice 1:"): | |
| current_voice = 1 | |
| voice_1_lines.append(line_stripped[len("voice 1:"):].strip()) | |
| elif line_stripped.lower().startswith("voice 2:"): | |
| current_voice = 2 | |
| voice_2_lines.append(line_stripped[len("voice 2:"):].strip()) | |
| elif current_voice == 1: | |
| voice_1_lines.append(line_stripped) | |
| elif current_voice == 2: | |
| voice_2_lines.append(line_stripped) | |
| voice_1_text = " ".join(filter(None, voice_1_lines)) # Filter out empty strings | |
| voice_2_text = " ".join(filter(None, voice_2_lines)) # Filter out empty strings | |
| st.write(f"Voice 1 Text: {voice_1_text}") | |
| st.write(f"Voice 2 Text: {voice_2_text}") | |
| st.session_state.voice1_audio_url = "" | |
| st.session_state.voice2_audio_url = "" | |
| if voice_1_text: | |
| with st.spinner("Getting Voice 1 audio..."): | |
| try: | |
| st.session_state.voice1_audio_url = get_tts_audio_url(voice_1_text) | |
| except requests.exceptions.RequestException as e: | |
| st.error(f"Error getting Voice 1 audio URL: {e}") | |
| else: | |
| st.warning("No text found for Voice 1.") | |
| if voice_2_text: | |
| with st.spinner("Getting Voice 2 audio..."): | |
| try: | |
| st.session_state.voice2_audio_url = get_tts_audio_url(voice_2_text) | |
| except requests.exceptions.RequestException as e: | |
| st.error(f"Error getting Voice 2 audio URL: {e}") | |
| else: | |
| st.warning("No text found for Voice 2.") | |
| st.success("Audio URLs fetched!") | |
| st.markdown("---") | |
| st.subheader("Listen to Podcast Voices:") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown("#### Voice 1") | |
| if st.session_state.voice1_audio_url: | |
| st.audio(st.session_state.voice1_audio_url, format="audio/wav") | |
| st.download_button( | |
| label="Download Voice 1 Audio", | |
| data=download_audio_from_url(st.session_state.voice1_audio_url), | |
| file_name="voice_1.wav", | |
| mime="audio/wav", | |
| key="dl_voice1" | |
| ) | |
| else: | |
| st.warning("Voice 1 audio not available.") | |
| with col2: | |
| st.markdown("#### Voice 2") | |
| if st.session_state.voice2_audio_url: | |
| st.audio(st.session_state.voice2_audio_url, format="audio/wav") | |
| st.download_button( | |
| label="Download Voice 2 Audio", | |
| data=download_audio_from_url(st.session_state.voice2_audio_url), | |
| file_name="voice_2.wav", | |
| mime="audio/wav", | |
| key="dl_voice2" | |
| ) | |
| else: | |
| st.warning("Voice 2 audio not available.") | |
| else: | |
| st.error("Failed to generate podcast script. Please try again.") | |
| st.markdown("---") | |
| st.markdown("Developed with ❤️ for HUGGINGFACE") | |
| st.markdown("For more information on Talkbot TTS: [talkbot.ir](https://talkbot.ir)") | |