bluenevus's picture
Update app.py
84fed9b verified
raw
history blame
6.78 kB
import dash
from dash import dcc, html, Input, Output, State, callback
import dash_bootstrap_components as dbc
import base64
import io
import google.generativeai as genai
import numpy as np
import edge_tts
import asyncio
import re
import logging
import json
from dash.exceptions import PreventUpdate
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Initialize Dash app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
# Initialize Gemini AI
genai.configure(api_key='YOUR_GEMINI_API_KEY')
# Helper functions (keep the existing functions)
def generate_podcast_script(api_key, content, duration, num_hosts):
# ... (keep the existing implementation)
async def text_to_speech(text, voice):
# ... (keep the existing implementation)
async def render_podcast(api_key, script, voice1, voice2, num_hosts):
# ... (keep the existing implementation)
async def get_voice_list():
# ... (keep the existing implementation)
# Language names dictionary (keep the existing dictionary)
language_names = {
# ... (keep the existing dictionary)
}
# Layout
app.layout = dbc.Container([
html.H1("AI Podcast Generator", className="my-4"),
dbc.Card([
dbc.CardBody([
dbc.Input(id="api-key-input", type="password", placeholder="Enter your Gemini API Key"),
dbc.Textarea(id="content-input", placeholder="Paste your content or upload a document", rows=5),
dcc.Upload(
id='document-upload',
children=html.Div(['Drag and Drop or ', html.A('Select a File')]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px 0'
}
),
dcc.RadioItems(
id="duration",
options=[
{'label': '1-5 min', 'value': '1-5 min'},
{'label': '5-10 min', 'value': '5-10 min'},
{'label': '10-15 min', 'value': '10-15 min'}
],
value='1-5 min',
inline=True
),
dcc.RadioItems(
id="num-hosts",
options=[
{'label': '1 host', 'value': 1},
{'label': '2 hosts', 'value': 2}
],
value=2,
inline=True
),
dcc.Dropdown(id="lang1-select", options=[{'label': lang, 'value': lang} for lang in language_names.values()], value="English (United States)"),
dcc.Dropdown(id="voice1-select"),
html.Div([
dcc.Dropdown(id="lang2-select", options=[{'label': lang, 'value': lang} for lang in language_names.values()], value="English (United States)"),
dcc.Dropdown(id="voice2-select")
], id="second-voice-container"),
dbc.Button("Generate Script", id="generate-btn", color="primary", className="mt-3"),
dbc.Textarea(id="script-output", rows=10, className="mt-3"),
dbc.Button("Render Podcast", id="render-btn", color="success", className="mt-3"),
html.Div(id="audio-output")
])
], className="mt-4")
], fluid=True)
# Callbacks
@app.callback(
Output("voice1-select", "options"),
Input("lang1-select", "value")
)
def update_voice1_options(lang):
selected_lang = next((key for key, value in language_names.items() if value == lang), None)
voices = asyncio.run(get_voice_list()).get(selected_lang, [])
return [{'label': voice, 'value': voice} for voice in voices]
@app.callback(
Output("voice2-select", "options"),
Input("lang2-select", "value")
)
def update_voice2_options(lang):
selected_lang = next((key for key, value in language_names.items() if value == lang), None)
voices = asyncio.run(get_voice_list()).get(selected_lang, [])
return [{'label': voice, 'value': voice} for voice in voices]
@app.callback(
Output("second-voice-container", "style"),
Input("num-hosts", "value")
)
def update_second_voice_visibility(num_hosts):
return {'display': 'block' if num_hosts == 2 else 'none'}
@app.callback(
Output("content-input", "value"),
Input("document-upload", "contents"),
State("document-upload", "filename")
)
def update_content(contents, filename):
if contents is not None:
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
try:
if 'csv' in filename:
df = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
return df.to_string()
elif 'xls' in filename:
df = pd.read_excel(io.BytesIO(decoded))
return df.to_string()
elif 'txt' in filename:
return decoded.decode('utf-8')
else:
return 'Unsupported file type'
except Exception as e:
return f'Error processing file: {str(e)}'
return ''
@app.callback(
Output("script-output", "value"),
Input("generate-btn", "n_clicks"),
State("api-key-input", "value"),
State("content-input", "value"),
State("duration", "value"),
State("num-hosts", "value")
)
def generate_script(n_clicks, api_key, content, duration, num_hosts):
if n_clicks is None:
raise PreventUpdate
try:
script = generate_podcast_script(api_key, content, duration, num_hosts)
return script
except Exception as e:
return f"Error generating script: {str(e)}"
@app.callback(
Output("audio-output", "children"),
Input("render-btn", "n_clicks"),
State("api-key-input", "value"),
State("script-output", "value"),
State("voice1-select", "value"),
State("voice2-select", "value"),
State("num-hosts", "value")
)
def render_podcast_audio(n_clicks, api_key, script, voice1, voice2, num_hosts):
if n_clicks is None:
raise PreventUpdate
try:
sample_rate, audio_data = asyncio.run(render_podcast(api_key, script, voice1, voice2, num_hosts))
audio_base64 = base64.b64encode(audio_data.tobytes()).decode('utf-8')
return html.Audio(src=f"data:audio/wav;base64,{audio_base64}", controls=True)
except Exception as e:
return html.Div(f"Error rendering podcast: {str(e)}", style={'color': 'red'})
if __name__ == '__main__':
print("Starting the Dash application...")
app.run(debug=True, host='0.0.0.0', port=7860)
print("Dash application has finished running.")