nikkmitra commited on
Commit
aa06471
Β·
verified Β·
1 Parent(s): 81c0b37

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +181 -46
app.py CHANGED
@@ -6,6 +6,8 @@ from pymongo import MongoClient
6
  from bson import ObjectId
7
  from huggingface_hub import HfApi, HfFolder, delete_file
8
  import tempfile
 
 
9
 
10
  # Load environment variables
11
  load_dotenv()
@@ -57,12 +59,130 @@ def add_voice(category, name, is_free):
57
  # Check for duplicate voice name within the same category
58
  if voices_collection.find_one({"category": category, "voices.name": name}):
59
  st.error(f"Voice '{name}' already exists in category '{category}'.")
60
- return
61
  voices_collection.update_one(
62
  {"category": category},
63
  {"$push": {"voices": {"name": name, "free": is_free}}},
64
  upsert=True # Ensure the category exists
65
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  # Streamlit app
68
  st.title("Mitra Voices")
@@ -76,31 +196,57 @@ st.header("Upload Voice")
76
 
77
  if categories:
78
  # Select category from dropdown
79
- selected_category = st.selectbox("Select Category", categories, help="Choose the category to which you want to add the voice")
 
 
 
 
80
 
81
  # Input for voice name
82
- voice_name = st.text_input("Voice Name", placeholder="Enter the name of the voice")
 
 
 
83
 
84
  # File uploader for MP3 file
85
  st.write("Please upload an MP3 file of the voice:")
86
- audio_file = st.file_uploader("Choose an MP3 file", type="mp3", help="Select an MP3 file of the voice")
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  if selected_category and voice_name and audio_file:
89
  st.audio(audio_file, format='audio/mp3')
90
  st.write("Preview the uploaded audio:")
91
 
92
- if st.button("Upload Voice", type="primary"):
93
- if upload_to_huggingface(audio_file, voice_name):
94
- st.success(f"βœ… Uploaded {voice_name}'s voice to Hugging Face repository")
95
-
96
- # Add the new voice to the selected category in the database
97
- add_voice(selected_category, voice_name, False) # Assuming new uploads are not free by default
98
- st.success(f"βœ… Added {voice_name} to the '{selected_category}' category in the database")
99
-
100
- # Clear the form by rerunning the app
101
- st.rerun()
102
- else:
103
- st.error("❌ Failed to upload the voice file")
 
 
 
 
 
 
 
 
104
  elif selected_category and (voice_name or audio_file):
105
  if not voice_name:
106
  st.info("Please enter the voice name to proceed")
@@ -112,43 +258,25 @@ else:
112
  # Add a separator
113
  st.markdown("---")
114
 
115
- # Function to clear the database
116
- def clear_database():
117
- voices_collection.delete_many({})
118
-
119
  # Button to clear the database
120
  if st.button("Clear Database"):
121
  clear_database()
122
  st.success("Database cleared successfully.")
123
  st.rerun()
124
 
125
- # Function to remove a voice
126
- def remove_voice(category, name):
127
- # Remove from MongoDB
128
- result = voices_collection.update_one(
129
- {"category": category},
130
- {"$pull": {"voices": {"name": name}}}
131
- )
132
-
133
- # If the voice was successfully removed from MongoDB, also delete from Hugging Face
134
- if result.modified_count > 0:
135
- try:
136
- api = HfApi()
137
- delete_file(
138
- path_in_repo=f"voices/{name}.mp3",
139
- repo_id="nikkmitra/clone",
140
- repo_type="space",
141
- token=hf_token
142
- )
143
- st.success(f"Deleted {name}'s voice file from Hugging Face repository")
144
- except Exception as e:
145
- st.warning(f"Failed to delete {name}'s voice file from Hugging Face: {str(e)}")
146
-
147
- return result.modified_count > 0
148
 
149
  # Add new voice category
150
  st.header("Add New Voice Category")
151
- new_category_name = st.text_input("New Category Name", placeholder="Enter new category name")
 
 
 
152
 
153
  if st.button("Add Category"):
154
  if new_category_name:
@@ -172,6 +300,15 @@ for category in all_voices:
172
  col1, col2, col3 = st.columns([3, 1, 1])
173
  with col1:
174
  st.write(f"{voice['name']} ({'Free' if voice['free'] else 'Premium'})")
 
 
 
 
 
 
 
 
 
175
  with col2:
176
  if st.button("Remove", key=f"remove_{category['category']}_{voice['name']}_{i}"):
177
  if remove_voice(category['category'], voice['name']):
@@ -186,5 +323,3 @@ for category in all_voices:
186
  {"$set": {"voices.$.free": not voice['free']}}
187
  )
188
  st.rerun()
189
-
190
- # Note: We don't need to explicitly close the MongoDB connection when using Streamlit
 
6
  from bson import ObjectId
7
  from huggingface_hub import HfApi, HfFolder, delete_file
8
  import tempfile
9
+ import base64
10
+ import requests # New import
11
 
12
  # Load environment variables
13
  load_dotenv()
 
59
  # Check for duplicate voice name within the same category
60
  if voices_collection.find_one({"category": category, "voices.name": name}):
61
  st.error(f"Voice '{name}' already exists in category '{category}'.")
62
+ return False
63
  voices_collection.update_one(
64
  {"category": category},
65
  {"$push": {"voices": {"name": name, "free": is_free}}},
66
  upsert=True # Ensure the category exists
67
  )
68
+ return True
69
+
70
+ # Function to add a new voice with base64
71
+ def add_voice_base64(category, name, is_free, audio_file):
72
+ # Check for duplicate voice name within the same category
73
+ if voices_collection.find_one({"category": category, "voices.name": name}):
74
+ st.error(f"Voice '{name}' already exists in category '{category}'.")
75
+ return False
76
+
77
+ # Encode the audio file to base64
78
+ audio_base64 = base64.b64encode(audio_file.getvalue()).decode('utf-8')
79
+
80
+ # Update the database with the new voice
81
+ voices_collection.update_one(
82
+ {"category": category},
83
+ {"$push": {"voices": {"name": name, "free": is_free, "base64": audio_base64}}},
84
+ upsert=True # Ensure the category exists
85
+ )
86
+
87
+ return True
88
+
89
+ # Function to remove a voice
90
+ def remove_voice(category, name):
91
+ # Find the voice to determine storage type
92
+ voice_doc = voices_collection.find_one({"category": category, "voices.name": name})
93
+ if not voice_doc:
94
+ st.error(f"Voice '{name}' not found in category '{category}'.")
95
+ return False
96
+ voice_data = next((v for v in voice_doc['voices'] if v['name'] == name), None)
97
+ if not voice_data:
98
+ st.error(f"Voice '{name}' not found in category '{category}'.")
99
+ return False
100
+
101
+ # Remove from MongoDB
102
+ result = voices_collection.update_one(
103
+ {"category": category},
104
+ {"$pull": {"voices": {"name": name}}}
105
+ )
106
+
107
+ # If removal was successful, handle deletion from Hugging Face if applicable
108
+ if result.modified_count > 0:
109
+ if 'base64' not in voice_data:
110
+ # Voice is stored on Hugging Face
111
+ try:
112
+ api = HfApi()
113
+ delete_file(
114
+ path_in_repo=f"voices/{name}.mp3",
115
+ repo_id="nikkmitra/clone",
116
+ repo_type="space",
117
+ token=hf_token
118
+ )
119
+ st.success(f"Deleted {name}'s voice file from Hugging Face repository")
120
+ except Exception as e:
121
+ st.warning(f"Failed to delete {name}'s voice file from Hugging Face: {str(e)}")
122
+ else:
123
+ # Voice was stored as base64 in MongoDB
124
+ st.success(f"Removed {name} from the '{category}' category in the database")
125
+ return result.modified_count > 0
126
+
127
+ # Function to update all voices by adding base64 field
128
+ def update_all_voices():
129
+ st.info("Starting the bulk update process. This may take a while depending on the number of voices.")
130
+
131
+ # Fetch all categories and their voices
132
+ all_categories = voices_collection.find()
133
+
134
+ total_voices = 0
135
+ updated_voices = 0
136
+ failed_voices = []
137
+
138
+ for category in all_categories:
139
+ category_name = category['category']
140
+ voices = category.get('voices', [])
141
+
142
+ for voice in voices:
143
+ total_voices += 1
144
+ voice_name = voice['name']
145
+
146
+ # Check if 'base64' field already exists
147
+ if 'base64' in voice:
148
+ continue # Skip voices already updated
149
+
150
+ # Assume the voice is stored on Hugging Face
151
+ file_path = f"voices/{voice_name}.mp3"
152
+ repo_id = "nikkmitra/clone" # Update this if different
153
+ url = f"https://huggingface.co/{repo_id}/resolve/main/{file_path}"
154
+
155
+ try:
156
+ # Download the audio file from Hugging Face
157
+ response = requests.get(url, headers={"Authorization": f"Bearer {hf_token}"})
158
+ if response.status_code == 200:
159
+ audio_data = response.content
160
+
161
+ # Encode to base64
162
+ audio_base64 = base64.b64encode(audio_data).decode('utf-8')
163
+
164
+ # Update the MongoDB document
165
+ voices_collection.update_one(
166
+ {"category": category_name, "voices.name": voice_name},
167
+ {"$set": {"voices.$.base64": audio_base64}}
168
+ )
169
+
170
+ updated_voices += 1
171
+ else:
172
+ failed_voices.append((category_name, voice_name, f"HTTP {response.status_code}"))
173
+ except Exception as e:
174
+ failed_voices.append((category_name, voice_name, str(e)))
175
+
176
+ # Summary of the update process
177
+ st.success(f"Bulk update completed. Total voices processed: {total_voices}")
178
+ st.success(f"Voices successfully updated with base64: {updated_voices}")
179
+
180
+ if failed_voices:
181
+ st.error(f"Failed to update {len(failed_voices)} voices:")
182
+ for fail in failed_voices:
183
+ st.error(f"Category: {fail[0]}, Voice: {fail[1]}, Reason: {fail[2]}")
184
+ else:
185
+ st.success("All voices updated successfully!")
186
 
187
  # Streamlit app
188
  st.title("Mitra Voices")
 
196
 
197
  if categories:
198
  # Select category from dropdown
199
+ selected_category = st.selectbox(
200
+ "Select Category",
201
+ categories,
202
+ help="Choose the category to which you want to add the voice"
203
+ )
204
 
205
  # Input for voice name
206
+ voice_name = st.text_input(
207
+ "Voice Name",
208
+ placeholder="Enter the name of the voice"
209
+ )
210
 
211
  # File uploader for MP3 file
212
  st.write("Please upload an MP3 file of the voice:")
213
+ audio_file = st.file_uploader(
214
+ "Choose an MP3 file",
215
+ type="mp3",
216
+ help="Select an MP3 file of the voice"
217
+ )
218
+
219
+ # Storage method selection
220
+ storage_method = st.radio(
221
+ "Select Storage Method",
222
+ ("Upload to Hugging Face", "Store as Base64 in MongoDB"),
223
+ help="Choose how you want to store the voice file."
224
+ )
225
 
226
  if selected_category and voice_name and audio_file:
227
  st.audio(audio_file, format='audio/mp3')
228
  st.write("Preview the uploaded audio:")
229
 
230
+ if storage_method == "Upload to Hugging Face":
231
+ if st.button("Upload Voice", type="primary"):
232
+ if upload_to_huggingface(audio_file, voice_name):
233
+ st.success(f"βœ… Uploaded {voice_name}'s voice to Hugging Face repository")
234
+
235
+ # Add the new voice to the selected category in the database
236
+ if add_voice(selected_category, voice_name, False): # Assuming new uploads are not free by default
237
+ st.success(f"βœ… Added {voice_name} to the '{selected_category}' category in the database")
238
+
239
+ # Clear the form by rerunning the app
240
+ st.rerun()
241
+ else:
242
+ st.error("❌ Failed to upload the voice file")
243
+ elif storage_method == "Store as Base64 in MongoDB":
244
+ if st.button("Store Voice", type="primary"):
245
+ if add_voice_base64(selected_category, voice_name, False, audio_file):
246
+ st.success(f"βœ… Stored {voice_name}'s voice in the '{selected_category}' category in the database as base64")
247
+ st.rerun()
248
+ else:
249
+ st.error("❌ Failed to store the voice file as base64")
250
  elif selected_category and (voice_name or audio_file):
251
  if not voice_name:
252
  st.info("Please enter the voice name to proceed")
 
258
  # Add a separator
259
  st.markdown("---")
260
 
 
 
 
 
261
  # Button to clear the database
262
  if st.button("Clear Database"):
263
  clear_database()
264
  st.success("Database cleared successfully.")
265
  st.rerun()
266
 
267
+ # Bulk Update Section
268
+ st.markdown("---")
269
+ st.header("Bulk Update Voices")
270
+
271
+ if st.button("Update All Voices"):
272
+ update_all_voices()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
274
  # Add new voice category
275
  st.header("Add New Voice Category")
276
+ new_category_name = st.text_input(
277
+ "New Category Name",
278
+ placeholder="Enter new category name"
279
+ )
280
 
281
  if st.button("Add Category"):
282
  if new_category_name:
 
300
  col1, col2, col3 = st.columns([3, 1, 1])
301
  with col1:
302
  st.write(f"{voice['name']} ({'Free' if voice['free'] else 'Premium'})")
303
+ if 'base64' in voice:
304
+ try:
305
+ audio_data = base64.b64decode(voice['base64'])
306
+ st.audio(audio_data, format='audio/mp3')
307
+ except Exception as e:
308
+ st.error(f"Failed to load audio for {voice['name']}: {str(e)}")
309
+ else:
310
+ # If stored on Hugging Face, provide a link or fetch directly
311
+ st.write("πŸ”— Stored on Hugging Face")
312
  with col2:
313
  if st.button("Remove", key=f"remove_{category['category']}_{voice['name']}_{i}"):
314
  if remove_voice(category['category'], voice['name']):
 
323
  {"$set": {"voices.$.free": not voice['free']}}
324
  )
325
  st.rerun()