Link-to-video / app.py
RohitCSharp's picture
Update app.py
6ac3507 verified
raw
history blame
2.99 kB
import gradio as gr
import tempfile, requests
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
from gtts import gTTS
from bs4 import BeautifulSoup
from PIL import Image, ImageDraw
import ffmpeg
import textwrap
# Initialize OpenAI LLM
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.3)
summary_prompt = PromptTemplate.from_template("""
Provide a crisp, promotional-style summary (under 50 words) of the following:
{text}
Summary:
""")
summary_chain = LLMChain(llm=llm, prompt=summary_prompt)
# Extract top article paragraphs
def extract_main_content(url):
resp = requests.get(url, timeout=10)
soup = BeautifulSoup(resp.content, "html.parser")
for tag in soup(["nav","header","footer","aside","script","style","noscript"]): tag.decompose()
paras = [p.get_text() for p in soup.find_all("p") if len(p.get_text()) > 60]
return "\n".join(paras[:20]) or None
# Gradient background
def create_background(path, size=(1280,720)):
img = Image.new("RGB", size)
draw = ImageDraw.Draw(img)
for y in range(size[1]):
draw.line([(0,y),(size[0],y)], fill=(10+y//10,20+y//12,50+y//15))
img.save(path)
# Generate AV summary
def url_to_av_summary(url, duration):
content = extract_main_content(url)
if not content:
return "Failed to extract content.", None
summary = summary_chain.run(text=content[:3000]).replace('"','')[:300]
# Wrap long summary to multiline
wrapped_summary = textwrap.fill(summary, width=50).replace("\n", "\\n")
# TTS
audio = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3").name
gTTS(text=summary).save(audio)
# Background image
bg = tempfile.NamedTemporaryFile(delete=False, suffix=".png").name
create_background(bg)
# Build video stream
video_stream = ffmpeg.input(bg, loop=1, framerate=1)
text_opts = dict(
fontfile="/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
text=wrapped_summary,
fontcolor="white",
fontsize=48,
box=1,
boxcolor="[email protected]",
boxborderw=5,
x="(w-text_w)/2",
y=f"h-(t*(h+text_h)/{duration})"
)
video = video_stream.drawtext(**text_opts).setpts('PTS')
audio_stream = ffmpeg.input(audio)
out_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
out = ffmpeg.output(video, audio_stream, out_path,
vcodec="libx264", acodec="aac", pix_fmt="yuv420p", t=duration)
out.run(quiet=True)
return summary, out_path
iface = gr.Interface(
fn=url_to_av_summary,
inputs=[gr.Textbox(label="Article URL"), gr.Radio([5,10], label="Duration (sec)", value=5)],
outputs=[gr.Textbox(label="Summary"), gr.Video(label="AV Summary")],
title="AV Summary Generator",
description="Generate a promo-style AV summary (5 or 10s) using OpenAI + gTTS + ffmpeg-python."
)
if __name__=='__main__':
iface.launch()