Ryanus commited on
Commit
7397c75
·
verified ·
1 Parent(s): bb17dc0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +185 -40
app.py CHANGED
@@ -9,11 +9,52 @@ from datetime import datetime
9
  import json
10
  import concurrent.futures
11
  import time
 
12
 
13
  # 储存目录设置
14
  STORAGE_DIR = os.path.expanduser("~/video_storage")
15
  STORAGE_CONFIG = os.path.join(STORAGE_DIR, "storage_config.json")
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  def init_storage():
18
  """初始化储存空间"""
19
  os.makedirs(STORAGE_DIR, exist_ok=True)
@@ -41,7 +82,6 @@ def save_to_storage(file_path, metadata=None):
41
  count += 1
42
 
43
  shutil.copy2(file_path, target_path)
44
- # update_storage_config() # 移除这行,在批量操作后统一更新
45
  return target_path
46
  except Exception as e:
47
  print(f"❌ 储存文件失败: {e}")
@@ -112,12 +152,10 @@ def download_all_storage():
112
 
113
  # 添加清单
114
  manifest = f"""# 储存空间视频清单
115
-
116
  ## 📊 下载信息
117
  - 下载时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
118
  - 视频总数: {len(video_files)} 个
119
  - 总大小: {config['total_size_mb']}MB
120
-
121
  ## 📁 文件列表
122
  """
123
  for video in video_files:
@@ -126,7 +164,6 @@ def download_all_storage():
126
  manifest += """
127
  ## 💡 使用说明
128
  这些是您的储存空间中保存的所有混剪视频,可直接使用或进一步编辑。
129
-
130
  ---
131
  FFmpeg 储存管理系统
132
  """
@@ -166,12 +203,10 @@ def download_selected_storage(selected_files):
166
 
167
  # 添加清单
168
  manifest = f"""# 选中视频下载清单
169
-
170
  ## 📊 下载信息
171
  - 下载时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
172
  - 选中文件: {len(valid_files)} 个
173
  - 总大小: {round(total_size, 1)}MB
174
-
175
  ## 📁 文件列表
176
  """
177
  for video in valid_files:
@@ -213,27 +248,133 @@ def clear_storage():
213
  except Exception as e:
214
  return f"❌ 清空失败: {str(e)}"
215
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  def ffmpeg_cut_video(input_path, start_time, duration, output_path):
217
- """[优化] 快速的视频切割,使用 superfast 预设"""
218
- command = [
219
- 'ffmpeg', '-i', input_path, '-ss', str(start_time), '-t', str(duration),
220
- '-c:v', 'libx264', '-preset', 'superfast', '-crf', '28',
221
- '-c:a', 'aac', '-b:a', '128k', '-avoid_negative_ts', 'make_zero', '-y', output_path
222
- ]
223
  result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
224
  return result.returncode == 0 and os.path.exists(output_path)
225
 
226
  def ffmpeg_resize_video(input_path, output_path, target_ratio):
227
- """[优化] 快速的比例调整,使用 superfast 预设"""
228
  if target_ratio == '9:16':
229
  filter_complex = "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black"
230
  else:
231
  filter_complex = "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black"
232
 
233
- command = [
234
- 'ffmpeg', '-i', input_path, '-vf', filter_complex,
235
- '-c:v', 'libx264', '-preset', 'superfast', '-crf', '28', '-c:a', 'copy', '-y', output_path
236
- ]
 
237
  result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
238
  return result.returncode == 0 and os.path.exists(output_path)
239
 
@@ -253,7 +394,9 @@ def concat_videos(file_list, output_path):
253
  list_file.write(f"file '{abs_path}'\n")
254
  list_file.close()
255
 
256
- command = ['ffmpeg', '-f', 'concat', '-safe', '0', '-i', list_file.name, '-c', 'copy', '-y', output_path]
 
 
257
  result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
258
  return result.returncode == 0 and os.path.exists(output_path)
259
  finally:
@@ -293,22 +436,24 @@ def process_single_video(video_file, clip_duration, temp_dir):
293
  return clips
294
 
295
  def process_videos_with_storage(video_files, clip_duration, num_output_videos, target_ratio):
296
- """带储存功能的视频处理 [优化版:并行切割 + 批量更新 + 进度日志]"""
297
  if not video_files:
298
  return "❌ 请上传视频文件", None, "", ""
299
 
300
- start_time = time.time() # ✅ 记录开始时间
301
  temp_dir = tempfile.mkdtemp()
302
 
303
  try:
304
  print(f"🔍 开始处理 {len(video_files)} 个视频文件...")
 
 
305
  print(f"⏱️ 切片时长: {clip_duration} 秒 | 生成数量: {num_output_videos} 个 | 比例: {target_ratio}")
306
 
307
  all_clips = []
308
 
309
- # --- [优化] 使用线程池并行处理每个视频文件 ---
310
- print(f"🚀 启动并行切片({min(4, os.cpu_count() or 1)} 线程)...")
311
- with concurrent.futures.ThreadPoolExecutor(max_workers=min(4, os.cpu_count() or 1)) as executor:
312
  future_to_video = {
313
  executor.submit(process_single_video, vf, clip_duration, temp_dir): vf
314
  for vf in video_files
@@ -326,7 +471,6 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
326
  video_file = future_to_video[future]
327
  print(f"❌ 切片失败: {os.path.basename(video_file.name)} - {exc}")
328
 
329
- # --- 并行处理结束 ---
330
  print(f"📊 所有视频切片完成,共生成 {len(all_clips)} 个片段")
331
 
332
  if not all_clips:
@@ -368,7 +512,6 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
368
  else:
369
  print(f"❌ 比例调整失败: 第 {i+1} 个视频")
370
 
371
- # --- [优化] 所有文件保存后,统一更新一次配置 ---
372
  if stored_files:
373
  update_storage_config()
374
  print(f"✅ 已统一更新储存配置,共保存 {len(stored_files)} 个视频文件")
@@ -376,7 +519,6 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
376
  if not output_files:
377
  return "❌ 生成混剪视频失败", None, "", ""
378
 
379
- # --- 打包下载 ---
380
  package_dir = tempfile.mkdtemp()
381
  timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
382
  zip_path = os.path.join(package_dir, f"混剪视频包_{target_ratio.replace(':', 'x')}_{timestamp}.zip")
@@ -389,13 +531,12 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
389
  print(f" ➤ 已添加: {arcname}")
390
 
391
  readme = f"""# 混剪视频包
392
-
393
  ## 📊 生成信息
394
  - 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
395
  - 视频数量: {len(output_files)} 个
396
  - 视频比例: {target_ratio}
397
  - 切片时长: {clip_duration} 秒
398
-
399
  ## 📁 文件列表
400
  """
401
  for i, vf in enumerate(output_files, 1):
@@ -406,7 +547,6 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
406
  ## 💾 储存信息
407
  所有视频已自动保存到本地储存空间:
408
  {', '.join(stored_files)}
409
-
410
  视频已按 {target_ratio} 比例优化,可直接发布。
411
  """
412
  zipf.writestr("README.txt", readme.encode('utf-8'))
@@ -414,31 +554,30 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
414
  total_size = os.path.getsize(zip_path) / (1024 * 1024)
415
  platform_info = "📱 短视频平台" if target_ratio == '9:16' else "🖥️ 长视频平台"
416
 
417
- end_time = time.time() # ✅ 计算耗时
418
  elapsed = end_time - start_time
419
  print(f"🎉 混剪完成!总耗时: {elapsed:.1f} 秒")
420
  print(f"📥 下载包大小: {total_size:.1f}MB")
421
  print(f"📁 已保存文件: {len(stored_files)} 个")
422
 
423
  success_msg = f"""✅ 混剪完成并已储存!
424
-
425
  📊 **生成统计:**
426
  • 🎬 混剪视频: {len(output_files)} 个
427
  • 📐 视频比例: {target_ratio}
428
  • 🎯 适合平台: {platform_info}
429
  • 📦 下载包大小: {total_size:.1f}MB
430
-
 
 
431
  💾 **自动储存:**
432
  • 📁 储存位置: ~/video_storage/
433
  • 🔥 已保存文件: {len(stored_files)} 个
434
  • ✅ 永久保存,不会丢失
435
-
436
  ⬇️ **立即下载:**
437
  点击下方按钮下载打包文件
438
  """
439
 
440
  details = f"""🎬 **视频详情:**
441
-
442
  """
443
  for i, vf in enumerate(output_files, 1):
444
  size_mb = os.path.getsize(vf) / (1024 * 1024)
@@ -452,11 +591,9 @@ def process_videos_with_storage(video_files, clip_duration, num_output_videos, t
452
 
453
  config, video_list = get_storage_info()
454
  storage_info = f"""📊 **储存空间状态:**
455
-
456
  💾 总计: {config['total_videos']} 个视频
457
  📦 总大小: {config['total_size_mb']}MB
458
  📁 位置: ~/video_storage/
459
-
460
  📋 **最新文件:**
461
  """
462
 
@@ -478,12 +615,11 @@ def refresh_storage_display():
478
  config, video_list = get_storage_info()
479
 
480
  storage_display = f"""💾 **储存空间概览**
481
-
482
  📊 **统计信息:**
483
  • 总视频数量: {config['total_videos']} 个
484
  • 总占用空间: {config['total_size_mb']}MB
485
  • 储存位置: ~/video_storage/
486
-
487
  📁 **文件列表:**
488
  """
489
 
@@ -529,10 +665,11 @@ init_storage()
529
  def main():
530
  with gr.Blocks(title="FFmpeg混剪+储存+下载管理", theme=gr.themes.Soft()) as demo:
531
 
532
- gr.HTML("""
533
  <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; color: white; margin-bottom: 20px;">
534
  <h1>🎬 FFmpeg 混剪工具 + 储存管理 + 一键下载</h1>
535
  <p style="margin: 10px 0 0 0;">长视频切片 → 智能混剪 → 比例调整 → 自动储存 → 一键下载</p>
 
536
  </div>
537
  """)
538
 
@@ -652,7 +789,7 @@ def main():
652
  outputs=[storage_display, file_selector, file_selector_download]
653
  )
654
 
655
- gr.Markdown("""
656
  ---
657
  ### 📖 功能说明
658
 
@@ -661,6 +798,8 @@ def main():
661
  - 📐 支持9:16/16:9比例调整
662
  - 📦 打包下载所有生成视频
663
  - 💾 **自动储存到本地目录**
 
 
664
 
665
  **💾 储存管理功能:**
666
  - 📁 所有生成视频自动保存到 `~/video_storage/`
@@ -685,6 +824,12 @@ def main():
685
  - **分享协作**: 打包分享给团队成员
686
  - **存档管理**: 定期下载备份到云盘
687
 
 
 
 
 
 
 
688
  **⚠️ 注意事项:**
689
  - 下载文件为ZIP格式,需要解压使用
690
  - 一键下载包含储存空间中所有视频文件
 
9
  import json
10
  import concurrent.futures
11
  import time
12
+ import platform
13
 
14
  # 储存目录设置
15
  STORAGE_DIR = os.path.expanduser("~/video_storage")
16
  STORAGE_CONFIG = os.path.join(STORAGE_DIR, "storage_config.json")
17
 
18
+ # 检测系统硬件加速支持
19
+ def detect_hardware_acceleration():
20
+ """检测可用的硬件加速"""
21
+ hardware_accel = {
22
+ 'nvidia': False,
23
+ 'amd': False,
24
+ 'intel': False,
25
+ 'encoder': 'libx264' # 默认使用软件编码
26
+ }
27
+
28
+ try:
29
+ # 检查NVIDIA GPU
30
+ result = subprocess.run(['ffmpeg', '-encoders'], capture_output=True, text=True)
31
+ if 'h264_nvenc' in result.stdout:
32
+ hardware_accel['nvidia'] = True
33
+ hardware_accel['encoder'] = 'h264_nvenc'
34
+ print("✅ 检测到NVIDIA GPU硬件加速支持")
35
+
36
+ # 检查AMD GPU
37
+ if 'h264_amf' in result.stdout:
38
+ hardware_accel['amd'] = True
39
+ if hardware_accel['encoder'] == 'libx264':
40
+ hardware_accel['encoder'] = 'h264_amf'
41
+ print("✅ 检测到AMD GPU硬件加速支持")
42
+
43
+ # 检查Intel Quick Sync
44
+ if 'h264_qsv' in result.stdout:
45
+ hardware_accel['intel'] = True
46
+ if hardware_accel['encoder'] == 'libx264':
47
+ hardware_accel['encoder'] = 'h264_qsv'
48
+ print("✅ 检测到Intel Quick Sync硬件加速支持")
49
+
50
+ except Exception as e:
51
+ print(f"⚠️ 硬件加速检测失败: {e}")
52
+
53
+ return hardware_accel
54
+
55
+ # 全局硬件加速信息
56
+ HARDWARE_ACCEL = detect_hardware_acceleration()
57
+
58
  def init_storage():
59
  """初始化储存空间"""
60
  os.makedirs(STORAGE_DIR, exist_ok=True)
 
82
  count += 1
83
 
84
  shutil.copy2(file_path, target_path)
 
85
  return target_path
86
  except Exception as e:
87
  print(f"❌ 储存文件失败: {e}")
 
152
 
153
  # 添加清单
154
  manifest = f"""# 储存空间视频清单
 
155
  ## 📊 下载信息
156
  - 下载时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
157
  - 视频总数: {len(video_files)} 个
158
  - 总大小: {config['total_size_mb']}MB
 
159
  ## 📁 文件列表
160
  """
161
  for video in video_files:
 
164
  manifest += """
165
  ## 💡 使用说明
166
  这些是您的储存空间中保存的所有混剪视频,可直接使用或进一步编辑。
 
167
  ---
168
  FFmpeg 储存管理系统
169
  """
 
203
 
204
  # 添加清单
205
  manifest = f"""# 选中视频下载清单
 
206
  ## 📊 下载信息
207
  - 下载时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
208
  - 选中文件: {len(valid_files)} 个
209
  - 总大小: {round(total_size, 1)}MB
 
210
  ## 📁 文件列表
211
  """
212
  for video in valid_files:
 
248
  except Exception as e:
249
  return f"❌ 清空失败: {str(e)}"
250
 
251
+ def get_optimal_threads():
252
+ """获取最优线程数"""
253
+ try:
254
+ cpu_count = os.cpu_count()
255
+ if cpu_count:
256
+ # 对于视频处理,使用CPU核心数的1.5倍通常效果较好
257
+ return max(1, min(cpu_count * 2, 16)) # 最多16个线程
258
+ return 4
259
+ except:
260
+ return 4
261
+
262
+ def build_ffmpeg_command(input_path, start_time, duration, output_path, operation='cut'):
263
+ """构建优化的FFmpeg命令"""
264
+ threads = get_optimal_threads()
265
+ encoder = HARDWARE_ACCEL['encoder']
266
+
267
+ base_command = ['ffmpeg', '-threads', str(threads)]
268
+
269
+ # 硬件加速解码
270
+ if HARDWARE_ACCEL['nvidia']:
271
+ base_command.extend(['-hwaccel', 'cuda'])
272
+ elif HARDWARE_ACCEL['amd']:
273
+ base_command.extend(['-hwaccel', 'amf'])
274
+ elif HARDWARE_ACCEL['intel']:
275
+ base_command.extend(['-hwaccel', 'qsv'])
276
+
277
+ base_command.extend(['-i', input_path])
278
+
279
+ if operation == 'cut':
280
+ base_command.extend(['-ss', str(start_time), '-t', str(duration)])
281
+
282
+ # 编码参数
283
+ if encoder == 'h264_nvenc':
284
+ # NVIDIA GPU编码参数
285
+ base_command.extend([
286
+ '-c:v', 'h264_nvenc',
287
+ '-preset', 'p1', # 最快预设
288
+ '-tune', 'ull', # 超低延迟
289
+ '-cq', '28', # 质量参数
290
+ '-c:a', 'aac',
291
+ '-b:a', '128k',
292
+ '-movflags', '+faststart',
293
+ '-y', output_path
294
+ ])
295
+ elif encoder == 'h264_amf':
296
+ # AMD GPU编码参数
297
+ base_command.extend([
298
+ '-c:v', 'h264_amf',
299
+ '-quality', 'speed',
300
+ '-rc', 'cqp',
301
+ '-cqp_i', '28',
302
+ '-cqp_p', '28',
303
+ '-c:a', 'aac',
304
+ '-b:a', '128k',
305
+ '-movflags', '+faststart',
306
+ '-y', output_path
307
+ ])
308
+ elif encoder == 'h264_qsv':
309
+ # Intel Quick Sync编码参数
310
+ base_command.extend([
311
+ '-c:v', 'h264_qsv',
312
+ '-preset', 'veryfast',
313
+ '-global_quality', '28',
314
+ '-c:a', 'aac',
315
+ '-b:a', '128k',
316
+ '-movflags', '+faststart',
317
+ '-y', output_path
318
+ ])
319
+ else:
320
+ # 软件编码参数 - 使用ultrafast预设
321
+ base_command.extend([
322
+ '-c:v', 'libx264',
323
+ '-preset', 'ultrafast', # 最快预设
324
+ '-crf', '28', # 质量参数
325
+ '-tune', 'fastdecode', # 优化解码速度
326
+ '-x264opts', 'no-scenecut', # 禁用场景检测以加快速度
327
+ '-c:a', 'aac',
328
+ '-b:a', '128k',
329
+ '-movflags', '+faststart',
330
+ '-avoid_negative_ts', 'make_zero',
331
+ '-y', output_path
332
+ ])
333
+
334
+ elif operation == 'resize':
335
+ # 调整尺寸的编码参数
336
+ if encoder == 'h264_nvenc':
337
+ base_command.extend([
338
+ '-c:v', 'h264_nvenc',
339
+ '-preset', 'p1',
340
+ '-tune', 'ull',
341
+ '-cq', '28',
342
+ '-c:a', 'copy',
343
+ '-movflags', '+faststart',
344
+ '-y', output_path
345
+ ])
346
+ else:
347
+ base_command.extend([
348
+ '-c:v', 'libx264',
349
+ '-preset', 'ultrafast',
350
+ '-crf', '28',
351
+ '-tune', 'fastdecode',
352
+ '-x264opts', 'no-scenecut',
353
+ '-c:a', 'copy',
354
+ '-movflags', '+faststart',
355
+ '-y', output_path
356
+ ])
357
+
358
+ return base_command
359
+
360
  def ffmpeg_cut_video(input_path, start_time, duration, output_path):
361
+ """[优化] 快速的视频切割,使用硬件加速和ultrafast预设"""
362
+ command = build_ffmpeg_command(input_path, start_time, duration, output_path, 'cut')
 
 
 
 
363
  result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
364
  return result.returncode == 0 and os.path.exists(output_path)
365
 
366
  def ffmpeg_resize_video(input_path, output_path, target_ratio):
367
+ """[优化] 快速的比例调整,使用硬件加速和ultrafast预设"""
368
  if target_ratio == '9:16':
369
  filter_complex = "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black"
370
  else:
371
  filter_complex = "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2:black"
372
 
373
+ command = build_ffmpeg_command(input_path, 0, 0, output_path, 'resize')
374
+ # 在resize操作中插入滤镜
375
+ command.insert(-5, '-vf') # 在-y之前插入
376
+ command.insert(-4, filter_complex)
377
+
378
  result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
379
  return result.returncode == 0 and os.path.exists(output_path)
380
 
 
394
  list_file.write(f"file '{abs_path}'\n")
395
  list_file.close()
396
 
397
+ # 使用多线程进行合并
398
+ threads = get_optimal_threads()
399
+ command = ['ffmpeg', '-threads', str(threads), '-f', 'concat', '-safe', '0', '-i', list_file.name, '-c', 'copy', '-y', output_path]
400
  result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
401
  return result.returncode == 0 and os.path.exists(output_path)
402
  finally:
 
436
  return clips
437
 
438
  def process_videos_with_storage(video_files, clip_duration, num_output_videos, target_ratio):
439
+ """带储存功能的视频处理 [优化版:硬件加速 + 并行切割 + 批量更新 + 进度日志]"""
440
  if not video_files:
441
  return "❌ 请上传视频文件", None, "", ""
442
 
443
+ start_time = time.time()
444
  temp_dir = tempfile.mkdtemp()
445
 
446
  try:
447
  print(f"🔍 开始处理 {len(video_files)} 个视频文件...")
448
+ print(f"⚡ 硬件加速: {HARDWARE_ACCEL['encoder']}")
449
+ print(f"🔧 线程数: {get_optimal_threads()}")
450
  print(f"⏱️ 切片时长: {clip_duration} 秒 | 生成数量: {num_output_videos} 个 | 比例: {target_ratio}")
451
 
452
  all_clips = []
453
 
454
+ # 使用进程池进行并行处理(避免GIL限制)
455
+ print(f"🚀 启动并行切片({min(8, os.cpu_count() or 1)} 进程)...")
456
+ with concurrent.futures.ProcessPoolExecutor(max_workers=min(8, os.cpu_count() or 1)) as executor:
457
  future_to_video = {
458
  executor.submit(process_single_video, vf, clip_duration, temp_dir): vf
459
  for vf in video_files
 
471
  video_file = future_to_video[future]
472
  print(f"❌ 切片失败: {os.path.basename(video_file.name)} - {exc}")
473
 
 
474
  print(f"📊 所有视频切片完成,共生成 {len(all_clips)} 个片段")
475
 
476
  if not all_clips:
 
512
  else:
513
  print(f"❌ 比例调整失败: 第 {i+1} 个视频")
514
 
 
515
  if stored_files:
516
  update_storage_config()
517
  print(f"✅ 已统一更新储存配置,共保存 {len(stored_files)} 个视频文件")
 
519
  if not output_files:
520
  return "❌ 生成混剪视频失败", None, "", ""
521
 
 
522
  package_dir = tempfile.mkdtemp()
523
  timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
524
  zip_path = os.path.join(package_dir, f"混剪视频包_{target_ratio.replace(':', 'x')}_{timestamp}.zip")
 
531
  print(f" ➤ 已添加: {arcname}")
532
 
533
  readme = f"""# 混剪视频包
 
534
  ## 📊 生成信息
535
  - 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
536
  - 视频数量: {len(output_files)} 个
537
  - 视频比例: {target_ratio}
538
  - 切片时长: {clip_duration} 秒
539
+ - 硬件加速: {HARDWARE_ACCEL['encoder']}
540
  ## 📁 文件列表
541
  """
542
  for i, vf in enumerate(output_files, 1):
 
547
  ## 💾 储存信息
548
  所有视频已自动保存到本地储存空间:
549
  {', '.join(stored_files)}
 
550
  视频已按 {target_ratio} 比例优化,可直接发布。
551
  """
552
  zipf.writestr("README.txt", readme.encode('utf-8'))
 
554
  total_size = os.path.getsize(zip_path) / (1024 * 1024)
555
  platform_info = "📱 短视频平台" if target_ratio == '9:16' else "🖥️ 长视频平台"
556
 
557
+ end_time = time.time()
558
  elapsed = end_time - start_time
559
  print(f"🎉 混剪完成!总耗时: {elapsed:.1f} 秒")
560
  print(f"📥 下载包大小: {total_size:.1f}MB")
561
  print(f"📁 已保存文件: {len(stored_files)} 个")
562
 
563
  success_msg = f"""✅ 混剪完成并已储存!
 
564
  📊 **生成统计:**
565
  • 🎬 混剪视频: {len(output_files)} 个
566
  • 📐 视频比例: {target_ratio}
567
  • 🎯 适合平台: {platform_info}
568
  • 📦 下载包大小: {total_size:.1f}MB
569
+ • ⚡ 硬件加速: {HARDWARE_ACCEL['encoder']}
570
+ • 🔧 处理线程: {get_optimal_threads()}
571
+ • ⏱️ 处理耗时: {elapsed:.1f} 秒
572
  💾 **自动储存:**
573
  • 📁 储存位置: ~/video_storage/
574
  • 🔥 已保存文件: {len(stored_files)} 个
575
  • ✅ 永久保存,不会丢失
 
576
  ⬇️ **立即下载:**
577
  点击下方按钮下载打包文件
578
  """
579
 
580
  details = f"""🎬 **视频详情:**
 
581
  """
582
  for i, vf in enumerate(output_files, 1):
583
  size_mb = os.path.getsize(vf) / (1024 * 1024)
 
591
 
592
  config, video_list = get_storage_info()
593
  storage_info = f"""📊 **储存空间状态:**
 
594
  💾 总计: {config['total_videos']} 个视频
595
  📦 总大小: {config['total_size_mb']}MB
596
  📁 位置: ~/video_storage/
 
597
  📋 **最新文件:**
598
  """
599
 
 
615
  config, video_list = get_storage_info()
616
 
617
  storage_display = f"""💾 **储存空间概览**
 
618
  📊 **统计信息:**
619
  • 总视频数量: {config['total_videos']} 个
620
  • 总占用空间: {config['total_size_mb']}MB
621
  • 储存位置: ~/video_storage/
622
+ • 硬件加速: {HARDWARE_ACCEL['encoder']}
623
  📁 **文件列表:**
624
  """
625
 
 
665
  def main():
666
  with gr.Blocks(title="FFmpeg混剪+储存+下载管理", theme=gr.themes.Soft()) as demo:
667
 
668
+ gr.HTML(f"""
669
  <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; color: white; margin-bottom: 20px;">
670
  <h1>🎬 FFmpeg 混剪工具 + 储存管理 + 一键下载</h1>
671
  <p style="margin: 10px 0 0 0;">长视频切片 → 智能混剪 → 比例调整 → 自动储存 → 一键下载</p>
672
+ <p style="margin: 5px 0 0 0; font-size: 14px; opacity: 0.9;">⚡ 硬件加速: {HARDWARE_ACCEL['encoder']} | 🔧 线程数: {get_optimal_threads()}</p>
673
  </div>
674
  """)
675
 
 
789
  outputs=[storage_display, file_selector, file_selector_download]
790
  )
791
 
792
+ gr.Markdown(f"""
793
  ---
794
  ### 📖 功能说明
795
 
 
798
  - 📐 支持9:16/16:9比例调整
799
  - 📦 打包下载所有生成视频
800
  - 💾 **自动储存到本地目录**
801
+ - 🚀 **硬件加速: {HARDWARE_ACCEL['encoder']}**
802
+ - 🔧 **多线程处理: {get_optimal_threads()} 线程**
803
 
804
  **💾 储存管理功能:**
805
  - 📁 所有生成视频自动保存到 `~/video_storage/`
 
824
  - **分享协作**: 打包分享给团队成员
825
  - **存档管理**: 定期下载备份到云盘
826
 
827
+ **⚡ 性能优化:**
828
+ - **硬件加速**: 自动检测并使用GPU加速
829
+ - **多线程处理**: 充分利用多核CPU
830
+ - **快速预设**: 使用ultrafast预设提升速度
831
+ - **并行处理**: 多个视频同时处理
832
+
833
  **⚠️ 注意事项:**
834
  - 下载文件为ZIP格式,需要解压使用
835
  - 一键下载包含储存空间中所有视频文件