Oneto8-test / app.py
Tamiloneto8's picture
Update app.py
fce5193 verified
raw
history blame
17.3 kB
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.Markdown(f"**Error Details:** {str(e)}")
gr.Markdown("Please check your connection and try again.")
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 select a target language.",
None, "", "", None, "",
gr.update(visible=False), 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 (
f"βœ… {result[0]}", result[2], result[3], result[4], result[5], result[6],
gr.update(visible=True), gr.update(visible=True)
)
except Exception as e:
logger.error("Error in start_processing: %s", e, exc_info=True)
return (
f"❌ Error: {str(e)}",
None, "", "", None, "",
gr.update(visible=False), gr.update(visible=False)
)
def navigate_chunk(transcription, translation, direction):
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)
return result[1], result[2], result[3], result[4], result[5]
except Exception as e:
logger.error("Error navigating chunks: %s", e, exc_info=True)
return None, f"❌ Navigation error: {str(e)}", "", None, ""
def generate_dubbed_chunk(transcription, translation):
if not transcription and not translation:
return 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
except Exception as e:
logger.error("Error generating dubbed chunk: %s", e, exc_info=True)
return 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 f"βœ… {progress}"
except Exception as e:
logger.error("Error finalizing chunk: %s", e, exc_info=True)
return f"❌ Error finalizing: {str(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 f"πŸŽ‰ {final_status}", final_audio
except Exception as e:
logger.error("Error merging audio files: %s", e, exc_info=True)
return f"❌ Merge error: {str(e)}", None
# Create custom theme with enhanced styling
custom_theme = gr_themes.Soft(
primary_hue="orange",
secondary_hue="red",
neutral_hue="slate"
)
# Enhanced CSS with creative design elements
enhanced_css = """
/* Main container styling */
.gradio-container {
background: linear-gradient(135deg, #fff8e6 0%, #fef3e2 50%, #fff8e6 100%);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
min-height: 100vh;
}
/* Header styling with animated gradient */
.main-header {
background: linear-gradient(45deg, #f97316, #ef4444, #f97316);
background-size: 300% 300%;
animation: gradientShift 6s ease infinite;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
font-weight: 800;
font-size: 2.5rem;
margin-bottom: 1rem;
}
@keyframes gradientShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
/* Card-like sections */
.step-card {
background: rgba(255, 255, 255, 0.9);
border: 2px solid rgba(249, 115, 22, 0.2);
border-radius: 16px;
padding: 24px;
margin: 16px 0;
box-shadow: 0 8px 32px rgba(249, 115, 22, 0.1);
backdrop-filter: blur(8px);
transition: all 0.3s ease;
}
.step-card:hover {
transform: translateY(-2px);
box-shadow: 0 12px 48px rgba(249, 115, 22, 0.15);
border-color: rgba(249, 115, 22, 0.4);
}
/* Enhanced primary buttons */
.gr-button[variant="primary"] {
background: linear-gradient(45deg, #f97316, #ef4444) !important;
border: none !important;
color: white !important;
font-weight: 600 !important;
padding: 12px 24px !important;
border-radius: 12px !important;
font-size: 1rem !important;
transition: all 0.3s ease !important;
box-shadow: 0 4px 16px rgba(249, 115, 22, 0.3) !important;
}
.gr-button[variant="primary"]:hover {
background: linear-gradient(45deg, #ea580c, #dc2626) !important;
transform: translateY(-2px) !important;
box-shadow: 0 8px 24px rgba(239, 68, 68, 0.4) !important;
}
/* Enhanced secondary buttons */
.gr-button[variant="secondary"] {
background: rgba(255, 248, 230, 0.9) !important;
border: 2px solid #f97316 !important;
color: #f97316 !important;
font-weight: 600 !important;
padding: 10px 20px !important;
border-radius: 10px !important;
transition: all 0.3s ease !important;
}
.gr-button[variant="secondary"]:hover {
background: linear-gradient(45deg, #f97316, #ef4444) !important;
color: white !important;
transform: translateY(-1px) !important;
box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3) !important;
}
/* Navigation buttons */
.nav-button {
background: linear-gradient(45deg, #f97316, #ef4444) !important;
border: none !important;
color: white !important;
font-weight: 600 !important;
padding: 8px 16px !important;
border-radius: 8px !important;
font-size: 0.9rem !important;
min-width: 120px !important;
}
/* Input styling */
.gr-textbox, .gr-dropdown {
border: 2px solid rgba(249, 115, 22, 0.3) !important;
border-radius: 12px !important;
background: rgba(255, 255, 255, 0.95) !important;
transition: all 0.3s ease !important;
font-size: 1rem !important;
}
.gr-textbox:focus, .gr-dropdown:focus {
border-color: #ef4444 !important;
box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.1) !important;
outline: none !important;
}
/* Audio player styling */
.gr-audio {
border: 2px solid rgba(249, 115, 22, 0.3) !important;
border-radius: 12px !important;
background: rgba(255, 255, 255, 0.95) !important;
padding: 12px !important;
}
/* Progress indicators */
.progress-text {
background: linear-gradient(45deg, #f97316, #ef4444);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 600;
}
/* Step numbers */
.step-number {
background: linear-gradient(45deg, #f97316, #ef4444);
color: white;
border-radius: 50%;
width: 32px;
height: 32px;
display: inline-flex;
align-items: center;
justify-content: center;
font-weight: bold;
margin-right: 8px;
}
/* Section headers */
.section-header {
color: #f97316;
font-weight: 700;
font-size: 1.25rem;
margin-bottom: 16px;
display: flex;
align-items: center;
}
/* Responsive design */
@media (max-width: 768px) {
.main-header {
font-size: 2rem;
}
.step-card {
padding: 16px;
}
}
/* Loading animation */
.loading {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.7; }
100% { opacity: 1; }
}
"""
# Define the enhanced Gradio interface
with gr.Blocks(theme=custom_theme, title="DubIndic - AI Audio Dubbing", css=enhanced_css) as demo:
# Main header
gr.HTML('<div class="main-header">🎬 DubIndic - AI Audio Dubbing Pipeline</div>')
gr.HTML('<div style="text-align: center; margin-bottom: 2rem; font-size: 1.1rem; color: #666;">Transform your audio into another Indian language with full editing control</div>')
# Step 1: Upload & Configure
with gr.Row():
with gr.Column(scale=2):
gr.HTML('<div class="step-card">')
gr.HTML('<div class="section-header"><span class="step-number">1</span>πŸ“€ Upload & Configure</div>')
with gr.Row():
with gr.Column(scale=1):
audio_input = gr.Audio(
sources=["upload"],
type="filepath",
label="🎡 Upload Audio File",
elem_classes=["upload-audio"]
)
with gr.Column(scale=1):
lang_dropdown = gr.Dropdown(
choices=["Assamese", "Bengali", "Gujarati", "Hindi", "Kannada", "Malayalam", "Marathi", "Odia", "Punjabi", "Tamil", "Telugu"],
label="🌐 Target Language",
value=None,
elem_classes=["language-select"]
)
process_btn = gr.Button(
"🎯 Start Processing",
variant="primary",
size="lg",
elem_classes=["process-button"]
)
step1_output = gr.Textbox(
label="πŸ“Š Processing Status",
interactive=False,
elem_classes=["status-output"]
)
gr.HTML('</div>')
# Step 2: Edit & Generate (Initially Hidden)
with gr.Column(visible=False, elem_classes=["step-card"]) as edit_section:
gr.HTML('<div class="section-header"><span class="step-number">2</span>✏️ Edit, Generate & Finalize Chunks</div>')
# Navigation controls
with gr.Row():
with gr.Column(scale=1):
prev_btn = gr.Button("◀️ Previous", elem_classes=["nav-button"])
with gr.Column(scale=1):
next_btn = gr.Button("Next ▢️", elem_classes=["nav-button"])
# Audio and text editing
with gr.Row():
with gr.Column(scale=1):
original_audio = gr.Audio(
label="🎡 Original Chunk Audio",
type="filepath",
interactive=False
)
with gr.Column(scale=1):
transcription_text = gr.Textbox(
label="πŸ“ Transcription (edit if needed)",
lines=3,
interactive=True,
placeholder="Original transcription will appear here..."
)
translation_text = gr.Textbox(
label="πŸ”„ Translation (edit if needed)",
lines=3,
interactive=True,
placeholder="Translation will appear here..."
)
# Generate and finalize controls
with gr.Row():
with gr.Column(scale=1):
generate_btn = gr.Button("πŸ”Š Generate Dubbed Chunk", variant="secondary")
with gr.Column(scale=1):
finalize_btn = gr.Button("βœ”οΈ Finalize Chunk", variant="secondary")
dubbed_audio = gr.Audio(
label="🎀 Dubbed Chunk Audio",
type="filepath",
interactive=False
)
progress_text = gr.Textbox(
label="πŸ“ˆ Progress",
interactive=False,
elem_classes=["progress-text"]
)
# Step 3: Final Merge (Initially Hidden)
with gr.Column(visible=False, elem_classes=["step-card"]) as merge_section:
gr.HTML('<div class="section-header"><span class="step-number">3</span>🏁 Merge Final Audio</div>')
merge_btn = gr.Button(
"πŸš€ Merge All Finalized Chunks",
variant="primary",
size="lg"
)
with gr.Row():
with gr.Column(scale=1):
final_output = gr.Textbox(
label="πŸŽ‰ Final Results",
interactive=False,
elem_classes=["final-status"]
)
with gr.Column(scale=1):
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]
)
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]
)
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]
)
generate_btn.click(
fn=generate_dubbed_chunk,
inputs=[transcription_text, translation_text],
outputs=[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,
favicon_path=None,
show_tips=True
)
else:
logger.error("Failed to create the Gradio interface.")