bluenevus commited on
Commit
644ec15
·
verified ·
1 Parent(s): 7026918

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -62
app.py CHANGED
@@ -12,9 +12,6 @@ import logging
12
  from dash.exceptions import PreventUpdate
13
  import pandas as pd
14
  import time
15
- import os
16
- from huggingface_hub import HfApi
17
- from dash import callback_context
18
 
19
  # Set up logging
20
  logging.basicConfig(level=logging.INFO)
@@ -23,12 +20,8 @@ logger = logging.getLogger(__name__)
23
  # Initialize Dash app
24
  app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
25
 
26
- # Initialize Gemini AI with the API key from HF secret
27
- gemini_api_key = os.environ.get("GEMINI_API_KEY")
28
- if not gemini_api_key:
29
- raise ValueError("GEMINI_API_KEY not found in environment variables. Please set it as a secret in your Hugging Face Space.")
30
-
31
- genai.configure(api_key=gemini_api_key)
32
 
33
  def generate_podcast_script(api_key, content, duration, num_hosts):
34
  genai.configure(api_key=api_key)
@@ -47,8 +40,6 @@ def generate_podcast_script(api_key, content, duration, num_hosts):
47
  Do not use any special characters or markdown. Only include the monologue with proper punctuation.
48
  Ensure the content flows naturally and stays relevant to the topic.
49
  Limit the script length to match the requested duration of {duration}.
50
- Do not put an intro our outro music as I only need the dialog
51
- The dialog must have proper punctuation like apostrophes
52
  """
53
  else:
54
  prompt = f"""
@@ -63,8 +54,6 @@ def generate_podcast_script(api_key, content, duration, num_hosts):
63
  Do not use any special characters or markdown. Only include the alternating dialogue lines with proper punctuation.
64
  Ensure the conversation flows naturally and stays relevant to the topic.
65
  Limit the script length to match the requested duration of {duration}.
66
- Do not put an intro our outro music as I only need the dialog
67
- The dialog must have proper punctuation like apostrophes
68
  """
69
 
70
  response = model.generate_content(prompt)
@@ -166,6 +155,7 @@ app.layout = dbc.Container([
166
 
167
  dbc.Card([
168
  dbc.CardBody([
 
169
  dbc.Textarea(id="content-input", placeholder="Paste your content or upload a document", rows=5, className="my-3"),
170
  dcc.Upload(
171
  id='document-upload',
@@ -254,66 +244,108 @@ def update_voice2_options(lang):
254
 
255
  @app.callback(
256
  [Output("script-output", "value"),
257
- Output("script-progress", "value"),
258
- Output("audio-output", "children"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  Output("download-audio", "data"),
260
  Output("podcast-progress", "value")],
261
- [Input("generate-btn", "n_clicks"),
262
- Input("generate-podcast-btn", "n_clicks")],
263
- [State("content-input", "value"),
264
- State("duration", "value"),
265
- State("num-hosts", "value"),
266
  State("voice1-select", "value"),
267
  State("voice2-select", "value"),
268
- State("script-output", "value")],
269
  prevent_initial_call=True
270
  )
271
- def generate_script_and_podcast(generate_clicks, podcast_clicks, content, duration, num_hosts, voice1, voice2, script):
272
- ctx = callback_context
273
- triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
274
-
275
- if not ctx.triggered:
276
  raise PreventUpdate
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
 
278
- if triggered_id == "generate-btn":
279
- try:
280
- for i in range(10):
281
- time.sleep(0.5) # Simulate progress
282
- script = generate_podcast_script(content, duration, num_hosts)
283
- return script, 100, dash.no_update, dash.no_update, dash.no_update
284
- except Exception as e:
285
- logger.error(f"Error generating script: {str(e)}")
286
- return f"Error: {str(e)}", 0, dash.no_update, dash.no_update, dash.no_update
 
287
 
288
- elif triggered_id == "generate-podcast-btn":
 
 
 
 
 
 
 
 
 
289
  try:
290
- # Run the async function in a synchronous context
291
- sample_rate, audio_data = asyncio.run(render_podcast(script, voice1, voice2, num_hosts))
292
-
293
- # Convert numpy array to WAV
294
- wav_audio = AudioSegment(
295
- audio_data.tobytes(),
296
- frame_rate=sample_rate,
297
- sample_width=audio_data.dtype.itemsize,
298
- channels=1
299
- )
300
-
301
- # Convert WAV to MP3
302
- buffer = io.BytesIO()
303
- wav_audio.export(buffer, format="mp3")
304
- buffer.seek(0)
305
- mp3_bytes = buffer.getvalue()
306
-
307
- # Create base64 audio for playback
308
- audio_base64 = base64.b64encode(mp3_bytes).decode('utf-8')
309
- audio_src = f"data:audio/mp3;base64,{audio_base64}"
310
-
311
- return dash.no_update, dash.no_update, html.Audio(src=audio_src, controls=True), dcc.send_bytes(mp3_bytes, "podcast.mp3"), 100
312
  except Exception as e:
313
- logger.error(f"Error rendering podcast: {str(e)}")
314
- return dash.no_update, dash.no_update, html.Div(f"Error: {str(e)}"), None, 0
315
-
316
- return dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update
317
 
318
  # Run the app
319
  if __name__ == '__main__':
 
12
  from dash.exceptions import PreventUpdate
13
  import pandas as pd
14
  import time
 
 
 
15
 
16
  # Set up logging
17
  logging.basicConfig(level=logging.INFO)
 
20
  # Initialize Dash app
21
  app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
22
 
23
+ # Initialize Gemini AI
24
+ genai.configure(api_key='YOUR_GEMINI_API_KEY')
 
 
 
 
25
 
26
  def generate_podcast_script(api_key, content, duration, num_hosts):
27
  genai.configure(api_key=api_key)
 
40
  Do not use any special characters or markdown. Only include the monologue with proper punctuation.
41
  Ensure the content flows naturally and stays relevant to the topic.
42
  Limit the script length to match the requested duration of {duration}.
 
 
43
  """
44
  else:
45
  prompt = f"""
 
54
  Do not use any special characters or markdown. Only include the alternating dialogue lines with proper punctuation.
55
  Ensure the conversation flows naturally and stays relevant to the topic.
56
  Limit the script length to match the requested duration of {duration}.
 
 
57
  """
58
 
59
  response = model.generate_content(prompt)
 
155
 
156
  dbc.Card([
157
  dbc.CardBody([
158
+ dbc.Input(id="api-key-input", type="password", placeholder="Enter your Gemini API Key"),
159
  dbc.Textarea(id="content-input", placeholder="Paste your content or upload a document", rows=5, className="my-3"),
160
  dcc.Upload(
161
  id='document-upload',
 
244
 
245
  @app.callback(
246
  [Output("script-output", "value"),
247
+ Output("script-progress", "value")],
248
+ Input("generate-btn", "n_clicks"),
249
+ [State("api-key-input", "value"),
250
+ State("content-input", "value"),
251
+ State("duration", "value"),
252
+ State("num-hosts", "value")],
253
+ prevent_initial_call=True
254
+ )
255
+ def generate_script(n_clicks, api_key, content, duration, num_hosts):
256
+ if n_clicks is None:
257
+ raise PreventUpdate
258
+ try:
259
+ for i in range(10):
260
+ time.sleep(0.5) # Simulate progress
261
+ # Instead of yielding, we'll just pass and update at the end
262
+ pass
263
+ script = generate_podcast_script(api_key, content, duration, num_hosts)
264
+ return script, 100
265
+ except Exception as e:
266
+ logger.error(f"Error generating script: {str(e)}")
267
+ return f"Error: {str(e)}", 0
268
+
269
+ @app.callback(
270
+ [Output("audio-output", "children"),
271
  Output("download-audio", "data"),
272
  Output("podcast-progress", "value")],
273
+ Input("generate-podcast-btn", "n_clicks"),
274
+ [State("api-key-input", "value"),
275
+ State("script-output", "value"),
 
 
276
  State("voice1-select", "value"),
277
  State("voice2-select", "value"),
278
+ State("num-hosts", "value")],
279
  prevent_initial_call=True
280
  )
281
+ def render_and_download_podcast(n_clicks, api_key, script, voice1, voice2, num_hosts):
282
+ if n_clicks is None:
 
 
 
283
  raise PreventUpdate
284
+ try:
285
+ # Run the async function in a synchronous context
286
+ sample_rate, audio_data = asyncio.run(render_podcast(api_key, script, voice1, voice2, num_hosts))
287
+
288
+ # Convert numpy array to WAV
289
+ wav_audio = AudioSegment(
290
+ audio_data.tobytes(),
291
+ frame_rate=sample_rate,
292
+ sample_width=audio_data.dtype.itemsize,
293
+ channels=1
294
+ )
295
+
296
+ # Convert WAV to MP3
297
+ buffer = io.BytesIO()
298
+ wav_audio.export(buffer, format="mp3")
299
+ buffer.seek(0)
300
+ mp3_bytes = buffer.getvalue()
301
+
302
+ # Create base64 audio for playback
303
+ audio_base64 = base64.b64encode(mp3_bytes).decode('utf-8')
304
+ audio_src = f"data:audio/mp3;base64,{audio_base64}"
305
+
306
+ return html.Audio(src=audio_src, controls=True), dcc.send_bytes(mp3_bytes, "podcast.mp3"), 100
307
+ except Exception as e:
308
+ logger.error(f"Error rendering podcast: {str(e)}")
309
+ return html.Div(f"Error: {str(e)}"), None, 0
310
 
311
+ @app.callback(
312
+ [Output("lang2-select", "style"),
313
+ Output("voice2-select", "style")],
314
+ Input("num-hosts", "value")
315
+ )
316
+ def update_second_voice_visibility(num_hosts):
317
+ if num_hosts == 2:
318
+ return {"display": "block"}, {"display": "block"}
319
+ else:
320
+ return {"display": "none"}, {"display": "none"}
321
 
322
+ @app.callback(
323
+ Output("content-input", "value"),
324
+ Input("document-upload", "contents"),
325
+ State("document-upload", "filename"),
326
+ prevent_initial_call=True
327
+ )
328
+ def update_content(contents, filename):
329
+ if contents is not None:
330
+ content_type, content_string = contents.split(',')
331
+ decoded = base64.b64decode(content_string)
332
  try:
333
+ if 'csv' in filename:
334
+ # Assume that the user uploaded a CSV file
335
+ df = pd.read_csv(io.StringIO(decoded.decode('utf-8')))
336
+ return df.to_string()
337
+ elif 'xls' in filename:
338
+ # Assume that the user uploaded an excel file
339
+ df = pd.read_excel(io.BytesIO(decoded))
340
+ return df.to_string()
341
+ elif 'txt' in filename or 'md' in filename:
342
+ # Assume that the user uploaded a text or markdown file
343
+ return decoded.decode('utf-8')
344
+ else:
345
+ return 'Unsupported file type. Please upload a CSV, Excel, text, or markdown file.'
 
 
 
 
 
 
 
 
 
346
  except Exception as e:
347
+ logger.error(f"Error processing uploaded file: {str(e)}")
348
+ return f'There was an error processing this file: {str(e)}'
 
 
349
 
350
  # Run the app
351
  if __name__ == '__main__':