Spaces:
Running
Running
Upload app.py
Browse files
app.py
CHANGED
|
@@ -13,32 +13,68 @@ def extract_last_frame(video_file):
|
|
| 13 |
# 創建固定名稱的輸出檔案
|
| 14 |
temp_output = tempfile.mktemp(suffix='.jpg')
|
| 15 |
|
| 16 |
-
#
|
| 17 |
-
|
| 18 |
-
duration_cmd = [
|
| 19 |
'ffprobe',
|
| 20 |
'-v', 'error',
|
| 21 |
-
'-
|
| 22 |
-
'-
|
|
|
|
|
|
|
| 23 |
video_file
|
| 24 |
]
|
| 25 |
|
| 26 |
-
|
| 27 |
-
duration = float(duration_result.stdout.strip())
|
| 28 |
|
| 29 |
-
#
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
if os.path.exists(temp_output) and os.path.getsize(temp_output) > 0:
|
| 44 |
# 重新命名為 lastframe.jpg
|
|
@@ -73,8 +109,8 @@ def merge_videos_wrapper(video_files):
|
|
| 73 |
return None, message
|
| 74 |
|
| 75 |
# 創建 Gradio 界面
|
| 76 |
-
with gr.Blocks(title="
|
| 77 |
-
gr.Markdown("#
|
| 78 |
gr.Markdown("提供影片最後一幀提取和多段影片合併功能")
|
| 79 |
|
| 80 |
with gr.Tabs():
|
|
|
|
| 13 |
# 創建固定名稱的輸出檔案
|
| 14 |
temp_output = tempfile.mktemp(suffix='.jpg')
|
| 15 |
|
| 16 |
+
# 獲取影片總幀數
|
| 17 |
+
frame_count_cmd = [
|
|
|
|
| 18 |
'ffprobe',
|
| 19 |
'-v', 'error',
|
| 20 |
+
'-select_streams', 'v:0',
|
| 21 |
+
'-count_frames',
|
| 22 |
+
'-show_entries', 'stream=nb_read_frames',
|
| 23 |
+
'-of', 'default=nokey=1:noprint_wrappers=1',
|
| 24 |
video_file
|
| 25 |
]
|
| 26 |
|
| 27 |
+
frame_result = subprocess.run(frame_count_cmd, capture_output=True, text=True)
|
|
|
|
| 28 |
|
| 29 |
+
# 如果無法獲取幀數,使用反向讀取方法
|
| 30 |
+
if not frame_result.stdout.strip() or frame_result.returncode != 0:
|
| 31 |
+
# 方法2: 使用 select 過濾器選擇最後一幀
|
| 32 |
+
extract_cmd = [
|
| 33 |
+
'ffmpeg',
|
| 34 |
+
'-i', video_file,
|
| 35 |
+
'-vf', 'select=eq(n\\,0)',
|
| 36 |
+
'-vsync', '0',
|
| 37 |
+
'-q:v', '2',
|
| 38 |
+
'-frames:v', '1',
|
| 39 |
+
temp_output,
|
| 40 |
+
'-y'
|
| 41 |
+
]
|
| 42 |
+
|
| 43 |
+
# 先嘗試從尾部讀取
|
| 44 |
+
extract_cmd_reverse = [
|
| 45 |
+
'ffmpeg',
|
| 46 |
+
'-sseof', '-3',
|
| 47 |
+
'-i', video_file,
|
| 48 |
+
'-vframes', '1',
|
| 49 |
+
'-vf', 'select=eq(pict_type\\,I)',
|
| 50 |
+
'-vsync', '0',
|
| 51 |
+
'-q:v', '2',
|
| 52 |
+
temp_output,
|
| 53 |
+
'-y'
|
| 54 |
+
]
|
| 55 |
+
|
| 56 |
+
result = subprocess.run(extract_cmd_reverse, capture_output=True, text=True)
|
| 57 |
+
|
| 58 |
+
# 如果失敗,使用標準方法
|
| 59 |
+
if result.returncode != 0 or not os.path.exists(temp_output):
|
| 60 |
+
subprocess.run(extract_cmd, capture_output=True, text=True)
|
| 61 |
+
else:
|
| 62 |
+
# 方法1: 使用幀數選擇最後一幀
|
| 63 |
+
total_frames = int(frame_result.stdout.strip())
|
| 64 |
+
last_frame = total_frames - 1
|
| 65 |
+
|
| 66 |
+
extract_cmd = [
|
| 67 |
+
'ffmpeg',
|
| 68 |
+
'-i', video_file,
|
| 69 |
+
'-vf', f'select=eq(n\\,{last_frame})',
|
| 70 |
+
'-vsync', '0',
|
| 71 |
+
'-q:v', '2',
|
| 72 |
+
'-frames:v', '1',
|
| 73 |
+
temp_output,
|
| 74 |
+
'-y'
|
| 75 |
+
]
|
| 76 |
+
|
| 77 |
+
subprocess.run(extract_cmd, check=True, capture_output=True)
|
| 78 |
|
| 79 |
if os.path.exists(temp_output) and os.path.getsize(temp_output) > 0:
|
| 80 |
# 重新命名為 lastframe.jpg
|
|
|
|
| 109 |
return None, message
|
| 110 |
|
| 111 |
# 創建 Gradio 界面
|
| 112 |
+
with gr.Blocks(title="影片工具箱") as demo:
|
| 113 |
+
gr.Markdown("# 影片工具箱")
|
| 114 |
gr.Markdown("提供影片最後一幀提取和多段影片合併功能")
|
| 115 |
|
| 116 |
with gr.Tabs():
|