import gradio as gr import os import shutil import subprocess import threading import time # Global variables for dropdown and checkbox character_accent = None use_narrator_voice_y_n = None # List of languages for character accents languages = ['en', 'es', 'fr', 'de', 'it', 'pt', 'pl', 'tr', 'ru', 'nl', 'cs', 'ar', 'zh-cn', 'hu', 'ko', 'ja', 'hi'] # Function to process the ebook and start the subprocess def process_ebook(ebook_file, character_accent, use_narrator_voice_y_n, state): if not ebook_file: return "No file uploaded.", state # Convert selected accent to its index +1 character_accent = str(languages.index(character_accent) + 1) # Pre-download the xtts TOS agreed file import download_tos_agreed_file import nltk nltk.download('averaged_perceptron_tagger_eng') nltk.download('punkt_tab') # Download the en_core_web_sm spacy model subprocess.run(["python", "-m", "spacy", "download", "en_core_web_sm"]) # Create input_files directory if it doesn't exist input_dir = "input_files" if not os.path.exists(input_dir): os.mkdir(input_dir) # Copy the uploaded file to input_files folder input_file_path = os.path.join(input_dir, os.path.basename(ebook_file)) shutil.copy(ebook_file, input_file_path) # Print the name of the uploaded file ebook_file_name = os.path.basename(ebook_file) initial_output = f"Uploaded file: {ebook_file_name}\n" # Initialize state with subprocess info state = { "process": None, "output": initial_output, "lock": threading.Lock() } # Start the subprocess in a separate thread thread = threading.Thread(target=run_subprocess, args=(input_file_path, character_accent, use_narrator_voice_y_n, state), daemon=True) thread.start() return initial_output, state # Function to run the subprocess and capture its output def run_subprocess(input_file_path, character_accent, use_narrator_voice_y_n, state): try: # Start the subprocess with additional arguments process = subprocess.Popen( ["python3", "Headless_VoxNovel.py", input_file_path, character_accent, use_narrator_voice_y_n], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1 # Line-buffered ) with state["lock"]: state["process"] = process # Continuously read the subprocess output for line in iter(process.stdout.readline, ''): with state["lock"]: state["output"] += line process.stdout.close() process.wait() with state["lock"]: state["output"] += "\nProcess finished." except Exception as e: with state["lock"]: state["output"] += f"\nError: {str(e)}" # Function to send user input to the subprocess def send_input(user_input, state): if not state or "process" not in state or state["process"] is None: return "Process is not running." process = state["process"] if process.poll() is not None: return "Process has already finished." try: # Send the input followed by a newline process.stdin.write(user_input + "\n") process.stdin.flush() return "Input sent successfully." except Exception as e: return f"Failed to send input: {str(e)}" # Function to update the output display def get_output(state): if not state: return "No process started." with state["lock"]: return state["output"] # Function to list output files for downloading def list_output_files(): # List all files in the output directory for downloading output_dir = "output_audiobooks" if os.path.exists(output_dir): files = [ os.path.join(output_dir, f) for f in os.listdir(output_dir) if os.path.isfile(os.path.join(output_dir, f)) ] return files return [] # Gradio Interface with gr.Blocks() as gui: gr.Markdown("### Ebook to Audiobook Converter") with gr.Row(): with gr.Column(): ebook_input = gr.File( label="Upload your ebook file (epub, pdf, etc.)", type='filepath' # Specify that we want the file path ) # Add dropdown for character accent accent_dropdown = gr.Dropdown( label="Character Accent", choices=languages, value="en" # Default to English ) # Add checkbox for narrator voice narrator_checkbox = gr.Checkbox( label="Use Narrator Voice for All", value=False # Default is 'n' (false) ) process_button = gr.Button("Start Processing") status_output = gr.Textbox(label="Status", lines=20) # Initialize state state = gr.State() # Start processing and update status in real-time process_button.click( process_ebook, inputs=[ebook_input, accent_dropdown, narrator_checkbox, state], outputs=[status_output, state] ) with gr.Column(): gr.Markdown("### Subprocess Input") # Textbox to allow user to send input to subprocess user_input_box = gr.Textbox(label="Send Input to Subprocess") submit_input_button = gr.Button("Submit Input") submit_input_button.click( send_input, inputs=[user_input_box, state], outputs=status_output # Corrected to pass the actual Gradio component ) with gr.Column(): gr.Markdown("### Download Generated Audiobook Files") download_button = gr.Button("Reload Files") file_output = gr.File( label="Generated Audiobook Files", file_count="multiple", type='filepath' # Corrected the type to 'filepath' ) # Update the file_output component with the list of output files download_button.click(fn=list_output_files, inputs=[], outputs=file_output) # Periodically update the status_output textbox def periodic_update(state): return get_output(state) # Use Gradio's `every` method to update every second gui.load( periodic_update, inputs=state, outputs=status_output, every=1 # Update every second ) gui.launch()