File size: 3,618 Bytes
d9efe10
 
ff06deb
d9efe10
e9d5607
 
83f07d9
 
556278e
d9efe10
83f07d9
d9efe10
 
 
83f07d9
d9efe10
83f07d9
d9efe10
 
 
 
 
 
ffe9821
d9efe10
556278e
83f07d9
ff06deb
 
83f07d9
e9d5607
 
 
 
 
 
 
 
 
 
 
 
ff06deb
4714e38
556278e
 
 
 
ff06deb
556278e
 
 
 
 
 
 
4714e38
556278e
 
4714e38
ff06deb
d9efe10
e9d5607
 
556278e
f4064e9
e66aff4
 
556278e
e66aff4
 
d9efe10
ff06deb
556278e
d9efe10
556278e
 
ff06deb
 
556278e
 
 
 
d9efe10
 
556278e
ff06deb
 
 
 
d9efe10
 
556278e
 
d9efe10
83f07d9
 
d9efe10
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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:
        temp_dir = tempfile.mkdtemp()
        wav_path = os.path.join(temp_dir, "summary.wav")
        mp3_path = os.path.join(temp_dir, "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}")

        if os.path.exists(mp3_path):
            return wav_path, mp3_path
        else:
            return wav_path, None
    except Exception as e:
        print(f"TTS ERROR: {e}")
        return None, None

def url_to_audio_summary(url, speaker):
    try:
        article_text = extract_main_content(url)
        if article_text.startswith("Error"):
            return article_text, None, None

        if len(article_text) > 1500:
            article_text = article_text[:1500] + "..."

        summary = summary_chain.invoke({"text": article_text})
        summary = summary["text"] if isinstance(summary, dict) and "text" in summary else summary

        wav_path, mp3_path = generate_human_like_audio(summary, speaker)
        return summary, wav_path, mp3_path
    except Exception as e:
        return f"Error: {str(e)}", None, None

def interface_wrapper(url, speaker):
    summary, wav_path, mp3_path = url_to_audio_summary(url, speaker)
    download_html = ""
    if mp3_path and os.path.exists(mp3_path):
        download_html = f'<a href="file/{os.path.basename(mp3_path)}" download target="_blank">Click to download MP3</a>'
    return summary, wav_path, download_html

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.HTML(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()