Update app.py
Browse files
app.py
CHANGED
@@ -1,15 +1,14 @@
|
|
1 |
import dash
|
2 |
from dash import dcc, html, Input, Output, State, callback
|
3 |
import dash_bootstrap_components as dbc
|
4 |
-
import base64
|
5 |
-
import io
|
6 |
import google.generativeai as genai
|
7 |
import numpy as np
|
8 |
import edge_tts
|
9 |
import asyncio
|
|
|
10 |
import re
|
|
|
11 |
import logging
|
12 |
-
import json
|
13 |
from dash.exceptions import PreventUpdate
|
14 |
|
15 |
# Set up logging
|
@@ -62,37 +61,36 @@ app.layout = dbc.Container([
|
|
62 |
'margin': '10px 0'
|
63 |
}
|
64 |
),
|
65 |
-
|
66 |
id="duration",
|
67 |
options=[
|
68 |
-
{
|
69 |
-
{
|
70 |
-
{
|
71 |
],
|
72 |
-
value=
|
73 |
inline=True
|
74 |
),
|
75 |
-
|
76 |
id="num-hosts",
|
77 |
options=[
|
78 |
-
{
|
79 |
-
{
|
80 |
],
|
81 |
value=2,
|
82 |
inline=True
|
83 |
),
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
dcc.Dropdown(id="voice2-select")
|
89 |
-
], id="second-voice-container"),
|
90 |
dbc.Button("Generate Script", id="generate-btn", color="primary", className="mt-3"),
|
91 |
dbc.Textarea(id="script-output", rows=10, className="mt-3"),
|
92 |
dbc.Button("Render Podcast", id="render-btn", color="success", className="mt-3"),
|
93 |
-
html.Div(id="audio-output")
|
|
|
94 |
])
|
95 |
-
]
|
96 |
], fluid=True)
|
97 |
|
98 |
# Callbacks
|
@@ -101,49 +99,22 @@ app.layout = dbc.Container([
|
|
101 |
Input("lang1-select", "value")
|
102 |
)
|
103 |
def update_voice1_options(lang):
|
|
|
|
|
104 |
selected_lang = next((key for key, value in language_names.items() if value == lang), None)
|
105 |
-
voices =
|
106 |
-
return [{
|
107 |
|
108 |
@app.callback(
|
109 |
Output("voice2-select", "options"),
|
110 |
Input("lang2-select", "value")
|
111 |
)
|
112 |
def update_voice2_options(lang):
|
|
|
|
|
113 |
selected_lang = next((key for key, value in language_names.items() if value == lang), None)
|
114 |
-
voices =
|
115 |
-
return [{
|
116 |
-
|
117 |
-
@app.callback(
|
118 |
-
Output("second-voice-container", "style"),
|
119 |
-
Input("num-hosts", "value")
|
120 |
-
)
|
121 |
-
def update_second_voice_visibility(num_hosts):
|
122 |
-
return {'display': 'block' if num_hosts == 2 else 'none'}
|
123 |
-
|
124 |
-
@app.callback(
|
125 |
-
Output("content-input", "value"),
|
126 |
-
Input("document-upload", "contents"),
|
127 |
-
State("document-upload", "filename")
|
128 |
-
)
|
129 |
-
def update_content(contents, filename):
|
130 |
-
if contents is not None:
|
131 |
-
content_type, content_string = contents.split(',')
|
132 |
-
decoded = base64.b64decode(content_string)
|
133 |
-
try:
|
134 |
-
if 'csv' in filename:
|
135 |
-
df = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
|
136 |
-
return df.to_string()
|
137 |
-
elif 'xls' in filename:
|
138 |
-
df = pd.read_excel(io.BytesIO(decoded))
|
139 |
-
return df.to_string()
|
140 |
-
elif 'txt' in filename:
|
141 |
-
return decoded.decode('utf-8')
|
142 |
-
else:
|
143 |
-
return 'Unsupported file type'
|
144 |
-
except Exception as e:
|
145 |
-
return f'Error processing file: {str(e)}'
|
146 |
-
return ''
|
147 |
|
148 |
@app.callback(
|
149 |
Output("script-output", "value"),
|
@@ -151,36 +122,54 @@ def update_content(contents, filename):
|
|
151 |
State("api-key-input", "value"),
|
152 |
State("content-input", "value"),
|
153 |
State("duration", "value"),
|
154 |
-
State("num-hosts", "value")
|
|
|
155 |
)
|
156 |
def generate_script(n_clicks, api_key, content, duration, num_hosts):
|
157 |
if n_clicks is None:
|
158 |
raise PreventUpdate
|
159 |
try:
|
160 |
-
|
161 |
-
return script
|
162 |
except Exception as e:
|
163 |
-
|
|
|
164 |
|
165 |
@app.callback(
|
166 |
Output("audio-output", "children"),
|
|
|
167 |
Input("render-btn", "n_clicks"),
|
168 |
State("api-key-input", "value"),
|
169 |
State("script-output", "value"),
|
170 |
State("voice1-select", "value"),
|
171 |
State("voice2-select", "value"),
|
172 |
-
State("num-hosts", "value")
|
|
|
173 |
)
|
174 |
-
def
|
175 |
if n_clicks is None:
|
176 |
raise PreventUpdate
|
177 |
try:
|
178 |
-
sample_rate, audio_data =
|
179 |
-
|
180 |
-
|
|
|
|
|
181 |
except Exception as e:
|
182 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
183 |
|
|
|
184 |
if __name__ == '__main__':
|
185 |
print("Starting the Dash application...")
|
186 |
app.run(debug=True, host='0.0.0.0', port=7860)
|
|
|
1 |
import dash
|
2 |
from dash import dcc, html, Input, Output, State, callback
|
3 |
import dash_bootstrap_components as dbc
|
|
|
|
|
4 |
import google.generativeai as genai
|
5 |
import numpy as np
|
6 |
import edge_tts
|
7 |
import asyncio
|
8 |
+
import io
|
9 |
import re
|
10 |
+
import base64
|
11 |
import logging
|
|
|
12 |
from dash.exceptions import PreventUpdate
|
13 |
|
14 |
# Set up logging
|
|
|
61 |
'margin': '10px 0'
|
62 |
}
|
63 |
),
|
64 |
+
dbc.RadioItems(
|
65 |
id="duration",
|
66 |
options=[
|
67 |
+
{"label": "1-5 min", "value": "1-5 min"},
|
68 |
+
{"label": "5-10 min", "value": "5-10 min"},
|
69 |
+
{"label": "10-15 min", "value": "10-15 min"}
|
70 |
],
|
71 |
+
value="1-5 min",
|
72 |
inline=True
|
73 |
),
|
74 |
+
dbc.RadioItems(
|
75 |
id="num-hosts",
|
76 |
options=[
|
77 |
+
{"label": "1 host", "value": 1},
|
78 |
+
{"label": "2 hosts", "value": 2}
|
79 |
],
|
80 |
value=2,
|
81 |
inline=True
|
82 |
),
|
83 |
+
dbc.Select(id="lang1-select", options=[{"label": lang, "value": lang} for lang in language_names.values()]),
|
84 |
+
dbc.Select(id="voice1-select"),
|
85 |
+
dbc.Select(id="lang2-select", options=[{"label": lang, "value": lang} for lang in language_names.values()]),
|
86 |
+
dbc.Select(id="voice2-select"),
|
|
|
|
|
87 |
dbc.Button("Generate Script", id="generate-btn", color="primary", className="mt-3"),
|
88 |
dbc.Textarea(id="script-output", rows=10, className="mt-3"),
|
89 |
dbc.Button("Render Podcast", id="render-btn", color="success", className="mt-3"),
|
90 |
+
html.Div(id="audio-output"),
|
91 |
+
dcc.Download(id="download-audio")
|
92 |
])
|
93 |
+
])
|
94 |
], fluid=True)
|
95 |
|
96 |
# Callbacks
|
|
|
99 |
Input("lang1-select", "value")
|
100 |
)
|
101 |
def update_voice1_options(lang):
|
102 |
+
if lang == "None":
|
103 |
+
return []
|
104 |
selected_lang = next((key for key, value in language_names.items() if value == lang), None)
|
105 |
+
voices = voice_dict.get(selected_lang, [])
|
106 |
+
return [{"label": v, "value": v} for v in voices]
|
107 |
|
108 |
@app.callback(
|
109 |
Output("voice2-select", "options"),
|
110 |
Input("lang2-select", "value")
|
111 |
)
|
112 |
def update_voice2_options(lang):
|
113 |
+
if lang == "None":
|
114 |
+
return []
|
115 |
selected_lang = next((key for key, value in language_names.items() if value == lang), None)
|
116 |
+
voices = voice_dict.get(selected_lang, [])
|
117 |
+
return [{"label": v, "value": v} for v in voices]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
|
119 |
@app.callback(
|
120 |
Output("script-output", "value"),
|
|
|
122 |
State("api-key-input", "value"),
|
123 |
State("content-input", "value"),
|
124 |
State("duration", "value"),
|
125 |
+
State("num-hosts", "value"),
|
126 |
+
prevent_initial_call=True
|
127 |
)
|
128 |
def generate_script(n_clicks, api_key, content, duration, num_hosts):
|
129 |
if n_clicks is None:
|
130 |
raise PreventUpdate
|
131 |
try:
|
132 |
+
return generate_podcast_script(api_key, content, duration, num_hosts)
|
|
|
133 |
except Exception as e:
|
134 |
+
logger.error(f"Error generating script: {str(e)}")
|
135 |
+
return f"Error: {str(e)}"
|
136 |
|
137 |
@app.callback(
|
138 |
Output("audio-output", "children"),
|
139 |
+
Output("download-audio", "data"),
|
140 |
Input("render-btn", "n_clicks"),
|
141 |
State("api-key-input", "value"),
|
142 |
State("script-output", "value"),
|
143 |
State("voice1-select", "value"),
|
144 |
State("voice2-select", "value"),
|
145 |
+
State("num-hosts", "value"),
|
146 |
+
prevent_initial_call=True
|
147 |
)
|
148 |
+
async def render_and_download_podcast(n_clicks, api_key, script, voice1, voice2, num_hosts):
|
149 |
if n_clicks is None:
|
150 |
raise PreventUpdate
|
151 |
try:
|
152 |
+
sample_rate, audio_data = await render_podcast(api_key, script, voice1, voice2, num_hosts)
|
153 |
+
audio_bytes = audio_data.tobytes()
|
154 |
+
audio_base64 = base64.b64encode(audio_bytes).decode('utf-8')
|
155 |
+
audio_src = f"data:audio/wav;base64,{audio_base64}"
|
156 |
+
return html.Audio(src=audio_src, controls=True), dcc.send_bytes(audio_bytes, "podcast.wav")
|
157 |
except Exception as e:
|
158 |
+
logger.error(f"Error rendering podcast: {str(e)}")
|
159 |
+
return html.Div(f"Error: {str(e)}"), None
|
160 |
+
|
161 |
+
@app.callback(
|
162 |
+
Output("lang2-select", "style"),
|
163 |
+
Output("voice2-select", "style"),
|
164 |
+
Input("num-hosts", "value")
|
165 |
+
)
|
166 |
+
def update_second_voice_visibility(num_hosts):
|
167 |
+
if num_hosts == 2:
|
168 |
+
return {"display": "block"}, {"display": "block"}
|
169 |
+
else:
|
170 |
+
return {"display": "none"}, {"display": "none"}
|
171 |
|
172 |
+
# Run the app
|
173 |
if __name__ == '__main__':
|
174 |
print("Starting the Dash application...")
|
175 |
app.run(debug=True, host='0.0.0.0', port=7860)
|