from flask import Flask, request, jsonify import os import requests from bs4 import BeautifulSoup import ebooklib from ebooklib import epub from urllib.parse import urlparse import io import os import torch from openvoice import se_extractor from openvoice.api import ToneColorConverter from melo.api import TTS from voice_cloning import VoiceCloningManager app = Flask(__name__) # --- Voice Cloning Setup --- # Initialize the VoiceCloningManager once when the app starts. # This loads the models into memory so they don't have to be reloaded for each request. print("Initializing Voice Cloning Manager...") voice_cloning_manager = VoiceCloningManager() print("Voice Cloning Manager Initialized.") # ------------------------- def get_text_from_url(url): try: response = requests.get(url) response.raise_for_status() # Raise an exception for bad status codes content_type = response.headers.get('content-type') if 'epub' in content_type: book = epub.read_epub(io.BytesIO(response.content)) text_content = "" for item in book.get_items_of_type(ebooklib.ITEM_DOCUMENT): soup = BeautifulSoup(item.get_body_content(), 'html.parser') text_content += soup.get_text() + "\n" return text_content elif 'html' in content_type: soup = BeautifulSoup(response.content, 'html.parser') return soup.get_text() elif 'text' in content_type: return response.text else: # Fallback for other content types or if content-type is not specific # You might want to add more sophisticated handling here return response.text except requests.exceptions.RequestException as e: print(f"Error fetching URL: {e}") return None def is_url(string): try: result = urlparse(string) return all([result.scheme, result.netloc]) except ValueError: return False @app.route('/api/voice-transfer', methods=['POST']) def voice_transfer(): if 'voice_file' not in request.files: return jsonify({"error": "No voice file part"}), 400 file = request.files['voice_file'] if file.filename == '': return jsonify({"error": "No selected file"}), 400 if file: # Save the uploaded file temporarily # In a production environment, you'd want a more robust storage solution upload_folder = 'uploads' if not os.path.exists(upload_folder): os.makedirs(upload_folder) voice_file_path = os.path.join(upload_folder, file.filename) file.save(voice_file_path) text_input = request.form.get('text') print(text_input) if not text_input: return jsonify({"error": "No text or text_url provided"}), 400 text_content = "" if is_url(text_input): text_content = get_text_from_url(text_input) if text_content is None: return jsonify({"error": "Failed to retrieve or parse content from URL"}), 400 else: print("Not URL") text_content = text_input # --- Perform Voice Cloning --- print("Starting voice cloning process...") # Call the new manager to generate the audio output_file_path = voice_cloning_manager.generate_cloned_voice_audio(text_content, voice_file_path) if output_file_path is None: return jsonify({"error": "Failed to generate voice file."}), 500 return jsonify({ "message": "Voice transfer process completed successfully.", "output_file": output_file_path }) if __name__ == '__main__': app.run(debug=True, port=5001)