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("""

🎤 تبدیل گفتار به متن

در این ابزار در حال برجسته‌سازی گفتارها را به فارسی یا انگلیسی تبدیل کنید.

""") 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 )