gen final video from fronted
Browse files- app.py +7 -15
- simulation.py +77 -0
app.py
CHANGED
@@ -4,7 +4,7 @@ import gradio as gr
|
|
4 |
from config import SCENE_CONFIGS, MODEL_CHOICES, MODE_CHOICES
|
5 |
from backend_api import submit_to_backend, get_task_status, get_task_result
|
6 |
from logging_utils import log_access, log_submission, is_request_allowed
|
7 |
-
from simulation import stream_simulation_results, convert_to_h264
|
8 |
from ui_components import update_history_display, update_scene_display, update_log_display, get_scene_instruction
|
9 |
from oss_utils import download_oss_file, get_user_tmp_dir, cleanup_user_tmp_dir, oss_file_exists
|
10 |
import os
|
@@ -55,23 +55,15 @@ def run_simulation(scene, model, mode, prompt, history, request: gr.Request):
|
|
55 |
# 获取最终任务状态
|
56 |
status = get_task_status(task_id)
|
57 |
if status.get("status") == "completed":
|
58 |
-
# 从OSS下载最终视频文件
|
59 |
-
oss_video_path = os.path.join(result_folder, "output.mp4") # 或者根据实际的视频文件名调整
|
60 |
-
user_dir = get_user_tmp_dir(session_id)
|
61 |
-
local_video_path = os.path.join(user_dir, task_id, "output.mp4")
|
62 |
-
|
63 |
try:
|
64 |
-
#
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
else:
|
69 |
-
# 如果OSS上没有最终视频,使用最后一个片段
|
70 |
-
gr.Info("Final video not found in OSS, using last segment")
|
71 |
-
video_path = None
|
72 |
|
73 |
except Exception as e:
|
74 |
-
print(f"Error
|
|
|
75 |
video_path = None
|
76 |
new_entry = {
|
77 |
"timestamp": timestamp,
|
|
|
4 |
from config import SCENE_CONFIGS, MODEL_CHOICES, MODE_CHOICES
|
5 |
from backend_api import submit_to_backend, get_task_status, get_task_result
|
6 |
from logging_utils import log_access, log_submission, is_request_allowed
|
7 |
+
from simulation import stream_simulation_results, convert_to_h264, create_final_video_from_oss_images
|
8 |
from ui_components import update_history_display, update_scene_display, update_log_display, get_scene_instruction
|
9 |
from oss_utils import download_oss_file, get_user_tmp_dir, cleanup_user_tmp_dir, oss_file_exists
|
10 |
import os
|
|
|
55 |
# 获取最终任务状态
|
56 |
status = get_task_status(task_id)
|
57 |
if status.get("status") == "completed":
|
|
|
|
|
|
|
|
|
|
|
58 |
try:
|
59 |
+
# 从OSS上的所有图片拼接成最终视频(6帧每秒)
|
60 |
+
gr.Info("Creating final video from all OSS images...")
|
61 |
+
video_path = create_final_video_from_oss_images(result_folder, task_id, request, fps=6)
|
62 |
+
gr.Info(f"Final video created successfully with 6 fps!")
|
|
|
|
|
|
|
|
|
63 |
|
64 |
except Exception as e:
|
65 |
+
print(f"Error creating final video from OSS images: {e}")
|
66 |
+
log_submission(scene, prompt, model, user_ip, f"Final video creation failed: {str(e)}")
|
67 |
video_path = None
|
68 |
new_entry = {
|
69 |
"timestamp": timestamp,
|
simulation.py
CHANGED
@@ -184,3 +184,80 @@ def convert_to_h264(video_path):
|
|
184 |
raise gr.Error(f"FFmpeg 转换失败: {e.stderr}")
|
185 |
except Exception as e:
|
186 |
raise gr.Error(f"转换过程中发生错误: {str(e)}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
raise gr.Error(f"FFmpeg 转换失败: {e.stderr}")
|
185 |
except Exception as e:
|
186 |
raise gr.Error(f"转换过程中发生错误: {str(e)}")
|
187 |
+
|
188 |
+
def create_final_video_from_oss_images(result_folder: str, task_id: str, request: gr.Request, fps: int = 6) -> str:
|
189 |
+
"""
|
190 |
+
从OSS上的所有图片拼接成最终完整视频
|
191 |
+
|
192 |
+
参数:
|
193 |
+
result_folder: OSS上的结果文件夹路径
|
194 |
+
task_id: 任务ID
|
195 |
+
request: Gradio请求对象
|
196 |
+
fps: 视频帧率 (6帧每秒)
|
197 |
+
|
198 |
+
返回:
|
199 |
+
最终视频文件路径
|
200 |
+
"""
|
201 |
+
# 获取图片文件夹路径
|
202 |
+
image_folder = os.path.join(result_folder, "images")
|
203 |
+
user_dir = get_user_tmp_dir(request.session_hash)
|
204 |
+
local_image_dir = os.path.join(user_dir, task_id, "final_images")
|
205 |
+
os.makedirs(local_image_dir, exist_ok=True)
|
206 |
+
|
207 |
+
try:
|
208 |
+
# 1. 获取OSS上的所有图片文件
|
209 |
+
oss_files = list_oss_files(image_folder)
|
210 |
+
image_files = [f for f in oss_files if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
|
211 |
+
|
212 |
+
if not image_files:
|
213 |
+
raise gr.Error("No images found in OSS for final video creation")
|
214 |
+
|
215 |
+
# 2. 按文件名排序确保时间顺序正确
|
216 |
+
image_files.sort(key=lambda x: os.path.splitext(os.path.basename(x))[0])
|
217 |
+
|
218 |
+
# 3. 下载所有图片到本地
|
219 |
+
frames = []
|
220 |
+
width, height = 0, 0
|
221 |
+
|
222 |
+
for oss_path in image_files:
|
223 |
+
try:
|
224 |
+
filename = os.path.basename(oss_path)
|
225 |
+
local_path = os.path.join(local_image_dir, filename)
|
226 |
+
download_oss_file(oss_path, local_path)
|
227 |
+
|
228 |
+
# 读取图片
|
229 |
+
frame = cv2.imread(local_path)
|
230 |
+
if frame is not None:
|
231 |
+
if width == 0: # 第一次获取图像尺寸
|
232 |
+
height, width = frame.shape[:2]
|
233 |
+
frames.append(frame)
|
234 |
+
|
235 |
+
except Exception as e:
|
236 |
+
print(f"Error processing {oss_path}: {e}")
|
237 |
+
continue
|
238 |
+
|
239 |
+
if not frames:
|
240 |
+
raise gr.Error("No valid images could be processed for final video")
|
241 |
+
|
242 |
+
# 4. 创建最终视频
|
243 |
+
final_video_dir = os.path.join(user_dir, task_id, "final")
|
244 |
+
os.makedirs(final_video_dir, exist_ok=True)
|
245 |
+
final_video_path = os.path.join(final_video_dir, "final_video.mp4")
|
246 |
+
|
247 |
+
# 使用OpenCV创建视频
|
248 |
+
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
249 |
+
out = cv2.VideoWriter(final_video_path, fourcc, fps, (width, height))
|
250 |
+
|
251 |
+
for frame in frames:
|
252 |
+
out.write(frame)
|
253 |
+
out.release()
|
254 |
+
|
255 |
+
# 5. 转换为H.264格式
|
256 |
+
h264_video_path = convert_to_h264(final_video_path)
|
257 |
+
|
258 |
+
print(f"Final video created: {h264_video_path} with {len(frames)} frames at {fps} fps")
|
259 |
+
return h264_video_path
|
260 |
+
|
261 |
+
except Exception as e:
|
262 |
+
print(f"Error creating final video from OSS images: {e}")
|
263 |
+
raise gr.Error(f"Failed to create final video: {str(e)}")
|