speh33 / app.py
suprimedev's picture
Update app.py
b4b418f verified
import gradio as gr
import speech_recognition as sr
from pydub import AudioSegment
import numpy as np
import io
import wave
import os
import threading
import queue
from functools import lru_cache
# تنظیمات اولیه
recognizer = sr.Recognizer()
recognizer.energy_threshold = 300
recognizer.dynamic_energy_threshold = True
# صف‌های پردازش real-time
audio_queue = queue.Queue()
transcript_queue = queue.Queue()
# متغیرهای حفظ متن
current_transcript = ""
transcript_lock = threading.Lock()
# تابع تبدیل numpy به فرمت WAV
def numpy_to_wav(audio_data, sample_rate=16000):
"""تعداد به فرمت WAV با نرمال‌سازی"""
buffer = io.BytesIO()
with wave.open(buffer, 'wb') as wav_file:
wav_file.setnchannels(1)
wav_file.setsampwidth(2)
wav_file.setframerate(sample_rate)
wav_file.writeframes(np.int16(audio_data * 32767))
buffer.seek(0)
return AudioSegment.from_wav(buffer)
# پردازش یک قطعه صوتی
@lru_cache(maxsize=128)
def process_audio_chunk(chunk_data):
"""پردازش یک قطعه صوتی با Google Speech Recognition"""
try:
# تبدیل به وفرمت WAV
audio_segment = numpy_to_wav(chunk_data)
with sr.AudioFile(io.BytesIO(audio_segment.raw_data)) as source:
audio = recognizer.record(source)
# تلاش با اولویت فارسی
try:
text = recognizer.recognize_google(audio, language='fa-IR')
except sr.UnknownValueError:
# اگر فارسی معتبر نباشد، با انگلیسی تلاش کنیم
text = recognizer.recognize_google(audio, language='en-US', show_all=False)
except sr.RequestError:
text = "[خطا در اتصال سرویس گوگل]"
except Exception as e:
text = ""
return text.strip()
except Exception as e:
print(f"خطا در پردازش {e}")
return ""
# تابع کمکی به real-time
def update_realtime_transcript():
"""به‌روزرسانی متن real-time"""
while True:
if not transcript_queue.empty():
new_text = transcript_queue.get()
with transcript_lock:
current_transcript += " " + new_text
current_transcript = " ".join(current_transcript.split())
time.sleep(0.1)
# رابط کاربری با Gradio
with gr.Blocks(
title="گستره گفتار به متن",
theme=gr.themes.Soft(),
css="""
.gradio-container { font-family: 'Vazir', 'Tahoma', sans-serif !important; }
.rtl { direction: rtl; text-align: right; }
"""
) as demo:
gr.HTML("""
<div style="text-align: center; max-width: 800px; margin: 0 auto;">
<h1 style="font-size: 2.5em; margin-bottom: 0.5em;">🎤 تبدیل گفتار به متن</h1>
<p style="font-size: 1.1em; color: #666; margin-bottom: 2em;">در این ابزار در حال برجسته‌سازی گفتارها را به فارسی یا انگلیسی تبدیل کنید.</p>
</div>
""")
with gr.Tabs():
# تب ضبط مستقیم
with gr.TabItem("🎙️ ضبط مستقیم"):
gr.Markdown("### میکروفون خود را فعال کرده و شروع به صحبت کنید")
with gr.Row():
with gr.Column(scale=1):
audio_input = gr.Audio(
sources=["microphone"],
type="numpy",
streaming=True,
label="میکروفون",
show_label=True,
elem_classes="rtl"
)
with gr.Column(scale=1):
clear_btn = gr.Button("🗑️ پاک کردن متن", variant="secondary", size="sm")
realtime_output = gr.Textbox(
label="متن تشخیص داده شده",
placeholder="شروع به صحبت کنید و متن اینجا ظاهر می‌شود...",
lines=12,
elem_classes="rtl",
rtl=True,
show_copy_button=True
)
# sentait‌ها
audio_input.stream(
lambda x: process_audio_chunk(x),
inputs=[audio_input],
outputs=[]
)
audio_input.stream(
lambda: update_realtime_transcript(),
inputs=[],
outputs=[realtime_output],
every=0.5
)
clear_btn.click(
lambda: "",
outputs=[realtime_output]
)
# تب فایل صوتی
with gr.TabItem("📁 فایل صوتی"):
gr.Markdown("### فایل صوتی خود را انتخاب کنید")
with gr.Row():
with gr.Column(scale=3):
file_input = gr.Audio(
sources=["upload"],
type="filepath",
label="انتخاب فایل صوتی",
elem_classes="rtl"
)
with gr.Column(scale=1):
chunk_duration = gr.Slider(
minimum=10,
maximum=60,
value=30,
step=5,
label="مدت هر بخش (ثانیه)",
elem_classes="rtl"
)
with gr.Row():
process_btn = gr.Button("🚀 شروع تبدیل", variant="primary", size="lg")
progress_label = gr.Textbox(
label="وضعیت پردازش",
interactive=False,
elem_classes="rtl"
)
file_output = gr.Textbox(
label="متن تشخیص داده شده",
placeholder="متن پس از پردازش اینجا نمایش داده می‌شود...",
lines=12,
elem_classes="rtl",
rtl=True,
show_copy_button=True
)
def safe_transcribe_file(file, duration):
"""پردازش فایل صوتی با مدیریت خطا"""
if file is None:
return "لطفاً یک فایل صوتی آپلود کنید", "شروع پردازش"
try:
audio = AudioSegment.from_file(file)
results = []
total_chunks = len(audio) // (duration * 1000)
for i in range(0, len(audio), duration*1000):
chunk = audio[i:i+duration*1000]
text = process_audio_chunk(np.array(chunk.get_array_of_samples()))
if text:
results.append(text)
progress = min(((i + duration*1000) / len(audio)) * 100, 100)
yield " ".join(results), f"پیشرفت: {progress:.1f}%"
return " ".join(results), "تکمیل پردازش ✅"
except Exception as e:
return f"خطا: {str(e)}", "خطا در پردازش ❌"
process_btn.click(
safe_transcribe_file,
inputs=[file_input, chunk_duration],
outputs=[file_output, progress_label]
)
# بخش راهنما
with gr.Accordion("📖 راهنمای استفاده", open=False, elem_classes="rtl"):
gr.Markdown("""
### نحوه استفاده:
**برای ضبط مستقیم:**
1. به تب "ضبط مستقیم" بروید
2. اجازه دسترسی به میکروفون را بدهید
3. شروع به صحبت کنید
4. متن به صورت خودکار نمایش داده می‌شود
**برای فایل صوتی:**
1. به تب "فایل صوتی" بروید
2. فایل مورد نظر را انتخاب کنید
3. مدت زمان تقسیم‌بندی را تنظیم کنید (پیش‌فرض: ۳۰ ثانیه)
4. روی "شروع تبدیل" کلیک کنید
5. منتظر بمانید تا پردازش کامل شود
### فرمت‌های پشتیبانی شده:
- MP3, WAV, M4A, FLAC, OGG, MP4, AVI, MOV
### نکات مهم:
- 🎯 برای دقت بیشتر، از فایل‌های با کیفیت بالا استفاده کنید
- 🔇 نویز پس‌زمینه را به حداقل برسانید
- 🗣️ واضح و شمرده صحبت کنید
- 🌐 اتصال اینترنت پایدار داشته باشید
""", elem_classes="rtl")
# ساخت و اجرای برنامه
if __name__ == "__main__":
demo.queue().launch(
share=True,
show_error=True
)