Oneto8-test / app.py
Tamiloneto8's picture
Update app.py
734e9ef verified
import os
import logging
import gradio as gr
from gradio_client import Client, handle_file
import gradio.themes as gr_themes
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# It's recommended to set the HUGGINGFACE_TOKEN as an environment variable
token = os.getenv("HUGGINGFACE_TOKEN")
def create_DubIndic_interface():
"""
Creates and configures the Gradio interface for the DubIndic application.
"""
try:
# Connect to the Gradio client on Hugging Face Spaces
client = Client("Tamiloneto8/Test1", hf_token=token, verbose=True)
logger.info("Successfully connected to Gradio client.")
except Exception as e:
logger.error("Error connecting to the private space: %s", e, exc_info=True)
# Create a fallback interface to show the connection error
with gr.Blocks() as demo:
gr.Markdown("# 🎬 DubIndic - Connection Error")
gr.Textbox(
value=f"Failed to connect to the Hugging Face Space. Please ensure the Space is running and the token is correct. Error: {e}",
label="Error",
interactive=False
)
return demo
# Define wrapper functions to call the API endpoints
def start_processing(audio_file, target_language):
if not audio_file or not target_language:
return (
"Please provide both an audio file and a target language.",
None, "", "", None, "",
gr.update(visible=False), gr.update(visible=False),
None, gr.update(visible=False), None, gr.update(visible=False)
)
try:
logger.info("Calling /process_audio_pipeline_step1 with file: %s", audio_file)
result = client.predict(
audio_file=handle_file(audio_file),
target_lang=target_language,
api_name="/process_audio_pipeline_step1"
)
logger.info("Received result from step 1: %s", result)
# API returns a 7-element tuple, we map it to our UI outputs
# [status, internal_val, orig_audio, trans, transl, dubbed_audio, progress]
return (
result[0], result[2], result[3], result[4], result[5], result[6],
gr.update(visible=True), gr.update(visible=True), # Make edit and merge sections visible
result[2] if result[2] else None, gr.update(visible=True if result[2] else False),
result[5] if result[5] else None, gr.update(visible=True if result[5] else False)
)
except Exception as e:
logger.error("Error in start_processing: %s", e, exc_info=True)
return (
f"Error starting the process: {e}",
None, "", "", None, "",
gr.update(visible=False), gr.update(visible=False),
None, gr.update(visible=False), None, gr.update(visible=False)
)
def navigate_chunk(transcription, translation, direction):
# The API uses different endpoints for next/previous navigation
# We assume /lambda is for previous and /lambda_1 is for next
api_to_call = "/lambda" if direction == "prev" else "/lambda_1"
try:
logger.info("Calling %s to navigate.", api_to_call)
result = client.predict(
t=transcription,
tr=translation,
api_name=api_to_call
)
logger.info("Received result from navigation: %s", result)
# API returns a 6-element tuple
# [internal_val, orig_audio, trans, transl, dubbed_audio, progress]
return (result[1], result[2], result[3], result[4], result[5],
result[1] if result[1] else None,
result[4] if result[4] else None)
except Exception as e:
logger.error("Error navigating chunks: %s", e, exc_info=True)
return None, f"Error navigating chunks: {e}", "", None, "", None, None
def generate_dubbed_chunk(transcription, translation):
if not transcription and not translation:
return None, None
try:
logger.info("Calling /generate_dubbed_chunk.")
dubbed_path = client.predict(
transcription=transcription,
translation=translation,
api_name="/generate_dubbed_chunk"
)
logger.info("Received dubbed chunk: %s", dubbed_path)
return dubbed_path, gr.update(value=dubbed_path, visible=True) if dubbed_path else gr.update(visible=False)
except Exception as e:
logger.error("Error generating dubbed chunk: %s", e, exc_info=True)
return None, None
def finalize_current_chunk():
try:
logger.info("Calling /finalize_current_chunk.")
progress = client.predict(api_name="/finalize_current_chunk")
logger.info("Received finalization progress: %s", progress)
return progress
except Exception as e:
logger.error("Error finalizing chunk: %s", e, exc_info=True)
return f"Error finalizing chunk: {e}"
def merge_all_chunks():
try:
logger.info("Calling /merge_audio_files.")
final_status, final_audio = client.predict(api_name="/merge_audio_files")
logger.info("Received final merged audio.")
return final_status, final_audio
except Exception as e:
logger.error("Error merging audio files: %s", e, exc_info=True)
return f"Error merging audio: {e}", None
# Create custom theme with orange-red gradient colors
custom_theme = gr_themes.Soft(
primary_hue="orange",
secondary_hue="red",
neutral_hue="gray"
).set(
button_primary_background_fill="linear-gradient(45deg, #f97316, #ef4444)",
button_primary_background_fill_hover="linear-gradient(45deg, #ea580c, #dc2626)",
button_primary_text_color="white",
block_background_fill="rgba(255, 255, 255, 0.05)",
block_border_color="rgba(249, 115, 22, 0.2)",
input_background_fill="rgba(255, 255, 255, 0.9)",
input_border_color="rgba(249, 115, 22, 0.3)",
input_border_color_focus="rgba(239, 68, 68, 0.6)"
)
# Define the Gradio Interface using Blocks for a custom layout
with gr.Blocks(theme=custom_theme, title="DubIndic - AI Audio Dubbing", css="""
.gradio-container {
background: linear-gradient(135deg, rgba(249, 115, 22, 0.1), rgba(239, 68, 68, 0.1));
}
.gr-button[variant="primary"] {
background: linear-gradient(45deg, #f97316, #ef4444) !important;
border: none !important;
color: white !important;
font-weight: bold !important;
}
.gr-button[variant="primary"]:hover {
background: linear-gradient(45deg, #ea580c, #dc2626) !important;
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(239, 68, 68, 0.3);
}
.gr-button[variant="secondary"] {
background: linear-gradient(45deg, rgba(249, 115, 22, 0.1), rgba(239, 68, 68, 0.1)) !important;
border: 2px solid #f97316 !important;
color: #f97316 !important;
font-weight: bold !important;
}
.gr-button[variant="secondary"]:hover {
background: linear-gradient(45deg, #f97316, #ef4444) !important;
color: white !important;
}
h1 {
background: linear-gradient(45deg, #f97316, #ef4444);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: bold;
}
.gr-textbox {
border: 2px solid rgba(249, 115, 22, 0.3) !important;
}
.gr-textbox:focus {
border-color: #ef4444 !important;
box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.1) !important;
}
""") as demo:
gr.Markdown("# 🎬 DubIndic - AI Audio Dubbing Pipeline")
gr.Markdown("Transform your audio into another Indian language with full editing control.")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### πŸ“€ Step 1: Upload & Configure")
audio_input = gr.Audio(sources=["upload"], type="filepath", label="🎡 Upload Audio File")
lang_dropdown = gr.Dropdown(
choices=["Assamese", "Bengali", "Gujarati", "Hindi", "Kannada", "Malayalam", "Marathi", "Odia", "Punjabi", "Tamil", "Telugu"],
label="🌐 Target Language"
)
process_btn = gr.Button("🎯 Start Processing", variant="primary")
step1_output = gr.Textbox(label="πŸ“Š Processing Status", interactive=False)
with gr.Column(visible=False) as edit_section:
gr.Markdown("### ✏️ Step 2: Edit, Generate & Finalize Chunks")
with gr.Row():
prev_btn = gr.Button("◀️ Previous")
next_btn = gr.Button("Next ▢️")
with gr.Row():
with gr.Column():
original_audio = gr.Audio(label="🎧 Original Chunk Audio", type="filepath", interactive=False)
download_original_audio = gr.File(label="πŸ’Ύ Download Original Chunk", visible=False)
with gr.Column():
dubbed_audio = gr.Audio(label="πŸ”Š Dubbed Chunk Audio", type="filepath", interactive=False)
download_dubbed_audio = gr.File(label="πŸ’Ύ Download Dubbed Chunk", visible=False)
transcription_text = gr.Textbox(label="Transcription (edit if needed)", lines=2, interactive=True)
translation_text = gr.Textbox(label="Translation (edit if needed)", lines=2, interactive=True)
with gr.Row():
generate_btn = gr.Button("πŸ”Š Generate Dubbed Chunk")
finalize_btn = gr.Button("βœ”οΈ Finalize Chunk", variant="secondary")
progress_text = gr.Textbox(label="Progress", interactive=False)
with gr.Row(visible=False) as merge_section:
gr.Markdown("### 🏁 Step 3: Merge Final Audio")
merge_btn = gr.Button("πŸš€ Merge All Finalized Chunks", variant="primary")
final_output = gr.Textbox(label="πŸŽ‰ Final Results", interactive=False)
output_audio = gr.Audio(label="πŸ”Š Final Dubbed Audio", type="filepath", interactive=False)
# Connect functions to UI components
process_btn.click(
fn=start_processing,
inputs=[audio_input, lang_dropdown],
outputs=[step1_output, original_audio, transcription_text, translation_text, dubbed_audio, progress_text,
edit_section, merge_section, download_original_audio, download_original_audio,
download_dubbed_audio, download_dubbed_audio]
)
prev_btn.click(
fn=lambda t, tr: navigate_chunk(t, tr, "prev"),
inputs=[transcription_text, translation_text],
outputs=[original_audio, transcription_text, translation_text, dubbed_audio, progress_text,
download_original_audio, download_dubbed_audio]
)
next_btn.click(
fn=lambda t, tr: navigate_chunk(t, tr, "next"),
inputs=[transcription_text, translation_text],
outputs=[original_audio, transcription_text, translation_text, dubbed_audio, progress_text,
download_original_audio, download_dubbed_audio]
)
generate_btn.click(
fn=generate_dubbed_chunk,
inputs=[transcription_text, translation_text],
outputs=[dubbed_audio, download_dubbed_audio]
)
finalize_btn.click(
fn=finalize_current_chunk,
inputs=[],
outputs=[progress_text]
)
merge_btn.click(
fn=merge_all_chunks,
inputs=[],
outputs=[final_output, output_audio]
)
return demo
if __name__ == "__main__":
DubIndic_interface = create_DubIndic_interface()
if DubIndic_interface:
DubIndic_interface.launch(show_error=True, share=False, server_name="0.0.0.0", server_port=7860)
else:
logger.error("Failed to create the Gradio interface.")