RohitCSharp's picture
Update app.py
261214f verified
raw
history blame
3.39 kB
import gradio as gr
from langchain.prompts import PromptTemplate
from langchain_huggingface import HuggingFacePipeline
from transformers import pipeline
from bs4 import BeautifulSoup
import requests
from TTS.api import TTS
import tempfile
import os
# Setup summarization LLM
summary_pipe = pipeline("text2text-generation", model="google/flan-t5-base", device=-1)
llm = HuggingFacePipeline(pipeline=summary_pipe)
# Prompt for more engaging summary
summary_prompt = PromptTemplate.from_template("""
Summarize the following article content in a clear, warm, and motivational tone like a preacher speaking to an audience:
{text}
Summary:
""")
summary_chain = summary_prompt | llm
# TTS model setup
tts_model = TTS(model_name="tts_models/multilingual/multi-dataset/your_tts", progress_bar=False, gpu=False)
SPEAKER_LIST = tts_model.speakers
DEFAULT_SPEAKER = SPEAKER_LIST[0] if SPEAKER_LIST else None
def extract_main_content(url):
try:
response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.content, "html.parser")
for tag in soup(["nav", "header", "footer", "aside", "script", "style", "noscript"]):
tag.decompose()
paragraphs = soup.find_all("p")
content = "\n".join([p.get_text() for p in paragraphs if len(p.get_text()) > 60])
return content.strip()
except Exception as e:
return f"Error extracting article content: {str(e)}"
def generate_human_like_audio(text, speaker):
try:
# Save in tmp directory accessible by Gradio
base = tempfile.gettempdir()
wav_path = os.path.join(base, "summary.wav")
mp3_path = os.path.join(base, "summary.mp3")
tts_model.tts_to_file(text=text, speaker=speaker, file_path=wav_path)
os.system(f"ffmpeg -y -i {wav_path} -codec:a libmp3lame -qscale:a 4 {mp3_path}")
return wav_path if os.path.exists(wav_path) else None, mp3_path if os.path.exists(mp3_path) else None
except Exception as e:
print(f"TTS ERROR: {e}")
return None, None
def url_to_audio_summary(url, speaker):
article_text = extract_main_content(url)
if article_text.startswith("Error"):
return article_text, None, None
# Truncate
if len(article_text) > 1500:
article_text = article_text[:1500] + "..."
summary = (summary_chain.invoke if hasattr(summary_chain, 'invoke') else summary_chain)({"text": article_text})
summary = summary.get("text") if isinstance(summary, dict) else summary
wav_path, mp3_path = generate_human_like_audio(summary, speaker)
return summary, wav_path, mp3_path
def interface_wrapper(url, speaker):
summary, wav_path, mp3_path = url_to_audio_summary(url, speaker)
return summary, wav_path, mp3_path
iface = gr.Interface(
fn=interface_wrapper,
inputs=[
gr.Textbox(label="Article URL", placeholder="Paste a news/blog URL here..."),
gr.Dropdown(choices=SPEAKER_LIST, value=DEFAULT_SPEAKER, label="Select Speaker")
],
outputs=[
gr.Textbox(label="Summary"),
gr.Audio(label="Preacher-style Audio Summary", type="filepath"),
gr.File(label="Download MP3")
],
title="Preaching-Style URL to Audio Agent",
description="Summarizes article content and reads it aloud in a warm, preacher-style voice using YourTTS. CPU-only."
)
if __name__ == "__main__":
iface.launch()