Spaces:
Running
Running
| import gradio as gr | |
| import yt_dlp | |
| import os | |
| import shutil | |
| from faster_whisper import WhisperModel | |
| # --- 1. Model Setup --- | |
| model = None | |
| def load_model(): | |
| global model | |
| if model is None: | |
| print("π₯ Loading Whisper Model...") | |
| model = WhisperModel("base", device="cpu", compute_type="int8") | |
| print("β Model Loaded!") | |
| return model | |
| # --- 2. Helper: Find FFmpeg --- | |
| def get_ffmpeg_dir(): | |
| # System me ffmpeg kahan hai, ye pata lagao | |
| path = shutil.which("ffmpeg") | |
| if path: | |
| return os.path.dirname(path) # Folder ka rasta return karo | |
| return "/usr/bin" # Default fallback | |
| # --- 3. Logic: Download Audio from URL --- | |
| def download_audio_from_url(url): | |
| output_path = "downloaded_audio" | |
| if os.path.exists(f"{output_path}.mp3"): os.remove(f"{output_path}.mp3") | |
| # Dynamic FFmpeg Path (Ye error fix karega) | |
| ffmpeg_dir = get_ffmpeg_dir() | |
| print(f"π§ FFmpeg found at: {ffmpeg_dir}") | |
| ydl_opts = { | |
| 'format': 'bestaudio/best', | |
| 'outtmpl': output_path, | |
| 'ffmpeg_location': ffmpeg_dir, # <--- FIXED | |
| 'postprocessors': [{ | |
| 'key': 'FFmpegExtractAudio', | |
| 'preferredcodec': 'mp3', | |
| 'preferredquality': '192', | |
| }], | |
| 'quiet': True, | |
| 'no_warnings': True, | |
| 'nocheckcertificate': True, | |
| 'http_headers': { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', | |
| 'Referer': 'https://www.tiktok.com/' | |
| } | |
| } | |
| try: | |
| with yt_dlp.YoutubeDL(ydl_opts) as ydl: | |
| ydl.download([url]) | |
| return f"{output_path}.mp3" | |
| except Exception as e: | |
| raise Exception(f"Download Fail: {str(e)}") | |
| # --- 4. Main Transcribe Function (Handles Both) --- | |
| def transcribe_media(url_input, file_input): | |
| audio_file_path = None | |
| try: | |
| # CASE 1: File Upload | |
| if file_input is not None: | |
| print(f"π Processing Uploaded File: {file_input}") | |
| audio_file_path = file_input | |
| # CASE 2: URL Input | |
| elif url_input and url_input.strip() != "": | |
| print(f"π Processing URL: {url_input}") | |
| audio_file_path = download_audio_from_url(url_input) | |
| else: | |
| return "β οΈ Error: Link daalein ya File upload karein." | |
| if not os.path.exists(audio_file_path): | |
| return "β Error: File nahi mili." | |
| # --- Transcribe --- | |
| current_model = load_model() | |
| # Turbo Settings: beam_size=1 (Fast) | |
| segments, _ = current_model.transcribe( | |
| audio_file_path, | |
| beam_size=1, | |
| vad_filter=True | |
| ) | |
| text = " ".join([s.text for s in segments]) | |
| return text.strip() | |
| except Exception as e: | |
| return f"β Error: {str(e)}" | |
| # --- 5. UI --- | |
| css = """ | |
| .container {max-width: 900px; margin: auto;} | |
| .gr-button-primary {background: linear-gradient(90deg, #1CB5E0 0%, #000851 100%); border: none; color: white;} | |
| """ | |
| with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo: | |
| with gr.Column(elem_classes="container"): | |
| gr.Markdown("# π Turbo Transcriber (Link & Upload)") | |
| gr.Markdown("Paste a TikTok link **OR** upload an Audio/Video file.") | |
| with gr.Tabs(): | |
| # TAB 1: Link | |
| with gr.TabItem("π Paste Link"): | |
| url_in = gr.Textbox(label="TikTok / YouTube URL", placeholder="https://...") | |
| btn_url = gr.Button("π Transcribe Link", variant="primary") | |
| # TAB 2: File Upload | |
| with gr.TabItem("π Upload File"): | |
| file_in = gr.Audio(label="Upload File", type="filepath", sources=["upload", "microphone"]) | |
| btn_file = gr.Button("π Transcribe File", variant="primary") | |
| transcript_out = gr.Code(label="Transcript Result", language="markdown", interactive=False, lines=15) | |
| # Actions | |
| btn_url.click(fn=transcribe_media, inputs=[url_in, gr.State(None)], outputs=transcript_out) | |
| btn_file.click(fn=transcribe_media, inputs=[gr.State(None), file_in], outputs=transcript_out) | |
| demo.launch() | |