import gradio as gr import os import shutil import subprocess import threading import time # Function to process the ebook and start the subprocess def process_ebook(ebook_file, state): if not ebook_file: return "No file uploaded.", state # 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, state), daemon=True) thread.start() return initial_output, state # Function to run the subprocess and capture its output def run_subprocess(input_file_path, state): try: # Start the subprocess process = subprocess.Popen( ["python3", "Auto_VoxNovel.py", input_file_path], 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 ) 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, 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='file' # Use 'file' type for gr.File component ) # 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()