sreepathi-ravikumar commited on
Commit
255df7f
·
verified ·
1 Parent(s): 0728713

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -111
app.py CHANGED
@@ -1,167 +1,148 @@
1
- from flask import Flask, request, jsonify, send_file
 
2
  import traceback
3
- import uuid
4
- import glob
5
- import asyncio
6
- from image_fetcher import main
7
- from video import create_text_image
8
- from moviepy.editor import *
9
  from PIL import Image
10
- import pytesseract
11
- import numpy as np
12
  from gtts import gTTS
13
  from mutagen.mp3 import MP3
14
- from gtts import gTTS
15
- import os
 
 
 
 
 
 
 
 
16
 
17
- def video_func(id,lines):
18
- tts = gTTS(text=lines[id], lang='ta', slow=False)
19
- filename = "/tmp/audio"+str(id)+".mp3"
20
- tts.save(filename)
21
- if os.path.exists(filename):
22
- audio = MP3(filename)
23
  duration = audio.info.length
24
- IMAGE_PATH = "/tmp/images/slide"+str(id)+".png" # Ensure this path is correct
25
- VIDEO_DURATION = duration # seconds
26
- HIGHLIGHT_COLOR = (255, 255, 0) # Yellow highlight
27
- HIGHLIGHT_OPACITY = 0.5 # Semi-transparent
28
-
29
- # --- OCR STEP ---
30
- img = Image.open(IMAGE_PATH)
31
- data = pytesseract.image_to_data(img, output_type=pytesseract.Output.DICT)
32
-
33
- # Extract words and their positions
34
- words = []
35
- for i in range(len(data['text'])):
36
- word = data['text'][i].strip()
37
- if word and int(data['conf'][i]) > 60:
38
- x, y, w, h = data['left'][i], data['top'][i], data['width'][i], data['height'][i]
39
- words.append({'text': word, 'box': (x, y, w, h)})
40
-
41
- # --- BASE IMAGE CLIP ---
42
- image_clip = ImageClip(IMAGE_PATH).set_duration(VIDEO_DURATION)
43
-
44
- # --- HIGHLIGHT WORDS ONE BY ONE ---
45
- n_words = len(words)
46
- highlight_duration = VIDEO_DURATION / n_words
47
-
48
- highlight_clips = []
49
-
50
- for i, word in enumerate(words):
51
- x, y, w, h = word['box']
52
- start = i * highlight_duration
53
- end = start + highlight_duration
54
-
55
- # Create highlight rectangle
56
- rect = ColorClip(size=(w, h), color=HIGHLIGHT_COLOR)
57
- rect = rect.set_opacity(HIGHLIGHT_OPACITY).set_position((x, y)).set_start(start).set_end(end)
58
-
59
- highlight_clips.append(rect)
60
-
61
- # --- FINAL VIDEO --
62
-
63
- final_clip = CompositeVideoClip([image_clip] + highlight_clips)
64
- audio = AudioFileClip(filename)
65
- final_clip = final_clip.set_audio(audio)
66
- final_clip.write_videofile("/tmp/clip"+str(id)+".mp4", fps=24)
67
 
68
- app = Flask(__name__)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
- @app.route("/")
71
- def home():
72
- return "Flask Video Generator is Running"
73
 
74
  @app.route("/generate", methods=["POST"])
75
  def generate_video():
76
  try:
77
  data = request.get_json()
78
  prompt = data.get("duration", '').strip()
79
- prompts=prompt.replace("**","")
80
- print(prompts)
81
- if prompts == '':
82
- return jsonify({"error": "prompts be must"}), 400
83
- image_folder = "/tmp/images"
84
- #line=prompts.splitlines()
85
- #asyncio.run(main(line))
86
- raw_lines = prompts.splitlines(keepends=False)
87
  lines = []
88
-
89
  i = 0
 
90
  while i < len(raw_lines):
91
  line = raw_lines[i].strip()
92
-
93
- # Check if current line is a heading
94
- if line.strip().startswith("#") and (line.endswith('?') or line.endswith(':')):
95
- block = line # Start block with heading
96
  i += 1
97
-
98
- # Accumulate body lines until next heading or 5+ lines
99
  paragraph_lines = []
 
100
  while i < len(raw_lines):
101
  next_line = raw_lines[i].strip()
102
-
103
- # Stop if next line is a heading
104
- if next_line.strip().startswith("#") and (next_line.endswith('?') or next_line.endswith(':')):
105
  break
106
-
107
  paragraph_lines.append(next_line)
108
  i += 1
109
-
110
- # If we've gathered enough lines for a slide, break to next
111
  if len(paragraph_lines) >= 5:
112
  break
113
-
114
- # Combine heading + paragraph
115
  if paragraph_lines:
116
  block += '\n' + '\n'.join(paragraph_lines)
117
-
118
  lines.append(block)
119
-
120
  else:
121
- # Group normal lines (not part of any heading)
122
  block_lines = []
123
  count = 0
124
-
125
  while i < len(raw_lines) and count < 5:
126
  next_line = raw_lines[i].strip()
127
-
128
- # If this is a heading, break to handle it separately
129
- if next_line.strip().startswith("#") and (next_line.endswith('?') or next_line.endswith(':')):
130
  break
131
-
132
  block_lines.append(next_line)
133
  i += 1
134
  count += 1
135
-
136
  if block_lines:
137
  lines.append('\n'.join(block_lines))
138
-
139
- # Print or use lines as slides
140
-
141
- image_olst=[]
142
  for id in range(len(lines)):
143
- create_text_image(lines[id],id,image_olst)
 
144
  for i in range(len(lines)):
145
- video_func(i,lines)
146
- clips = []
147
- for id in range(len(lines)):
148
- clip = VideoFileClip(f"clip{id}.mp4")
149
- clips.append(clip)
150
-
151
  final_video = concatenate_videoclips(clips)
152
- final_video.write_videofile("/tmp/final_output.mp4", fps=24)
 
 
 
153
  for img in image_olst:
154
  os.remove(img)
155
 
156
- return send_file("/tmp/final_output.mp4", mimetype='video/mp4')
157
 
158
  except Exception as e:
159
  traceback.print_exc()
160
  return jsonify({"error": str(e)}), 500
161
 
 
 
 
 
 
 
162
  if __name__ == "__main__":
163
  app.run(host="0.0.0.0", port=7860)
164
 
165
- # Example call (remove or change in your actual app)
166
-
167
 
 
1
+ import os
2
+ import tempfile
3
  import traceback
4
+ from flask import Flask, request, jsonify, send_file
 
 
 
 
 
5
  from PIL import Image
6
+ from moviepy.editor import *
 
7
  from gtts import gTTS
8
  from mutagen.mp3 import MP3
9
+ import pytesseract
10
+ import numpy as np
11
+
12
+ app = Flask(__name__)
13
+
14
+ def video_func(id, lines):
15
+ try:
16
+ # Temp files
17
+ temp_audio = tempfile.NamedTemporaryFile(delete=False, suffix='.mp3')
18
+ temp_audio.close()
19
 
20
+ # Text-to-Speech
21
+ tts = gTTS(text=lines[id], lang='ta', slow=False)
22
+ tts.save(temp_audio.name)
23
+
24
+ audio = MP3(temp_audio.name)
 
25
  duration = audio.info.length
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ image_path = f"/tmp/images/slide{id}.png"
28
+ video_duration = duration
29
+ highlight_color = (255, 255, 0)
30
+ highlight_opacity = 0.5
31
+
32
+ # OCR: Extract words
33
+ img = Image.open(image_path)
34
+ data = pytesseract.image_to_data(img, output_type=pytesseract.Output.DICT)
35
+
36
+ words = []
37
+ for i in range(len(data['text'])):
38
+ word = data['text'][i].strip()
39
+ if word and int(data['conf'][i]) > 60:
40
+ x, y, w, h = data['left'][i], data['top'][i], data['width'][i], data['height'][i]
41
+ words.append({'text': word, 'box': (x, y, w, h)})
42
+
43
+ image_clip = ImageClip(image_path).set_duration(video_duration)
44
+
45
+ # Highlight effect
46
+ n_words = len(words)
47
+ highlight_duration = video_duration / max(n_words, 1)
48
+ highlight_clips = []
49
+
50
+ for i, word in enumerate(words):
51
+ x, y, w, h = word['box']
52
+ start = i * highlight_duration
53
+ end = start + highlight_duration
54
+
55
+ rect = ColorClip(size=(w, h), color=highlight_color)
56
+ rect = rect.set_opacity(highlight_opacity).set_position((x, y)).set_start(start).set_end(end)
57
+ highlight_clips.append(rect)
58
+
59
+ final_clip = CompositeVideoClip([image_clip] + highlight_clips)
60
+ audio = AudioFileClip(temp_audio.name)
61
+ final_clip = final_clip.set_audio(audio)
62
+ final_clip.write_videofile(f"/tmp/clip{id}.mp4", fps=24)
63
+
64
+ except Exception as e:
65
+ print(f"Error in video_func for ID {id}: {e}")
66
+ traceback.print_exc()
67
 
 
 
 
68
 
69
  @app.route("/generate", methods=["POST"])
70
  def generate_video():
71
  try:
72
  data = request.get_json()
73
  prompt = data.get("duration", '').strip()
74
+ prompts = prompt.replace("**", "")
75
+
76
+ if not prompts:
77
+ return jsonify({"error": "prompts must not be empty"}), 400
78
+
79
+ raw_lines = prompts.splitlines()
 
 
80
  lines = []
 
81
  i = 0
82
+
83
  while i < len(raw_lines):
84
  line = raw_lines[i].strip()
85
+
86
+ if line.startswith("#") and (line.endswith('?') or line.endswith(':')):
87
+ block = line
 
88
  i += 1
 
 
89
  paragraph_lines = []
90
+
91
  while i < len(raw_lines):
92
  next_line = raw_lines[i].strip()
93
+ if next_line.startswith("#") and (next_line.endswith('?') or next_line.endswith(':')):
 
 
94
  break
 
95
  paragraph_lines.append(next_line)
96
  i += 1
 
 
97
  if len(paragraph_lines) >= 5:
98
  break
99
+
 
100
  if paragraph_lines:
101
  block += '\n' + '\n'.join(paragraph_lines)
 
102
  lines.append(block)
 
103
  else:
 
104
  block_lines = []
105
  count = 0
 
106
  while i < len(raw_lines) and count < 5:
107
  next_line = raw_lines[i].strip()
108
+ if next_line.startswith("#") and (next_line.endswith('?') or next_line.endswith(':')):
 
 
109
  break
 
110
  block_lines.append(next_line)
111
  i += 1
112
  count += 1
 
113
  if block_lines:
114
  lines.append('\n'.join(block_lines))
115
+
116
+ # Slide image creation
117
+ image_olst = []
 
118
  for id in range(len(lines)):
119
+ create_text_image(lines[id], id, image_olst)
120
+
121
  for i in range(len(lines)):
122
+ video_func(i, lines)
123
+
124
+ clips = [VideoFileClip(f"/tmp/clip{id}.mp4") for id in range(len(lines))]
 
 
 
125
  final_video = concatenate_videoclips(clips)
126
+ output_path = "/tmp/final_output.mp4"
127
+ final_video.write_videofile(output_path, fps=24)
128
+
129
+ # Clean up
130
  for img in image_olst:
131
  os.remove(img)
132
 
133
+ return send_file(output_path, mimetype='video/mp4')
134
 
135
  except Exception as e:
136
  traceback.print_exc()
137
  return jsonify({"error": str(e)}), 500
138
 
139
+
140
+ @app.route("/")
141
+ def home():
142
+ return "Flask Video Generator is Running"
143
+
144
+
145
  if __name__ == "__main__":
146
  app.run(host="0.0.0.0", port=7860)
147
 
 
 
148