import gradio as gr import os import tempfile import yt_dlp import subprocess import requests from huggingface_hub import InferenceClient # --------------------------- # Model setup # --------------------------- WHISPER_MODEL = "openai/whisper-large-v3" EN_SUMMARY_MODEL = "facebook/bart-large-cnn" UR_SUMMARY_MODEL = "openai/gpt-oss-120b" client = InferenceClient() # --------------------------- # Helper Functions # --------------------------- def download_youtube_audio(url: str): """Download YouTube audio as mp3""" try: tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") ydl_opts = { "format": "bestaudio/best", "outtmpl": tmp.name, "quiet": True, "postprocessors": [{"key": "FFmpegExtractAudio", "preferredcodec": "mp3"}], } with yt_dlp.YoutubeDL(ydl_opts) as ydl: ydl.download([url]) return tmp.name except Exception as e: raise RuntimeError(f"❌ Error downloading YouTube audio: {e}") def convert_to_wav(audio_path: str): """Convert any audio to 16kHz mono WAV""" wav_path = tempfile.mktemp(suffix=".wav") try: subprocess.run( ["ffmpeg", "-y", "-i", audio_path, "-ar", "16000", "-ac", "1", wav_path], check=True, capture_output=True, ) return wav_path except subprocess.CalledProcessError as e: raise RuntimeError(f"❌ ffmpeg conversion failed: {e}") # --------------------------- # Transcription # --------------------------- def transcribe_audio(audio_file=None, youtube_url=None): try: if youtube_url and youtube_url.strip(): audio_path = download_youtube_audio(youtube_url) elif audio_file: audio_path = audio_file else: return "❌ Please record, upload, or provide a YouTube link." wav_path = convert_to_wav(audio_path) headers = { "Authorization": f"Bearer {os.environ.get('HUGGINGFACE_API_TOKEN','')}", "Content-Type": "audio/wav" } api_url = f"https://api-inference.huggingface.co/models/{WHISPER_MODEL}" with open(wav_path, "rb") as f: response = requests.post(api_url, headers=headers, data=f.read()) if response.status_code != 200: raise RuntimeError(f"HF API error: {response.text}") data = response.json() if isinstance(data, dict) and "text" in data: return data["text"] elif isinstance(data, list) and "text" in data[0]: return data[0]["text"] else: return str(data) except Exception as e: return f"❌ Error during transcription: {e}" # --------------------------- # Summarization # --------------------------- def summarize_text(text, language): try: if language == "English": result = client.summarization(model=EN_SUMMARY_MODEL, inputs=text, max_new_tokens=1024) return result["summary_text"] else: resp = client.text_generation( model=UR_SUMMARY_MODEL, prompt=f"مندرجہ ذیل انگریزی متن کا جامع اردو خلاصہ لکھیں:\n\n{text}", max_new_tokens=2048, ) return resp except Exception as e: return f"❌ Summarization failed: {e}" # --------------------------- # Tutorial Generator # --------------------------- def generate_tutorial(transcription, summary, language): try: prompt = ( f"Create a comprehensive, beginner-friendly tutorial in {language} " f"based on the following transcript and summary.\n\n" f"Transcript:\n{transcription}\n\nSummary:\n{summary}" ) model = UR_SUMMARY_MODEL if language == "Urdu" else EN_SUMMARY_MODEL result = client.text_generation(model=model, prompt=prompt, max_new_tokens=2200) return result except Exception as e: return f"❌ Error generating tutorial: {e}" # --------------------------- # Gradio UI # --------------------------- with gr.Blocks(title="🎙️ Smart Transcriber & Tutorial Maker") as demo: gr.Markdown("## 🎧 Smart Transcriber, Summarizer & Tutorial Creator") with gr.Row(): audio_input = gr.Audio(sources=["microphone", "upload"], type="filepath", label="🎙️ Record or Upload Audio") yt_input = gr.Textbox(label="🎥 Or paste YouTube link") trans_btn = gr.Button("🚀 Transcribe") transcript_output = gr.Textbox(label="📝 Transcription", lines=8) with gr.Row(): lang_choice = gr.Radio(["English", "Urdu"], label="Select Summary Language", value="English") sum_btn = gr.Button("🧠 Generate Detailed Summary") summary_output = gr.Textbox(label="📋 Summary", lines=10) tut_btn = gr.Button("📘 Create Beginner Tutorial") tutorial_output = gr.Textbox(label="🎓 Tutorial", lines=12) # Button actions trans_btn.click(transcribe_audio, [audio_input, yt_input], transcript_output) sum_btn.click(summarize_text, [transcript_output, lang_choice], summary_output) tut_btn.click(generate_tutorial, [transcript_output, summary_output, lang_choice], tutorial_output) demo.launch()