CuddleBuddys commited on
Commit
1e1a9cb
·
verified ·
1 Parent(s): 6df81d9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -14
app.py CHANGED
@@ -15,42 +15,56 @@ from elevenlabs.client import ElevenLabs
15
  from elevenlabs import play, save
16
 
17
  # Load environment variables
 
18
  load_dotenv()
 
19
 
20
  # Argument parsing
21
  parser = argparse.ArgumentParser()
22
  parser.add_argument("--share", action='store_true', default=False, help="make link public")
23
  args = parser.parse_args()
 
24
 
25
  device = 'cuda' if torch.cuda.is_available() else 'cpu'
 
 
26
  output_dir = 'outputs'
27
  samples_dir = 'samples'
28
  os.makedirs(output_dir, exist_ok=True)
29
  os.makedirs(samples_dir, exist_ok=True)
 
30
 
31
  supported_languages = ['zh', 'en']
 
32
 
 
33
  MAILERSEND_API_KEY = os.getenv("MAILERSEND_API_KEY")
34
  MAILERSEND_DOMAIN = os.getenv("MAILERSEND_DOMAIN")
35
  MAILERSEND_SENDER_EMAIL = f"noreply@{MAILERSEND_DOMAIN}"
36
  MAILERSEND_SENDER_NAME = "Voice Clone App"
 
37
 
38
  ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
39
  client = ElevenLabs(api_key=ELEVENLABS_API_KEY)
 
40
 
41
  AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
42
  AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
43
  AWS_REGION_NAME = os.getenv('AWS_REGION_NAME')
44
  S3_BUCKET_NAME = os.getenv('S3_BUCKET_NAME')
 
45
 
46
  # List of blocked words
47
  BLOCKED_WORDS = ['Kill','hurt','shoot','gun','rifle','AR','semi automatic','knife','blade','sword','punch harm','disrupt','blackmail','steal','bitch','cunt','fuck','freaking','nigger','nigga','niggas','cracker','jew','oriental','fag','faggot','account','money','transfer','urgent','help','scared','policy','frightened','accident','fear','scam','address','social security number','assault','injure','maim','destroy','damage','threaten','intimidate','bully','menace','blackmail','extort','exploit','defame','steal','rob','embezzle','defraud Harass','jerk','idiot','stupid','moron','asshole','con','trick','swindle','defraud','payment','credit card','bank account','urgent','immediate','afraid','phone number','email','password']
 
48
 
49
  def get_blocked_words(text):
 
50
  # Split the text into words for accurate matching
51
  words_in_text = text.lower().split()
52
  # Find all blocked words present in the text
53
  blocked_found = [word for word in BLOCKED_WORDS if word.lower() in words_in_text]
 
54
  return blocked_found
55
 
56
  # Function to check for blocked words
@@ -59,6 +73,7 @@ def contains_blocked_words(text):
59
 
60
  # Function to send email with downloadable file using MailerSend
61
  def send_email_with_file(recipient_email, file_path, subject, body):
 
62
  try:
63
  mailer = emails.NewEmail(MAILERSEND_API_KEY)
64
 
@@ -82,7 +97,7 @@ def send_email_with_file(recipient_email, file_path, subject, body):
82
 
83
  with open(file_path, "rb") as file:
84
  attachment_content = base64.b64encode(file.read()).decode('utf-8')
85
-
86
  attachments = [
87
  {
88
  "filename": os.path.basename(file_path),
@@ -93,16 +108,21 @@ def send_email_with_file(recipient_email, file_path, subject, body):
93
  mailer.set_attachments(attachments, mail_body)
94
 
95
  response = mailer.send(mail_body)
 
96
 
97
  if response[0] == 202:
 
98
  return True
99
  else:
 
100
  return False
101
  except Exception as e:
 
102
  return False
103
 
104
  # S3 upload functions
105
  def upload_to_s3(local_file, bucket, s3_file):
 
106
  s3 = boto3.client('s3',
107
  aws_access_key_id=AWS_ACCESS_KEY_ID,
108
  aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
@@ -110,60 +130,79 @@ def upload_to_s3(local_file, bucket, s3_file):
110
 
111
  try:
112
  s3.upload_file(local_file, bucket, s3_file, ExtraArgs={'ACL': 'public-read'})
 
113
  return True
114
  except FileNotFoundError:
 
115
  return False
116
  except NoCredentialsError:
 
 
 
 
117
  return False
118
 
119
  def upload_voice_sample_and_metadata(sample_path, metadata, bucket):
 
120
  # Upload the voice sample
121
  sample_filename = os.path.basename(sample_path)
122
  s3_sample_path = f'voice_samples/{sample_filename}'
123
  if not upload_to_s3(sample_path, bucket, s3_sample_path):
 
124
  return False
125
 
126
  # Create and upload metadata file
127
  metadata['sample_s3_path'] = s3_sample_path
128
  metadata_filename = f"{os.path.splitext(sample_filename)[0]}_metadata.json"
129
  s3_metadata_path = f'voice_metadata/{metadata_filename}'
130
-
131
  # Save metadata to a temporary file
132
  temp_metadata_path = '/tmp/temp_metadata.json'
133
- with open(temp_metadata_path, 'w') as f:
134
- json.dump(metadata, f)
135
-
 
 
 
 
 
136
  # Upload metadata file
137
  if not upload_to_s3(temp_metadata_path, bucket, s3_metadata_path):
 
138
  return False
139
-
140
  # Clean up temporary file
141
- os.remove(temp_metadata_path)
 
 
 
 
142
 
 
143
  return True
144
 
145
  def predict(prompt, style, audio_file_pth, voice_name, customer_email, order_name):
 
146
  text_hint = 'Your file will only be saved for 24 hours.\n'
147
  if len(prompt) < 2:
148
  text_hint += "[ERROR] Please provide a longer prompt text.\n"
 
149
  return text_hint, None, None
150
  if len(prompt) > 200:
151
  text_hint += "[ERROR] Text length limited to 200 characters. Please try shorter text.\n"
 
152
  return text_hint, None, None
153
 
154
  blocked_words = get_blocked_words(prompt)
155
  if blocked_words:
156
  text_hint += f"[ERROR] Your text contains blocked words: {', '.join(blocked_words)}. Please remove them and try again.\n"
 
157
  return text_hint, None, None
158
 
159
  # Check if audio file was uploaded
160
  if audio_file_pth is None:
161
  text_hint += "[ERROR] No audio file was uploaded. Please upload a reference audio file.\n"
162
- return text_hint, None, None
163
-
164
- # Check if audio file was uploaded
165
- if audio_file_pth is None:
166
- text_hint += "[ERROR] No audio file was uploaded. Please upload a reference audio file.\n"
167
  return text_hint, None, None
168
 
169
  # Copy the sample audio to the samples directory
@@ -171,8 +210,10 @@ def predict(prompt, style, audio_file_pth, voice_name, customer_email, order_nam
171
  sample_filename = f"{voice_name}_{customer_email}_sample.mp3"
172
  sample_path = os.path.join(samples_dir, sample_filename)
173
  shutil.copy2(audio_file_pth, sample_path)
 
174
  except Exception as e:
175
  text_hint += f"[ERROR] Failed to copy audio file: {str(e)}\n"
 
176
  return text_hint, None, None
177
 
178
  # Prepare metadata
@@ -181,27 +222,48 @@ def predict(prompt, style, audio_file_pth, voice_name, customer_email, order_nam
181
  'email': customer_email,
182
  'order_name': order_name
183
  }
 
184
 
185
  # Use ElevenLabs API to clone the voice and generate audio
186
  try:
187
  full_voice_name = f"{voice_name}_{customer_email}"
 
188
  voice = client.clone(
189
  name=full_voice_name,
190
  description="A trial voice model for testing",
191
  files=[sample_path],
192
  )
 
 
 
193
  audio = client.generate(text=prompt, voice=voice)
194
  output_audio_path = os.path.join(output_dir, f"{full_voice_name}_output.mp3")
195
  save(audio, output_audio_path)
 
 
196
  text_hint += "Audio generated successfully using ElevenLabs.\n"
197
  except Exception as e:
198
  text_hint += f"[ERROR] ElevenLabs API error: {e}\n"
 
 
 
 
 
 
 
199
  return text_hint, None, None
200
 
201
  # Send email with the generated audio file
202
  email_subject = "Your Voice Clone Audio is Ready"
203
  email_body = f"Hi {voice_name},\n\nYour voice clone audio file is ready. Please find the attached file.\n\nBest regards,\nVoice Clone App"
 
 
 
 
 
 
204
  return text_hint, output_audio_path, sample_path
 
205
  with gr.Blocks(gr.themes.Glass()) as demo:
206
  with gr.Row():
207
  with gr.Column():
@@ -235,20 +297,30 @@ with gr.Blocks(gr.themes.Glass()) as demo:
235
  info="We'll send you a downloadable file to this email address."
236
  )
237
  tts_button = gr.Button("Start", elem_id="send-btn", visible=True)
 
238
 
239
  with gr.Column():
240
  out_text_gr = gr.Text(label="Info")
241
  audio_gr = gr.Audio(label="Generated Audio", autoplay=True)
242
  ref_audio_gr = gr.Audio(label="Original Audio Used")
 
243
 
244
- tts_button.click(predict, [input_text_gr, style_gr, ref_gr, voice_name_gr, customer_email_gr, order_gr], outputs=[out_text_gr, audio_gr, ref_audio_gr])
 
 
 
 
 
245
 
246
  demo.queue()
 
247
  demo.launch(debug=True, show_api=False, share=args.share)
 
248
 
249
  css = """
250
  footer {visibility: hidden}
251
  audio .btn-container {display: none}
252
  """
253
 
254
- demo.add_css(css)
 
 
15
  from elevenlabs import play, save
16
 
17
  # Load environment variables
18
+ print("Loading environment variables...")
19
  load_dotenv()
20
+ print("Environment variables loaded.")
21
 
22
  # Argument parsing
23
  parser = argparse.ArgumentParser()
24
  parser.add_argument("--share", action='store_true', default=False, help="make link public")
25
  args = parser.parse_args()
26
+ print(f"Arguments parsed. Share mode is set to: {args.share}")
27
 
28
  device = 'cuda' if torch.cuda.is_available() else 'cpu'
29
+ print(f"Using device: {device}")
30
+
31
  output_dir = 'outputs'
32
  samples_dir = 'samples'
33
  os.makedirs(output_dir, exist_ok=True)
34
  os.makedirs(samples_dir, exist_ok=True)
35
+ print(f"Directories '{output_dir}' and '{samples_dir}' are ready.")
36
 
37
  supported_languages = ['zh', 'en']
38
+ print(f"Supported languages: {supported_languages}")
39
 
40
+ # Load API keys and configurations
41
  MAILERSEND_API_KEY = os.getenv("MAILERSEND_API_KEY")
42
  MAILERSEND_DOMAIN = os.getenv("MAILERSEND_DOMAIN")
43
  MAILERSEND_SENDER_EMAIL = f"noreply@{MAILERSEND_DOMAIN}"
44
  MAILERSEND_SENDER_NAME = "Voice Clone App"
45
+ print("MailerSend configuration loaded.")
46
 
47
  ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
48
  client = ElevenLabs(api_key=ELEVENLABS_API_KEY)
49
+ print("ElevenLabs client initialized.")
50
 
51
  AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
52
  AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')
53
  AWS_REGION_NAME = os.getenv('AWS_REGION_NAME')
54
  S3_BUCKET_NAME = os.getenv('S3_BUCKET_NAME')
55
+ print("AWS S3 configuration loaded.")
56
 
57
  # List of blocked words
58
  BLOCKED_WORDS = ['Kill','hurt','shoot','gun','rifle','AR','semi automatic','knife','blade','sword','punch harm','disrupt','blackmail','steal','bitch','cunt','fuck','freaking','nigger','nigga','niggas','cracker','jew','oriental','fag','faggot','account','money','transfer','urgent','help','scared','policy','frightened','accident','fear','scam','address','social security number','assault','injure','maim','destroy','damage','threaten','intimidate','bully','menace','blackmail','extort','exploit','defame','steal','rob','embezzle','defraud Harass','jerk','idiot','stupid','moron','asshole','con','trick','swindle','defraud','payment','credit card','bank account','urgent','immediate','afraid','phone number','email','password']
59
+ print(f"Blocked words list loaded with {len(BLOCKED_WORDS)} words.")
60
 
61
  def get_blocked_words(text):
62
+ print("Checking for blocked words in the input text...")
63
  # Split the text into words for accurate matching
64
  words_in_text = text.lower().split()
65
  # Find all blocked words present in the text
66
  blocked_found = [word for word in BLOCKED_WORDS if word.lower() in words_in_text]
67
+ print(f"Blocked words found: {blocked_found}")
68
  return blocked_found
69
 
70
  # Function to check for blocked words
 
73
 
74
  # Function to send email with downloadable file using MailerSend
75
  def send_email_with_file(recipient_email, file_path, subject, body):
76
+ print(f"Sending email to {recipient_email} with file {file_path}...")
77
  try:
78
  mailer = emails.NewEmail(MAILERSEND_API_KEY)
79
 
 
97
 
98
  with open(file_path, "rb") as file:
99
  attachment_content = base64.b64encode(file.read()).decode('utf-8')
100
+
101
  attachments = [
102
  {
103
  "filename": os.path.basename(file_path),
 
108
  mailer.set_attachments(attachments, mail_body)
109
 
110
  response = mailer.send(mail_body)
111
+ print(f"MailerSend response: {response}")
112
 
113
  if response[0] == 202:
114
+ print("Email sent successfully.")
115
  return True
116
  else:
117
+ print("Failed to send email.")
118
  return False
119
  except Exception as e:
120
+ print(f"Error sending email: {e}")
121
  return False
122
 
123
  # S3 upload functions
124
  def upload_to_s3(local_file, bucket, s3_file):
125
+ print(f"Uploading {local_file} to S3 bucket {bucket} as {s3_file}...")
126
  s3 = boto3.client('s3',
127
  aws_access_key_id=AWS_ACCESS_KEY_ID,
128
  aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
 
130
 
131
  try:
132
  s3.upload_file(local_file, bucket, s3_file, ExtraArgs={'ACL': 'public-read'})
133
+ print("File uploaded to S3 successfully.")
134
  return True
135
  except FileNotFoundError:
136
+ print("File not found.")
137
  return False
138
  except NoCredentialsError:
139
+ print("AWS credentials not available.")
140
+ return False
141
+ except Exception as e:
142
+ print(f"Error uploading to S3: {e}")
143
  return False
144
 
145
  def upload_voice_sample_and_metadata(sample_path, metadata, bucket):
146
+ print("Uploading voice sample and metadata to S3...")
147
  # Upload the voice sample
148
  sample_filename = os.path.basename(sample_path)
149
  s3_sample_path = f'voice_samples/{sample_filename}'
150
  if not upload_to_s3(sample_path, bucket, s3_sample_path):
151
+ print("Failed to upload voice sample.")
152
  return False
153
 
154
  # Create and upload metadata file
155
  metadata['sample_s3_path'] = s3_sample_path
156
  metadata_filename = f"{os.path.splitext(sample_filename)[0]}_metadata.json"
157
  s3_metadata_path = f'voice_metadata/{metadata_filename}'
158
+
159
  # Save metadata to a temporary file
160
  temp_metadata_path = '/tmp/temp_metadata.json'
161
+ try:
162
+ with open(temp_metadata_path, 'w') as f:
163
+ json.dump(metadata, f)
164
+ print("Metadata file created.")
165
+ except Exception as e:
166
+ print(f"Error creating metadata file: {e}")
167
+ return False
168
+
169
  # Upload metadata file
170
  if not upload_to_s3(temp_metadata_path, bucket, s3_metadata_path):
171
+ print("Failed to upload metadata file.")
172
  return False
173
+
174
  # Clean up temporary file
175
+ try:
176
+ os.remove(temp_metadata_path)
177
+ print("Temporary metadata file removed.")
178
+ except Exception as e:
179
+ print(f"Error removing temporary file: {e}")
180
 
181
+ print("Voice sample and metadata uploaded successfully.")
182
  return True
183
 
184
  def predict(prompt, style, audio_file_pth, voice_name, customer_email, order_name):
185
+ print("Prediction started...")
186
  text_hint = 'Your file will only be saved for 24 hours.\n'
187
  if len(prompt) < 2:
188
  text_hint += "[ERROR] Please provide a longer prompt text.\n"
189
+ print("Prompt is too short.")
190
  return text_hint, None, None
191
  if len(prompt) > 200:
192
  text_hint += "[ERROR] Text length limited to 200 characters. Please try shorter text.\n"
193
+ print("Prompt is too long.")
194
  return text_hint, None, None
195
 
196
  blocked_words = get_blocked_words(prompt)
197
  if blocked_words:
198
  text_hint += f"[ERROR] Your text contains blocked words: {', '.join(blocked_words)}. Please remove them and try again.\n"
199
+ print(f"Blocked words detected: {blocked_words}")
200
  return text_hint, None, None
201
 
202
  # Check if audio file was uploaded
203
  if audio_file_pth is None:
204
  text_hint += "[ERROR] No audio file was uploaded. Please upload a reference audio file.\n"
205
+ print("No audio file uploaded.")
 
 
 
 
206
  return text_hint, None, None
207
 
208
  # Copy the sample audio to the samples directory
 
210
  sample_filename = f"{voice_name}_{customer_email}_sample.mp3"
211
  sample_path = os.path.join(samples_dir, sample_filename)
212
  shutil.copy2(audio_file_pth, sample_path)
213
+ print(f"Audio file copied to {sample_path}.")
214
  except Exception as e:
215
  text_hint += f"[ERROR] Failed to copy audio file: {str(e)}\n"
216
+ print(f"Error copying audio file: {e}")
217
  return text_hint, None, None
218
 
219
  # Prepare metadata
 
222
  'email': customer_email,
223
  'order_name': order_name
224
  }
225
+ print("Metadata prepared:", metadata)
226
 
227
  # Use ElevenLabs API to clone the voice and generate audio
228
  try:
229
  full_voice_name = f"{voice_name}_{customer_email}"
230
+ print(f"Cloning voice with name: {full_voice_name}")
231
  voice = client.clone(
232
  name=full_voice_name,
233
  description="A trial voice model for testing",
234
  files=[sample_path],
235
  )
236
+ print("Voice cloned successfully.")
237
+
238
+ print("Generating audio using the cloned voice...")
239
  audio = client.generate(text=prompt, voice=voice)
240
  output_audio_path = os.path.join(output_dir, f"{full_voice_name}_output.mp3")
241
  save(audio, output_audio_path)
242
+ print(f"Audio generated and saved to {output_audio_path}.")
243
+
244
  text_hint += "Audio generated successfully using ElevenLabs.\n"
245
  except Exception as e:
246
  text_hint += f"[ERROR] ElevenLabs API error: {e}\n"
247
+ print(f"ElevenLabs API error: {e}")
248
+ return text_hint, None, None
249
+
250
+ # Optionally upload to S3 (uncommented)
251
+ if not upload_voice_sample_and_metadata(sample_path, metadata, S3_BUCKET_NAME):
252
+ text_hint += "[ERROR] Failed to upload to S3.\n"
253
+ print("Failed to upload voice sample and metadata to S3.")
254
  return text_hint, None, None
255
 
256
  # Send email with the generated audio file
257
  email_subject = "Your Voice Clone Audio is Ready"
258
  email_body = f"Hi {voice_name},\n\nYour voice clone audio file is ready. Please find the attached file.\n\nBest regards,\nVoice Clone App"
259
+ if send_email_with_file(customer_email, output_audio_path, email_subject, email_body):
260
+ text_hint += "An email has been sent with your audio file.\n"
261
+ else:
262
+ text_hint += "[ERROR] Failed to send email.\n"
263
+ print("Failed to send email with the audio file.")
264
+
265
  return text_hint, output_audio_path, sample_path
266
+
267
  with gr.Blocks(gr.themes.Glass()) as demo:
268
  with gr.Row():
269
  with gr.Column():
 
297
  info="We'll send you a downloadable file to this email address."
298
  )
299
  tts_button = gr.Button("Start", elem_id="send-btn", visible=True)
300
+ print("Gradio input components initialized.")
301
 
302
  with gr.Column():
303
  out_text_gr = gr.Text(label="Info")
304
  audio_gr = gr.Audio(label="Generated Audio", autoplay=True)
305
  ref_audio_gr = gr.Audio(label="Original Audio Used")
306
+ print("Gradio output components initialized.")
307
 
308
+ tts_button.click(
309
+ predict,
310
+ [input_text_gr, style_gr, ref_gr, voice_name_gr, customer_email_gr, order_gr],
311
+ outputs=[out_text_gr, audio_gr, ref_audio_gr]
312
+ )
313
+ print("Gradio button click event bound to predict function.")
314
 
315
  demo.queue()
316
+ print("Launching Gradio demo...")
317
  demo.launch(debug=True, show_api=False, share=args.share)
318
+ print("Gradio demo launched.")
319
 
320
  css = """
321
  footer {visibility: hidden}
322
  audio .btn-container {display: none}
323
  """
324
 
325
+ demo.add_css(css)
326
+ print("Custom CSS added to Gradio interface.")