MySafeCode commited on
Commit
a7ce9d4
·
verified ·
1 Parent(s): f63e5b7

Update src/app.py.py

Browse files
Files changed (1) hide show
  1. src/app.py.py +176 -176
src/app.py.py CHANGED
@@ -1,176 +1,176 @@
1
- import streamlit as st
2
- import cv2
3
- import numpy as np
4
- from pathlib import Path
5
- import subprocess
6
- import shutil
7
-
8
- st.title("🎬 Live Preview + Shader + Logo App (GPU/CPU + Audio)")
9
-
10
- # --- Uploads ---
11
- video_file = st.file_uploader("Upload video", type=["mp4", "mov"])
12
- logo_file = st.file_uploader("Upload logo PNG", type=["png"])
13
- logo_size_option = st.selectbox("Logo size", [64, 128, 256])
14
-
15
- # --- Shader toggle ---
16
- shader_option = st.radio("Apply Shader?", ["Yes", "No"])
17
- shader_code = """
18
- def shader_frame(width, height, t):
19
- x = np.linspace(0, 1, width)
20
- y = np.linspace(0, 1, height)
21
- xv, yv = np.meshgrid(x, y)
22
- r = ((xv + 0.5*np.sin(t)) % 1.0 * 255).astype(np.uint8)
23
- g = ((yv + 0.5*np.cos(t)) % 1.0 * 255).astype(np.uint8)
24
- b = (0.5*255*np.ones_like(r)).astype(np.uint8)
25
- frame = np.stack([b, g, r], axis=2)
26
- return frame
27
- """
28
- if shader_option == "Yes":
29
- st.text_area("Current shader code", shader_code, height=200)
30
-
31
- # --- Paths ---
32
- video_path = Path("video.mp4")
33
- if video_file:
34
- video_path.write_bytes(video_file.getbuffer())
35
-
36
- status_placeholder = st.empty()
37
-
38
- # --- Shader generator ---
39
- def shader_frame(width, height, t):
40
- x = np.linspace(0, 1, width)
41
- y = np.linspace(0, 1, height)
42
- xv, yv = np.meshgrid(x, y)
43
- r = ((xv + 0.5*np.sin(t)) % 1.0 * 255).astype(np.uint8)
44
- g = ((yv + 0.5*np.cos(t)) % 1.0 * 255).astype(np.uint8)
45
- b = (0.5*255*np.ones_like(r)).astype(np.uint8)
46
- frame = np.stack([b, g, r], axis=2)
47
- return frame
48
-
49
- # --- Logo loader ---
50
- logo = None
51
- has_alpha = False
52
- if logo_file:
53
- logo_data = np.frombuffer(logo_file.read(), np.uint8)
54
- logo = cv2.imdecode(logo_data, cv2.IMREAD_UNCHANGED)
55
- has_alpha = logo.shape[2] == 4 if logo.ndim == 3 else False
56
- st.text(f"Logo loaded, transparency: {'Yes' if has_alpha else 'No'}")
57
-
58
- # Resize logo
59
- lh, lw = logo.shape[:2]
60
- scale = logo_size_option / max(lw, lh)
61
- new_w = int(lw * scale)
62
- new_h = int(lh * scale)
63
- logo = cv2.resize(logo, (new_w, new_h), interpolation=cv2.INTER_AREA)
64
-
65
- # --- Logo overlay ---
66
- def overlay_logo(frame, logo, has_alpha):
67
- height, width = frame.shape[:2]
68
- lh, lw = logo.shape[:2]
69
- y1, y2 = height - lh - 10, height - 10
70
- x1, x2 = width - lw - 10, width - 10
71
- if has_alpha:
72
- alpha = logo[:, :, 3] / 255.0
73
- for c in range(3):
74
- frame[y1:y2, x1:x2, c] = (
75
- alpha * logo[:, :, c] + (1 - alpha) * frame[y1:y2, x1:x2, c]
76
- )
77
- else:
78
- frame[y1:y2, x1:x2] = logo[:, :, :3]
79
- return frame
80
-
81
- # --- GPU detection ---
82
- def has_nvenc():
83
- try:
84
- result = subprocess.run(["ffmpeg", "-encoders"], capture_output=True, text=True)
85
- return "h264_nvenc" in result.stdout
86
- except Exception:
87
- return False
88
-
89
- # --- Preview generator ---
90
- def generate_preview():
91
- if not video_file:
92
- status_placeholder.warning("Upload a video first!")
93
- return
94
-
95
- cap = cv2.VideoCapture(str(video_path))
96
- fps = cap.get(cv2.CAP_PROP_FPS) or 30
97
- width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
98
- height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
99
- total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
100
-
101
- st.text(f"Preview resolution: {width} x {height} @ {fps:.1f} FPS")
102
-
103
- tmp_out = Path("temp_frames.mp4")
104
- out = cv2.VideoWriter(str(tmp_out),
105
- cv2.VideoWriter_fourcc(*'mp4v'),
106
- fps, (width, height))
107
-
108
- t = 0.0
109
- dt = 1.0 / fps
110
- frame_idx = 0
111
-
112
- preview_display = st.empty()
113
- progress_bar = st.progress(0)
114
-
115
- while True:
116
- ret, frame = cap.read()
117
- if not ret:
118
- break
119
-
120
- # Shader
121
- if shader_option == "Yes":
122
- shader = shader_frame(width, height, t)
123
- blended = cv2.addWeighted(frame, 0.7, shader, 0.3, 0)
124
- else:
125
- blended = frame.copy()
126
-
127
- # Logo
128
- if logo is not None:
129
- blended = overlay_logo(blended, logo, has_alpha)
130
-
131
- out.write(blended)
132
-
133
- # Live preview
134
- preview_small = cv2.resize(blended, (width // 2, height // 2))
135
- preview_display.image(preview_small, channels="BGR")
136
-
137
- t += dt
138
- frame_idx += 1
139
- progress_bar.progress(min(frame_idx / max(total_frames, 1), 1.0))
140
-
141
- cap.release()
142
- out.release()
143
-
144
- # --- Merge audio ---
145
- output_path = Path("preview.mp4")
146
- encoder = "h264_nvenc" if has_nvenc() else "libx264"
147
- st.info(f"Encoding with: {encoder}")
148
-
149
- cmd = [
150
- "ffmpeg", "-y",
151
- "-i", str(tmp_out),
152
- "-i", str(video_path),
153
- "-map", "0:v:0",
154
- "-map", "1:a:0",
155
- "-c:v", encoder,
156
- "-preset", "fast",
157
- "-b:v", "5M",
158
- "-c:a", "aac",
159
- str(output_path)
160
- ]
161
-
162
- try:
163
- subprocess.run(cmd, check=True)
164
- st.success("✅ Preview generated successfully with audio!")
165
- st.video(str(output_path))
166
- st.markdown(f"[📥 Download preview](./{output_path})")
167
- except subprocess.CalledProcessError as e:
168
- st.error("❌ FFmpeg failed to merge audio.")
169
- st.text(e)
170
-
171
- # --- Buttons ---
172
- if st.button("Generate Preview"):
173
- generate_preview()
174
-
175
- if st.button("Go Live"):
176
- st.warning("Go Live is not implemented yet.")
 
1
+ import streamlit as st
2
+ import cv2
3
+ import numpy as np
4
+ from pathlib import Path
5
+ import subprocess
6
+ import shutil
7
+
8
+ st.title("🎬 Download this file and run with ffmpeg8.0 + streamlit locally. Not here!")
9
+
10
+ # --- Uploads ---
11
+ video_file = st.file_uploader("Upload video", type=["mp4", "mov"])
12
+ logo_file = st.file_uploader("Upload logo PNG", type=["png"])
13
+ logo_size_option = st.selectbox("Logo size", [64, 128, 256])
14
+
15
+ # --- Shader toggle ---
16
+ shader_option = st.radio("Apply Shader?", ["Yes", "No"])
17
+ shader_code = """
18
+ def shader_frame(width, height, t):
19
+ x = np.linspace(0, 1, width)
20
+ y = np.linspace(0, 1, height)
21
+ xv, yv = np.meshgrid(x, y)
22
+ r = ((xv + 0.5*np.sin(t)) % 1.0 * 255).astype(np.uint8)
23
+ g = ((yv + 0.5*np.cos(t)) % 1.0 * 255).astype(np.uint8)
24
+ b = (0.5*255*np.ones_like(r)).astype(np.uint8)
25
+ frame = np.stack([b, g, r], axis=2)
26
+ return frame
27
+ """
28
+ if shader_option == "Yes":
29
+ st.text_area("Current shader code", shader_code, height=200)
30
+
31
+ # --- Paths ---
32
+ video_path = Path("video.mp4")
33
+ if video_file:
34
+ video_path.write_bytes(video_file.getbuffer())
35
+
36
+ status_placeholder = st.empty()
37
+
38
+ # --- Shader generator ---
39
+ def shader_frame(width, height, t):
40
+ x = np.linspace(0, 1, width)
41
+ y = np.linspace(0, 1, height)
42
+ xv, yv = np.meshgrid(x, y)
43
+ r = ((xv + 0.5*np.sin(t)) % 1.0 * 255).astype(np.uint8)
44
+ g = ((yv + 0.5*np.cos(t)) % 1.0 * 255).astype(np.uint8)
45
+ b = (0.5*255*np.ones_like(r)).astype(np.uint8)
46
+ frame = np.stack([b, g, r], axis=2)
47
+ return frame
48
+
49
+ # --- Logo loader ---
50
+ logo = None
51
+ has_alpha = False
52
+ if logo_file:
53
+ logo_data = np.frombuffer(logo_file.read(), np.uint8)
54
+ logo = cv2.imdecode(logo_data, cv2.IMREAD_UNCHANGED)
55
+ has_alpha = logo.shape[2] == 4 if logo.ndim == 3 else False
56
+ st.text(f"Logo loaded, transparency: {'Yes' if has_alpha else 'No'}")
57
+
58
+ # Resize logo
59
+ lh, lw = logo.shape[:2]
60
+ scale = logo_size_option / max(lw, lh)
61
+ new_w = int(lw * scale)
62
+ new_h = int(lh * scale)
63
+ logo = cv2.resize(logo, (new_w, new_h), interpolation=cv2.INTER_AREA)
64
+
65
+ # --- Logo overlay ---
66
+ def overlay_logo(frame, logo, has_alpha):
67
+ height, width = frame.shape[:2]
68
+ lh, lw = logo.shape[:2]
69
+ y1, y2 = height - lh - 10, height - 10
70
+ x1, x2 = width - lw - 10, width - 10
71
+ if has_alpha:
72
+ alpha = logo[:, :, 3] / 255.0
73
+ for c in range(3):
74
+ frame[y1:y2, x1:x2, c] = (
75
+ alpha * logo[:, :, c] + (1 - alpha) * frame[y1:y2, x1:x2, c]
76
+ )
77
+ else:
78
+ frame[y1:y2, x1:x2] = logo[:, :, :3]
79
+ return frame
80
+
81
+ # --- GPU detection ---
82
+ def has_nvenc():
83
+ try:
84
+ result = subprocess.run(["ffmpeg", "-encoders"], capture_output=True, text=True)
85
+ return "h264_nvenc" in result.stdout
86
+ except Exception:
87
+ return False
88
+
89
+ # --- Preview generator ---
90
+ def generate_preview():
91
+ if not video_file:
92
+ status_placeholder.warning("Upload a video first!")
93
+ return
94
+
95
+ cap = cv2.VideoCapture(str(video_path))
96
+ fps = cap.get(cv2.CAP_PROP_FPS) or 30
97
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
98
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
99
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
100
+
101
+ st.text(f"Preview resolution: {width} x {height} @ {fps:.1f} FPS")
102
+
103
+ tmp_out = Path("temp_frames.mp4")
104
+ out = cv2.VideoWriter(str(tmp_out),
105
+ cv2.VideoWriter_fourcc(*'mp4v'),
106
+ fps, (width, height))
107
+
108
+ t = 0.0
109
+ dt = 1.0 / fps
110
+ frame_idx = 0
111
+
112
+ preview_display = st.empty()
113
+ progress_bar = st.progress(0)
114
+
115
+ while True:
116
+ ret, frame = cap.read()
117
+ if not ret:
118
+ break
119
+
120
+ # Shader
121
+ if shader_option == "Yes":
122
+ shader = shader_frame(width, height, t)
123
+ blended = cv2.addWeighted(frame, 0.7, shader, 0.3, 0)
124
+ else:
125
+ blended = frame.copy()
126
+
127
+ # Logo
128
+ if logo is not None:
129
+ blended = overlay_logo(blended, logo, has_alpha)
130
+
131
+ out.write(blended)
132
+
133
+ # Live preview
134
+ preview_small = cv2.resize(blended, (width // 2, height // 2))
135
+ preview_display.image(preview_small, channels="BGR")
136
+
137
+ t += dt
138
+ frame_idx += 1
139
+ progress_bar.progress(min(frame_idx / max(total_frames, 1), 1.0))
140
+
141
+ cap.release()
142
+ out.release()
143
+
144
+ # --- Merge audio ---
145
+ output_path = Path("preview.mp4")
146
+ encoder = "h264_nvenc" if has_nvenc() else "libx264"
147
+ st.info(f"Encoding with: {encoder}")
148
+
149
+ cmd = [
150
+ "ffmpeg", "-y",
151
+ "-i", str(tmp_out),
152
+ "-i", str(video_path),
153
+ "-map", "0:v:0",
154
+ "-map", "1:a:0",
155
+ "-c:v", encoder,
156
+ "-preset", "fast",
157
+ "-b:v", "5M",
158
+ "-c:a", "aac",
159
+ str(output_path)
160
+ ]
161
+
162
+ try:
163
+ subprocess.run(cmd, check=True)
164
+ st.success("✅ Preview generated successfully with audio!")
165
+ st.video(str(output_path))
166
+ st.markdown(f"[📥 Download preview](./{output_path})")
167
+ except subprocess.CalledProcessError as e:
168
+ st.error("❌ FFmpeg failed to merge audio.")
169
+ st.text(e)
170
+
171
+ # --- Buttons ---
172
+ if st.button("Generate Preview"):
173
+ generate_preview()
174
+
175
+ if st.button("Go Live"):
176
+ st.warning("Go Live is not implemented yet.")