tester343 commited on
Commit
d2c4fc9
·
verified ·
1 Parent(s): 012f1e5

Update app_enhanced.py

Browse files
Files changed (1) hide show
  1. app_enhanced.py +37 -44
app_enhanced.py CHANGED
@@ -1,4 +1,3 @@
1
- import spaces # <--- CRITICAL: MUST BE THE FIRST IMPORT
2
  import os
3
  import time
4
  import threading
@@ -12,16 +11,20 @@ import cv2
12
  import math
13
  import numpy as np
14
  import srt
 
15
  from flask import Flask, jsonify, request, send_from_directory, send_file
16
 
17
  # ======================================================
18
- # 🚀 ZEROGPU CONFIGURATION
19
  # ======================================================
20
- @spaces.GPU
21
- def gpu_warmup():
22
- import torch
23
- print(f"✅ ZeroGPU Warmup: CUDA Available: {torch.cuda.is_available()}")
24
- return True
 
 
 
25
 
26
  # ======================================================
27
  # 🧱 DATA CLASSES
@@ -68,15 +71,16 @@ def generate_save_code(length=8):
68
  return code
69
 
70
  # ======================================================
71
- # 🧠 GLOBAL GPU FUNCTIONS
 
 
 
72
  # ======================================================
73
- @spaces.GPU(duration=300)
74
- def generate_comic_gpu(video_path, user_dir, frames_dir, metadata_path, target_pages):
75
- print(f"🚀 GPU Task Started: {video_path} | Pages: {target_pages}")
76
 
77
- import cv2
78
- import srt
79
- import numpy as np
80
  from backend.keyframes.keyframes import black_bar_crop
81
  from backend.simple_color_enhancer import SimpleColorEnhancer
82
  from backend.quality_color_enhancer import QualityColorEnhancer
@@ -98,11 +102,15 @@ def generate_comic_gpu(video_path, user_dir, frames_dir, metadata_path, target_p
98
  get_real_subtitles(video_path)
99
  if os.path.exists('test1.srt'):
100
  shutil.move('test1.srt', user_srt)
101
- except:
 
102
  with open(user_srt, 'w') as f: f.write("1\n00:00:01,000 --> 00:00:04,000\n...\n")
103
 
104
  with open(user_srt, 'r', encoding='utf-8') as f:
105
- all_subs = list(srt.parse(f.read()))
 
 
 
106
 
107
  # 3. Smart Keyframe Selection
108
  valid_subs = [s for s in all_subs if s.content.strip()]
@@ -137,7 +145,6 @@ def generate_comic_gpu(video_path, user_dir, frames_dir, metadata_path, target_p
137
  fname = f"frame_{count:04d}.png"
138
  p = os.path.join(frames_dir, fname)
139
  cv2.imwrite(p, frame)
140
- os.sync()
141
  frame_metadata[fname] = {'dialogue': moment['text'], 'time': mid}
142
  frame_files_ordered.append(fname)
143
  count += 1
@@ -149,6 +156,7 @@ def generate_comic_gpu(video_path, user_dir, frames_dir, metadata_path, target_p
149
  try: black_bar_crop()
150
  except: pass
151
 
 
152
  se = SimpleColorEnhancer()
153
  qe = QualityColorEnhancer()
154
 
@@ -198,10 +206,7 @@ def generate_comic_gpu(video_path, user_dir, frames_dir, metadata_path, target_p
198
 
199
  return result
200
 
201
- @spaces.GPU
202
- def regen_frame_gpu(video_path, frames_dir, metadata_path, fname, direction):
203
- import cv2
204
- import json
205
  from backend.simple_color_enhancer import SimpleColorEnhancer
206
 
207
  if not os.path.exists(metadata_path): return {"success": False, "message": "No metadata"}
@@ -221,7 +226,6 @@ def regen_frame_gpu(video_path, frames_dir, metadata_path, fname, direction):
221
  if ret:
222
  p = os.path.join(frames_dir, fname)
223
  cv2.imwrite(p, frame)
224
- os.sync()
225
  try: SimpleColorEnhancer().enhance_single(p, p)
226
  except: pass
227
 
@@ -231,10 +235,7 @@ def regen_frame_gpu(video_path, frames_dir, metadata_path, fname, direction):
231
  return {"success": True, "message": f"Adjusted to {new_t:.2f}s"}
232
  return {"success": False, "message": "End of video"}
233
 
234
- @spaces.GPU
235
- def get_frame_at_ts_gpu(video_path, frames_dir, metadata_path, fname, ts):
236
- import cv2
237
- import json
238
  from backend.simple_color_enhancer import SimpleColorEnhancer
239
 
240
  cap = cv2.VideoCapture(video_path)
@@ -245,7 +246,6 @@ def get_frame_at_ts_gpu(video_path, frames_dir, metadata_path, fname, ts):
245
  if ret:
246
  p = os.path.join(frames_dir, fname)
247
  cv2.imwrite(p, frame)
248
- os.sync()
249
  try: SimpleColorEnhancer().enhance_single(p, p)
250
  except: pass
251
 
@@ -280,8 +280,9 @@ class EnhancedComicGenerator:
280
 
281
  def run(self, target_pages):
282
  try:
283
- self.write_status("Waiting for GPU...", 5)
284
- data = generate_comic_gpu(self.video_path, self.user_dir, self.frames_dir, self.metadata_path, int(target_pages))
 
285
  with open(os.path.join(self.output_dir, 'pages.json'), 'w') as f:
286
  json.dump(data, f, indent=2)
287
  self.write_status("Complete!", 100)
@@ -485,7 +486,7 @@ INDEX_HTML = '''
485
  </div>
486
  </div>
487
 
488
- <!-- NEW TEMPLATE OPTIONS -->
489
  <div class="control-group">
490
  <label>📐 Page Layout (Template):</label>
491
  <select id="template-select" onchange="changeTemplate(this.value)">
@@ -629,7 +630,6 @@ INDEX_HTML = '''
629
  function getCurrentState() {
630
  const pages = [];
631
  document.querySelectorAll('.comic-page').forEach(p => {
632
- // Get Grid Class
633
  const grid = p.querySelector('.comic-grid');
634
  let template = 't-classic';
635
  if(grid) {
@@ -665,12 +665,9 @@ INDEX_HTML = '''
665
 
666
  function saveDraft() { localStorage.setItem('comic_draft_'+sid, JSON.stringify({ pages: getCurrentState(), saveCode: currentSaveCode, savedAt: new Date().toISOString() })); }
667
 
668
- // FUNCTION ADDED: Change Template
669
  function changeTemplate(tpl) {
670
  document.querySelectorAll('.comic-grid').forEach(g => {
671
- // Remove existing template classes
672
  g.classList.remove('t-classic', 't-feat-top', 't-side', 't-cinematic');
673
- // Add new
674
  g.classList.add(tpl);
675
  });
676
  saveDraft();
@@ -685,11 +682,9 @@ INDEX_HTML = '''
685
  const div = document.createElement('div'); div.className = 'comic-page';
686
 
687
  const grid = document.createElement('div');
688
- // Apply saved template or default
689
  const tpl = page.template || 't-classic';
690
  grid.className = `comic-grid ${tpl}`;
691
 
692
- // Set dropdown to current template (of first page)
693
  if(pageIdx === 0) document.getElementById('template-select').value = tpl;
694
 
695
  page.panels.forEach((pan) => {
@@ -900,7 +895,6 @@ def upload():
900
  if 'file' not in request.files or not request.files['file'].filename:
901
  return jsonify({'success': False, 'message': 'No file selected'}), 400
902
 
903
- # GET PAGE COUNT FROM FORM
904
  target_pages = request.form.get('target_pages', 4)
905
 
906
  f = request.files['file']
@@ -909,7 +903,7 @@ def upload():
909
  f.save(gen.video_path)
910
  gen.write_status("Starting...", 5)
911
 
912
- # Run in thread
913
  threading.Thread(target=gen.run, args=(target_pages,)).start()
914
  return jsonify({'success': True, 'message': 'Generation started.'})
915
 
@@ -935,16 +929,16 @@ def regen():
935
  sid = request.args.get('sid')
936
  d = request.get_json()
937
  gen = EnhancedComicGenerator(sid)
938
- # CALL GLOBAL GPU FUNCTION
939
- return jsonify(regen_frame_gpu(gen.video_path, gen.frames_dir, gen.metadata_path, d['filename'], d['direction']))
940
 
941
  @app.route('/goto_timestamp', methods=['POST'])
942
  def go_time():
943
  sid = request.args.get('sid')
944
  d = request.get_json()
945
  gen = EnhancedComicGenerator(sid)
946
- # CALL GLOBAL GPU FUNCTION
947
- return jsonify(get_frame_at_ts_gpu(gen.video_path, gen.frames_dir, gen.metadata_path, d['filename'], float(d['timestamp'])))
948
 
949
  @app.route('/replace_panel', methods=['POST'])
950
  def rep_panel():
@@ -1010,6 +1004,5 @@ def load_comic(code):
1010
  return jsonify({'success': False, 'message': str(e)})
1011
 
1012
  if __name__ == '__main__':
1013
- try: gpu_warmup()
1014
- except: pass
1015
  app.run(host='0.0.0.0', port=7860)
 
 
1
  import os
2
  import time
3
  import threading
 
11
  import math
12
  import numpy as np
13
  import srt
14
+ import torch
15
  from flask import Flask, jsonify, request, send_from_directory, send_file
16
 
17
  # ======================================================
18
+ # 🚀 CUDA CONFIGURATION
19
  # ======================================================
20
+ def check_cuda():
21
+ """Checks for CUDA availability without ZeroGPU decorators"""
22
+ if torch.cuda.is_available():
23
+ print(f"✅ CUDA Engine Active: {torch.cuda.get_device_name(0)}")
24
+ return True
25
+ else:
26
+ print("⚠️ CUDA Not Detected. Running on CPU (Expect slower generation)")
27
+ return False
28
 
29
  # ======================================================
30
  # 🧱 DATA CLASSES
 
71
  return code
72
 
73
  # ======================================================
74
+ # 🧠 CORE PROCESSING FUNCTIONS (Standard CUDA)
75
+ # ======================================================
76
+ # Removed @spaces.GPU decorators. These functions now run
77
+ # directly in the thread/process invoking them.
78
  # ======================================================
79
+
80
+ def generate_comic_core(video_path, user_dir, frames_dir, metadata_path, target_pages):
81
+ print(f"🚀 Processing Task Started: {video_path} | Pages: {target_pages}")
82
 
83
+ # Import backend logic here to ensure they load into the correct context
 
 
84
  from backend.keyframes.keyframes import black_bar_crop
85
  from backend.simple_color_enhancer import SimpleColorEnhancer
86
  from backend.quality_color_enhancer import QualityColorEnhancer
 
102
  get_real_subtitles(video_path)
103
  if os.path.exists('test1.srt'):
104
  shutil.move('test1.srt', user_srt)
105
+ except Exception as e:
106
+ print(f"Subtitle error (using placeholder): {e}")
107
  with open(user_srt, 'w') as f: f.write("1\n00:00:01,000 --> 00:00:04,000\n...\n")
108
 
109
  with open(user_srt, 'r', encoding='utf-8') as f:
110
+ try:
111
+ all_subs = list(srt.parse(f.read()))
112
+ except:
113
+ all_subs = []
114
 
115
  # 3. Smart Keyframe Selection
116
  valid_subs = [s for s in all_subs if s.content.strip()]
 
145
  fname = f"frame_{count:04d}.png"
146
  p = os.path.join(frames_dir, fname)
147
  cv2.imwrite(p, frame)
 
148
  frame_metadata[fname] = {'dialogue': moment['text'], 'time': mid}
149
  frame_files_ordered.append(fname)
150
  count += 1
 
156
  try: black_bar_crop()
157
  except: pass
158
 
159
+ # Initialize enhancers (they usually load models to CUDA if available)
160
  se = SimpleColorEnhancer()
161
  qe = QualityColorEnhancer()
162
 
 
206
 
207
  return result
208
 
209
+ def regen_frame_core(video_path, frames_dir, metadata_path, fname, direction):
 
 
 
210
  from backend.simple_color_enhancer import SimpleColorEnhancer
211
 
212
  if not os.path.exists(metadata_path): return {"success": False, "message": "No metadata"}
 
226
  if ret:
227
  p = os.path.join(frames_dir, fname)
228
  cv2.imwrite(p, frame)
 
229
  try: SimpleColorEnhancer().enhance_single(p, p)
230
  except: pass
231
 
 
235
  return {"success": True, "message": f"Adjusted to {new_t:.2f}s"}
236
  return {"success": False, "message": "End of video"}
237
 
238
+ def get_frame_at_ts_core(video_path, frames_dir, metadata_path, fname, ts):
 
 
 
239
  from backend.simple_color_enhancer import SimpleColorEnhancer
240
 
241
  cap = cv2.VideoCapture(video_path)
 
246
  if ret:
247
  p = os.path.join(frames_dir, fname)
248
  cv2.imwrite(p, frame)
 
249
  try: SimpleColorEnhancer().enhance_single(p, p)
250
  except: pass
251
 
 
280
 
281
  def run(self, target_pages):
282
  try:
283
+ self.write_status("Waiting for GPU/Processor...", 5)
284
+ # Directly call the core function (standard CUDA)
285
+ data = generate_comic_core(self.video_path, self.user_dir, self.frames_dir, self.metadata_path, int(target_pages))
286
  with open(os.path.join(self.output_dir, 'pages.json'), 'w') as f:
287
  json.dump(data, f, indent=2)
288
  self.write_status("Complete!", 100)
 
486
  </div>
487
  </div>
488
 
489
+ <!-- TEMPLATE OPTIONS -->
490
  <div class="control-group">
491
  <label>📐 Page Layout (Template):</label>
492
  <select id="template-select" onchange="changeTemplate(this.value)">
 
630
  function getCurrentState() {
631
  const pages = [];
632
  document.querySelectorAll('.comic-page').forEach(p => {
 
633
  const grid = p.querySelector('.comic-grid');
634
  let template = 't-classic';
635
  if(grid) {
 
665
 
666
  function saveDraft() { localStorage.setItem('comic_draft_'+sid, JSON.stringify({ pages: getCurrentState(), saveCode: currentSaveCode, savedAt: new Date().toISOString() })); }
667
 
 
668
  function changeTemplate(tpl) {
669
  document.querySelectorAll('.comic-grid').forEach(g => {
 
670
  g.classList.remove('t-classic', 't-feat-top', 't-side', 't-cinematic');
 
671
  g.classList.add(tpl);
672
  });
673
  saveDraft();
 
682
  const div = document.createElement('div'); div.className = 'comic-page';
683
 
684
  const grid = document.createElement('div');
 
685
  const tpl = page.template || 't-classic';
686
  grid.className = `comic-grid ${tpl}`;
687
 
 
688
  if(pageIdx === 0) document.getElementById('template-select').value = tpl;
689
 
690
  page.panels.forEach((pan) => {
 
895
  if 'file' not in request.files or not request.files['file'].filename:
896
  return jsonify({'success': False, 'message': 'No file selected'}), 400
897
 
 
898
  target_pages = request.form.get('target_pages', 4)
899
 
900
  f = request.files['file']
 
903
  f.save(gen.video_path)
904
  gen.write_status("Starting...", 5)
905
 
906
+ # Run in thread - Standard processing
907
  threading.Thread(target=gen.run, args=(target_pages,)).start()
908
  return jsonify({'success': True, 'message': 'Generation started.'})
909
 
 
929
  sid = request.args.get('sid')
930
  d = request.get_json()
931
  gen = EnhancedComicGenerator(sid)
932
+ # Direct function call
933
+ return jsonify(regen_frame_core(gen.video_path, gen.frames_dir, gen.metadata_path, d['filename'], d['direction']))
934
 
935
  @app.route('/goto_timestamp', methods=['POST'])
936
  def go_time():
937
  sid = request.args.get('sid')
938
  d = request.get_json()
939
  gen = EnhancedComicGenerator(sid)
940
+ # Direct function call
941
+ return jsonify(get_frame_at_ts_core(gen.video_path, gen.frames_dir, gen.metadata_path, d['filename'], float(d['timestamp'])))
942
 
943
  @app.route('/replace_panel', methods=['POST'])
944
  def rep_panel():
 
1004
  return jsonify({'success': False, 'message': str(e)})
1005
 
1006
  if __name__ == '__main__':
1007
+ check_cuda()
 
1008
  app.run(host='0.0.0.0', port=7860)