RohitCSharp commited on
Commit
6ac3507
·
verified ·
1 Parent(s): 490dc5d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -40
app.py CHANGED
@@ -1,14 +1,16 @@
1
  import gradio as gr
2
- import tempfile, subprocess, requests
3
  from langchain.chains import LLMChain
4
  from langchain.prompts import PromptTemplate
5
- from langchain.chat_models import ChatOpenAI
6
  from gtts import gTTS
7
  from bs4 import BeautifulSoup
8
  from PIL import Image, ImageDraw
 
 
9
 
10
- # OpenAI LLM (fast + accurate)
11
- llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.3)
12
  summary_prompt = PromptTemplate.from_template("""
13
  Provide a crisp, promotional-style summary (under 50 words) of the following:
14
 
@@ -18,64 +20,70 @@ Summary:
18
  """)
19
  summary_chain = LLMChain(llm=llm, prompt=summary_prompt)
20
 
21
- # Extract relevant content from article
22
  def extract_main_content(url):
23
  resp = requests.get(url, timeout=10)
24
  soup = BeautifulSoup(resp.content, "html.parser")
25
- for tag in soup(["nav", "header", "footer", "aside", "script", "style", "noscript"]): tag.decompose()
26
  paras = [p.get_text() for p in soup.find_all("p") if len(p.get_text()) > 60]
27
  return "\n".join(paras[:20]) or None
28
 
29
  # Gradient background
30
- def create_background(image_path, size=(1280,720)):
31
  img = Image.new("RGB", size)
32
  draw = ImageDraw.Draw(img)
33
  for y in range(size[1]):
34
- color = (10 + y//10, 20 + y//12, 50 + y//15)
35
- draw.line([(0, y), (size[0], y)], fill=color)
36
- img.save(image_path)
37
 
38
- # AV generation logic with variable duration
39
  def url_to_av_summary(url, duration):
40
  content = extract_main_content(url)
41
  if not content:
42
- return "Failed to extract article content.", None
43
  summary = summary_chain.run(text=content[:3000]).replace('"','')[:300]
44
 
45
- audio_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3").name
46
- gTTS(text=summary).save(audio_path)
47
 
48
- bg_path = tempfile.NamedTemporaryFile(delete=False, suffix=".png").name
49
- create_background(bg_path)
 
50
 
51
- video_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
52
- cmd = [
53
- 'ffmpeg', '-y',
54
- '-loop', '1', '-i', bg_path, '-i', audio_path,
55
- '-vf', (
56
- "drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf:text='" + summary +
57
- f"':fontcolor=white:fontsize=48:box=1:[email protected]:boxborderw=5:x=(w-text_w)/2:y=h-(t*(h+text_h)/{duration})"
58
- ),
59
- '-t', str(duration),
60
- '-c:v', 'libx264', '-c:a', 'aac', '-pix_fmt', 'yuv420p', '-shortest', video_path
61
- ]
62
- subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
63
 
64
- return summary, video_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  iface = gr.Interface(
67
  fn=url_to_av_summary,
68
- inputs=[
69
- gr.Textbox(label="Article URL"),
70
- gr.Radio([5, 10], label="Video Duration (sec)", value=5)
71
- ],
72
- outputs=[
73
- gr.Textbox(label="Summary"),
74
- gr.Video(label="Generated AV Summary")
75
- ],
76
- title="🎞️ AV Summary Generator (OpenAI Powered)",
77
- description="Generate a short AV video (5 or 10 seconds) summarizing any article. Uses OpenAI + gTTS + FFmpeg."
78
  )
79
 
80
- if __name__ == '__main__':
81
  iface.launch()
 
1
  import gradio as gr
2
+ import tempfile, requests
3
  from langchain.chains import LLMChain
4
  from langchain.prompts import PromptTemplate
5
+ from langchain_openai import ChatOpenAI
6
  from gtts import gTTS
7
  from bs4 import BeautifulSoup
8
  from PIL import Image, ImageDraw
9
+ import ffmpeg
10
+ import textwrap
11
 
12
+ # Initialize OpenAI LLM
13
+ llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.3)
14
  summary_prompt = PromptTemplate.from_template("""
15
  Provide a crisp, promotional-style summary (under 50 words) of the following:
16
 
 
20
  """)
21
  summary_chain = LLMChain(llm=llm, prompt=summary_prompt)
22
 
23
+ # Extract top article paragraphs
24
  def extract_main_content(url):
25
  resp = requests.get(url, timeout=10)
26
  soup = BeautifulSoup(resp.content, "html.parser")
27
+ for tag in soup(["nav","header","footer","aside","script","style","noscript"]): tag.decompose()
28
  paras = [p.get_text() for p in soup.find_all("p") if len(p.get_text()) > 60]
29
  return "\n".join(paras[:20]) or None
30
 
31
  # Gradient background
32
+ def create_background(path, size=(1280,720)):
33
  img = Image.new("RGB", size)
34
  draw = ImageDraw.Draw(img)
35
  for y in range(size[1]):
36
+ draw.line([(0,y),(size[0],y)], fill=(10+y//10,20+y//12,50+y//15))
37
+ img.save(path)
 
38
 
39
+ # Generate AV summary
40
  def url_to_av_summary(url, duration):
41
  content = extract_main_content(url)
42
  if not content:
43
+ return "Failed to extract content.", None
44
  summary = summary_chain.run(text=content[:3000]).replace('"','')[:300]
45
 
46
+ # Wrap long summary to multiline
47
+ wrapped_summary = textwrap.fill(summary, width=50).replace("\n", "\\n")
48
 
49
+ # TTS
50
+ audio = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3").name
51
+ gTTS(text=summary).save(audio)
52
 
53
+ # Background image
54
+ bg = tempfile.NamedTemporaryFile(delete=False, suffix=".png").name
55
+ create_background(bg)
 
 
 
 
 
 
 
 
 
56
 
57
+ # Build video stream
58
+ video_stream = ffmpeg.input(bg, loop=1, framerate=1)
59
+ text_opts = dict(
60
+ fontfile="/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
61
+ text=wrapped_summary,
62
+ fontcolor="white",
63
+ fontsize=48,
64
+ box=1,
65
+ boxcolor="[email protected]",
66
+ boxborderw=5,
67
+ x="(w-text_w)/2",
68
+ y=f"h-(t*(h+text_h)/{duration})"
69
+ )
70
+ video = video_stream.drawtext(**text_opts).setpts('PTS')
71
+ audio_stream = ffmpeg.input(audio)
72
+
73
+ out_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
74
+ out = ffmpeg.output(video, audio_stream, out_path,
75
+ vcodec="libx264", acodec="aac", pix_fmt="yuv420p", t=duration)
76
+ out.run(quiet=True)
77
+
78
+ return summary, out_path
79
 
80
  iface = gr.Interface(
81
  fn=url_to_av_summary,
82
+ inputs=[gr.Textbox(label="Article URL"), gr.Radio([5,10], label="Duration (sec)", value=5)],
83
+ outputs=[gr.Textbox(label="Summary"), gr.Video(label="AV Summary")],
84
+ title="AV Summary Generator",
85
+ description="Generate a promo-style AV summary (5 or 10s) using OpenAI + gTTS + ffmpeg-python."
 
 
 
 
 
 
86
  )
87
 
88
+ if __name__=='__main__':
89
  iface.launch()