RohitCSharp commited on
Commit
106c061
·
verified ·
1 Parent(s): 1389833

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -47
app.py CHANGED
@@ -1,16 +1,16 @@
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,70 +20,65 @@ Summary:
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()
 
1
  import gradio as gr
2
+ import tempfile, requests, os
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
  import ffmpeg
10
  import textwrap
11
 
12
+ # OpenAI LLM
13
+ llm = ChatOpenAI(model="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 article content
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
+ # Create a single-slide background
32
+ def create_background(text, path, size=(1280,720)):
33
+ img = Image.new("RGB", size, color=(20, 30, 60))
34
  draw = ImageDraw.Draw(img)
35
+ wrapped = textwrap.fill(text, width=40)
36
+ lines = wrapped.split('\n')
37
+ y_text = (size[1] - len(lines)*60) // 2
38
+ for line in lines:
39
+ draw.text(((size[0]-draw.textlength(line))/2, y_text), line, fill="white")
40
+ y_text += 60
41
  img.save(path)
42
 
43
  # Generate AV summary
44
  def url_to_av_summary(url, duration):
45
  content = extract_main_content(url)
46
  if not content:
47
+ return "Failed to extract article content.", None
48
  summary = summary_chain.run(text=content[:3000]).replace('"','')[:300]
49
 
50
+ # Audio
51
+ audio_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3").name
52
+ gTTS(text=summary).save(audio_path)
53
 
54
+ # Image with multiline summary
55
+ bg_path = tempfile.NamedTemporaryFile(delete=False, suffix=".png").name
56
+ create_background(summary, bg_path)
57
 
58
+ # Final video
59
+ video_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name
60
+ cmd = [
61
+ 'ffmpeg', '-y', '-loop', '1', '-i', bg_path, '-i', audio_path,
62
+ '-c:v', 'libx264', '-c:a', 'aac', '-b:a', '192k', '-pix_fmt', 'yuv420p',
63
+ '-t', str(duration), '-shortest', video_path
64
+ ]
65
+ os.system(' '.join(cmd))
66
 
67
+ return summary, video_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  iface = gr.Interface(
70
  fn=url_to_av_summary,
71
+ inputs=[
72
+ gr.Textbox(label="Article URL"),
73
+ gr.Radio([5, 10], label="Video Duration (sec)", value=5)
74
+ ],
75
+ outputs=[
76
+ gr.Textbox(label="Summary"),
77
+ gr.Video(label="Generated AV Summary")
78
+ ],
79
+ title="🎞️ AV Summary Generator (Multiline Slide Version)",
80
+ description="Generate a short 5/10 sec AV with multiline centered text. CPU only, OpenAI + gTTS + FFmpeg."
81
  )
82
 
83
+ if __name__ == '__main__':
84
  iface.launch()