Spaces:
Running
Running
File size: 4,562 Bytes
9e41260 889e1fa d011be0 889e1fa 7bc6887 889e1fa 7bc6887 889e1fa 595c4b7 7bc6887 889e1fa 595c4b7 3ae4583 12ef859 595c4b7 26ce970 3ae4583 595c4b7 889e1fa 595c4b7 3ae4583 595c4b7 3ae4583 889e1fa 7bc6887 889e1fa 12ef859 889e1fa 12ef859 d011be0 12ef859 d011be0 7bf74d5 12ef859 889e1fa 7bc6887 889e1fa 7bc6887 889e1fa d011be0 fef1314 d011be0 fef1314 d011be0 fef1314 889e1fa 7bc6887 889e1fa |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
import gradio as gr
import edge_tts
import asyncio
import tempfile
import os
from moviepy.editor import AudioFileClip
# Get all available voices
async def get_voices():
voices = await edge_tts.list_voices()
return {f"{v['ShortName']} - {v['Locale']} ({v['Gender']})": v['ShortName'] for v in voices}
# Text to speech functionality
async def text_to_speech(text, voice, rate, pitch):
if not text.strip():
return None, gr.Warning("Please enter the text to convert.")
if not voice:
return None, gr.Warning("Please select a voice.")
voice_short_name = voice.split(" - ")[0]
rate_str = f"{rate:+d}%"
pitch_str = f"{pitch:+d}Hz"
communicate = edge_tts.Communicate(text, voice_short_name, rate=rate_str, pitch=pitch_str)
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
tmp_path = tmp_file.name
await communicate.save(tmp_path)
return tmp_path, None
# Generate SRT file with 1 line of subtitles containing 10-14 words
def generate_srt(words, audio_duration, srt_path):
with open(srt_path, 'w', encoding='utf-8') as srt_file:
segment_duration = audio_duration / (len(words) // 14) # Average duration for each 14 words
current_time = 0
for i in range(0, len(words), 14): # Every 14 words for one line
line = ' '.join(words[i:i + 14]) # Up to 14 words
start_time = current_time
end_time = start_time + segment_duration # Adjust duration for one line
start_time_str = format_srt_time(start_time)
end_time_str = format_srt_time(end_time)
srt_file.write(f"{i // 14 + 1}\n{start_time_str} --> {end_time_str}\n{line}\n\n")
current_time += segment_duration # Update current time for the next segment
return srt_path
def format_srt_time(seconds):
millis = int((seconds - int(seconds)) * 1000)
seconds = int(seconds)
minutes = seconds // 60
hours = minutes // 60
minutes %= 60
seconds %= 60
return f"{hours:02}:{minutes:02}:{seconds:02},{millis:03}"
# Text to audio and SRT functionality
async def text_to_audio_and_srt(text, voice, rate, pitch):
audio_path, warning = await text_to_speech(text, voice, rate, pitch)
if warning:
return None, None, warning
audio_clip = AudioFileClip(audio_path)
audio_duration = audio_clip.duration
# Generate SRT file based on the entire text
base_name = os.path.splitext(audio_path)[0]
srt_path = f"{base_name}_subtitle.srt"
words = text.split()
generate_srt(words, audio_duration, srt_path)
return audio_path, srt_path, None
# Gradio interface function
def tts_interface(text, voice, rate, pitch):
audio_path, srt_path, warning = asyncio.run(text_to_audio_and_srt(text, voice, rate, pitch))
return audio_path, srt_path, warning
# Create Gradio app
async def create_demo():
voices = await get_voices()
with gr.Blocks() as demo:
gr.Markdown(
"""
<h1 style="text-align: center; color: #333;">Text to Speech with Subtitles</h1>
<p style="text-align: center; color: #555;">Convert your text to natural-sounding speech and generate subtitles (SRT) for your audio.</p>
""",
elem_id="header"
)
with gr.Row():
with gr.Column():
text_input = gr.Textbox(label="Input Text", lines=5, placeholder="Enter text here...")
voice_dropdown = gr.Dropdown(choices=[""] + list(voices.keys()), label="Select Voice", value="")
rate_slider = gr.Slider(minimum=-50, maximum=50, value=0, label="Rate Adjustment (%)", step=1)
pitch_slider = gr.Slider(minimum=-20, maximum=20, value=0, label="Pitch Adjustment (Hz)", step=1)
generate_button = gr.Button("Generate Audio and Subtitles", variant="primary")
with gr.Column():
output_audio = gr.Audio(label="Generated Audio", type="filepath")
output_srt = gr.File(label="Generated SRT", file_count="single")
warning_msg = gr.Markdown(label="Warning", visible=False)
generate_button.click(
fn=tts_interface,
inputs=[text_input, voice_dropdown, rate_slider, pitch_slider],
outputs=[output_audio, output_srt, warning_msg]
)
return demo
# Run the app
if __name__ == "__main__":
demo = asyncio.run(create_demo())
demo.launch()
|