Ryanus commited on
Commit
374a53a
·
verified ·
1 Parent(s): ba492f5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +172 -56
app.py CHANGED
@@ -15,6 +15,30 @@ def ffmpeg_cut_video(input_path, start_time, duration, output_path):
15
  process = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
16
  return process.returncode == 0
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  def concat_videos_ffmpeg(file_list, output_path):
19
  list_file = tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt')
20
  try:
@@ -60,7 +84,7 @@ def extract_clips_from_videos(video_files, clip_duration):
60
  shutil.rmtree(temp_dir, ignore_errors=True)
61
  raise
62
 
63
- def generate_mixed_videos(clips, num_output_videos):
64
  temp_dir = tempfile.mkdtemp()
65
  random.shuffle(clips)
66
  clips_per_video = max(1, len(clips) // num_output_videos)
@@ -72,25 +96,31 @@ def generate_mixed_videos(clips, num_output_videos):
72
  end_idx = len(clips) if i == num_output_videos - 1 else (start_idx + clips_per_video)
73
  selected_clips = clips[start_idx:end_idx]
74
 
75
- # 为每个视频生成更有意义的文件名
76
- timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
77
- output_path = os.path.join(temp_dir, f"混剪视频_{i+1}_{timestamp}.mp4")
78
-
79
- ok = concat_videos_ffmpeg(selected_clips, output_path)
80
  if not ok:
81
  raise RuntimeError("视频合并失败")
 
 
 
 
 
 
 
 
82
  output_files.append(output_path)
 
83
  return output_files, temp_dir
84
  except Exception:
85
  shutil.rmtree(temp_dir, ignore_errors=True)
86
  raise
87
 
88
- def create_video_package(output_files, original_file_names):
89
  """将生成的视频文件打包成zip,并创建说明文件"""
90
 
91
- # 创建临时目录用于打包
92
  package_dir = tempfile.mkdtemp()
93
- zip_path = os.path.join(package_dir, f"混剪视频包_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip")
94
 
95
  try:
96
  with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
@@ -105,8 +135,26 @@ def create_video_package(output_files, original_file_names):
105
  ## 📊 生成信息
106
  - 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
107
  - 视频数量: {len(output_files)} 个
 
108
  - 源文件: {', '.join(original_file_names)}
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  ## 📁 文件列表
111
  """
112
 
@@ -115,18 +163,39 @@ def create_video_package(output_files, original_file_names):
115
  readme_content += f"- 混剪视频_{i}.mp4 ({file_size:.1f}MB)\n"
116
 
117
  readme_content += f"""
118
- ## 🎬 使用建议
119
- - 适合发布到抖音、快手、小红书等短视频平台
120
- - 建议添加背景音乐以提升观看体验
121
- - 可以进一步编辑添加字幕、特效等
 
122
 
123
- ## 技术信息
124
- - 制作工具: FFmpeg 自动剪辑
125
- - 处理方式: 智能切片 + 随机重组
126
- - 视频编码: H.264/AAC
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  ---
129
- 感谢使用 FFmpeg 自动混剪工具!
130
  """
131
 
132
  # 将说明文件添加到zip
@@ -138,7 +207,7 @@ def create_video_package(output_files, original_file_names):
138
  shutil.rmtree(package_dir, ignore_errors=True)
139
  raise e
140
 
141
- def process_and_package(video_files, clip_duration, num_output_videos):
142
  if not video_files or len(video_files) == 0:
143
  return "❌ 请上传至少一个视频文件", None, ""
144
 
@@ -148,27 +217,37 @@ def process_and_package(video_files, clip_duration, num_output_videos):
148
 
149
  # 1. 视频处理
150
  clips, clips_temp_dir = extract_clips_from_videos(video_files, clip_duration)
151
- output_files, output_temp_dir = generate_mixed_videos(clips, num_output_videos)
152
 
153
  # 清理切片临时目录
154
  shutil.rmtree(clips_temp_dir, ignore_errors=True)
155
 
156
  # 2. 打包所有视频
157
- zip_file_path = create_video_package(output_files, original_names)
158
 
159
  # 计算总大小
160
  total_size = os.path.getsize(zip_file_path) / (1024 * 1024) # MB
161
 
 
 
 
 
 
 
 
162
  status_msg = f"""✅ 处理完成!
163
 
164
  📊 **生成统计:**
165
  • 混剪视频数量: {len(output_files)} 个
 
 
166
  • 打包文件大小: {total_size:.1f}MB
167
  • 处理时间: {datetime.now().strftime('%H:%M:%S')}
168
 
169
  📦 **打包内容:**
170
- • {len(output_files)} 个混剪视频文件
171
- • 1 个使用说明文档
 
172
  • 所有文件已压缩打包
173
 
174
  💾 **下载说明:**
@@ -176,7 +255,7 @@ def process_and_package(video_files, clip_duration, num_output_videos):
176
  """
177
 
178
  # 生成详细信息
179
- details = f"""🎬 **视频详情:**
180
 
181
  """
182
  for i, video_file in enumerate(output_files, 1):
@@ -185,24 +264,43 @@ def process_and_package(video_files, clip_duration, num_output_videos):
185
 
186
  details += f"""
187
  🔧 **技术参数:**
 
188
  • 切片时长: {clip_duration}秒
189
- 随机混剪算法: 智能重组
190
  • 视频编码: H.264
191
  • 音频编码: AAC
 
192
 
193
- 📱 **发布建议:**
194
- 适合短视频平台发布
195
- 建议添加背景音乐
196
- 可进一步编辑添加特效
197
- 注意平台尺寸要求
 
 
198
 
199
- 💡 **后续处理:**
200
- 解压后即可使用
201
- 支持主流播放器播放
202
- 可用视频编辑软件进一步处理
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  """
204
 
205
- # 清理视频临时目录(但保留zip文件)
206
  shutil.rmtree(output_temp_dir, ignore_errors=True)
207
 
208
  return status_msg, zip_file_path, details
@@ -212,14 +310,14 @@ def process_and_package(video_files, clip_duration, num_output_videos):
212
 
213
  def main():
214
  with gr.Blocks(
215
- title="FFmpeg自动剪辑+打包下载",
216
  theme=gr.themes.Soft()
217
  ) as demo:
218
 
219
  gr.HTML("""
220
- <div style="text-align: center; padding: 20px; background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); border-radius: 10px; color: white; margin-bottom: 20px;">
221
- <h1>🎬 FFmpeg 自动剪辑 + 打包下载</h1>
222
- <p style="margin: 10px 0 0 0;">长视频自动切片 → 智能混剪 → 一键打包下载</p>
223
  </div>
224
  """)
225
 
@@ -246,6 +344,14 @@ def main():
246
  maximum=8
247
  )
248
 
 
 
 
 
 
 
 
 
249
  process_btn = gr.Button(
250
  "🎬 开始自动剪辑并打包",
251
  variant="primary",
@@ -255,7 +361,7 @@ def main():
255
  with gr.Column(scale=1):
256
  status_output = gr.Textbox(
257
  label="📊 处理状态",
258
- lines=10,
259
  interactive=False,
260
  show_copy_button=True
261
  )
@@ -270,14 +376,14 @@ def main():
270
  with gr.Column(scale=1):
271
  details_output = gr.Textbox(
272
  label="📝 详细信息",
273
- lines=15,
274
  interactive=False,
275
  show_copy_button=True
276
  )
277
 
278
  process_btn.click(
279
- fn=process_and_package,
280
- inputs=[video_input, clip_duration, num_output],
281
  outputs=[status_output, download_file, details_output]
282
  )
283
 
@@ -287,24 +393,34 @@ def main():
287
 
288
  **🎬 视频处理流程:**
289
  1. **上传视频** → 支持 MP4、MOV、AVI、MKV 格式
290
- 2. **自动切片**按指定时长将视频切成小段
291
- 3. **智能混剪**随机重组片段生成新视频
292
- 4. **自动打包**所有视频 + 说明文档打包成ZIP
293
- 5. **一键下载**保存到本地硬盘
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
 
295
  **💾 打包内容:**
296
- - ✅ 所有生成的混剪视频文件
297
  - ✅ 详细的使用说明文档
298
- - ✅ 技术参数和建议信息
 
299
  - ✅ 压缩打包,节省存储空间
300
 
301
- **🚀 优势特点:**
302
- - 🔥 **完全本地化** → 无需任何在线服务
303
- - ⚡ **批量处理** → 支持多视频同时处理
304
- - 🎯 **智能算法** → 随机重组避免重复
305
- - 📱 **适配平台** → 生成适合短视频平台的内容
306
- - 💾 **打包下载** → 一次下载全部文件
307
-
308
  **⚠️ 系统要求:**
309
  - 需要安装 FFmpeg 和 FFprobe
310
  - 建议使用稳定的网络连接
 
15
  process = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
16
  return process.returncode == 0
17
 
18
+ def ffmpeg_resize_video(input_path, output_path, target_ratio):
19
+ """调整视频比例"""
20
+ if target_ratio == '9:16':
21
+ # 竖屏:高度保持,宽度=高度*9/16,居中裁剪
22
+ scale_filter = "scale=-2:1920,crop=1080:1920"
23
+ elif target_ratio == '16:9':
24
+ # 横屏:宽度保持,高度=宽度*9/16,居中裁剪
25
+ scale_filter = "scale=1920:-2,crop=1920:1080"
26
+ else:
27
+ # 默认保持原比例
28
+ scale_filter = "scale=-2:-2"
29
+
30
+ command = [
31
+ 'ffmpeg',
32
+ '-i', input_path,
33
+ '-vf', scale_filter,
34
+ '-c:a', 'copy',
35
+ '-y',
36
+ output_path
37
+ ]
38
+
39
+ process = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
40
+ return process.returncode == 0
41
+
42
  def concat_videos_ffmpeg(file_list, output_path):
43
  list_file = tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt')
44
  try:
 
84
  shutil.rmtree(temp_dir, ignore_errors=True)
85
  raise
86
 
87
+ def generate_mixed_videos(clips, num_output_videos, target_ratio):
88
  temp_dir = tempfile.mkdtemp()
89
  random.shuffle(clips)
90
  clips_per_video = max(1, len(clips) // num_output_videos)
 
96
  end_idx = len(clips) if i == num_output_videos - 1 else (start_idx + clips_per_video)
97
  selected_clips = clips[start_idx:end_idx]
98
 
99
+ # 先合并片段
100
+ temp_video_path = os.path.join(temp_dir, f"temp_mixed_{i+1}.mp4")
101
+ ok = concat_videos_ffmpeg(selected_clips, temp_video_path)
 
 
102
  if not ok:
103
  raise RuntimeError("视频合并失败")
104
+
105
+ # 调整视频比例
106
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
107
+ output_path = os.path.join(temp_dir, f"混剪视频_{target_ratio.replace(':', 'x')}_{i+1}_{timestamp}.mp4")
108
+ ok = ffmpeg_resize_video(temp_video_path, output_path, target_ratio)
109
+ if not ok:
110
+ raise RuntimeError("视频比例调整失败")
111
+
112
  output_files.append(output_path)
113
+
114
  return output_files, temp_dir
115
  except Exception:
116
  shutil.rmtree(temp_dir, ignore_errors=True)
117
  raise
118
 
119
+ def create_video_package(output_files, original_file_names, target_ratio):
120
  """将生成的视频文件打包成zip,并创建说明文件"""
121
 
 
122
  package_dir = tempfile.mkdtemp()
123
+ zip_path = os.path.join(package_dir, f"混剪视频包_{target_ratio.replace(':', 'x')}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip")
124
 
125
  try:
126
  with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
 
135
  ## 📊 生成信息
136
  - 生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
137
  - 视频数量: {len(output_files)} 个
138
+ - 视频比例: {target_ratio}
139
  - 源文件: {', '.join(original_file_names)}
140
 
141
+ ## 📱 比例说明
142
+ """
143
+
144
+ if target_ratio == '9:16':
145
+ readme_content += """- 🔥 9:16 竖屏格式
146
+ - 📱 适合平台:抖音、快手、小红书、Instagram Stories
147
+ - 🎯 最佳用途:短视频、Vlog、才艺展示
148
+ - 📐 分辨率:1080x1920 (推荐)
149
+ """
150
+ else:
151
+ readme_content += """- 🖥️ 16:9 横屏格式
152
+ - 📺 适合平台:YouTube、B站、腾讯视频、爱奇艺
153
+ - 🎯 最佳用途:长视频、教程、游戏、影视解说
154
+ - 📐 分辨率:1920x1080 (推荐)
155
+ """
156
+
157
+ readme_content += f"""
158
  ## 📁 文件列表
159
  """
160
 
 
163
  readme_content += f"- 混剪视频_{i}.mp4 ({file_size:.1f}MB)\n"
164
 
165
  readme_content += f"""
166
+ ## 🎬 制作技术
167
+ - 切片算法: FFmpeg 自动分割
168
+ - 混剪逻辑: 智能随机重组
169
+ - 比例调整: {target_ratio} 专业适配
170
+ - 视频编码: H.264/AAC 高质���
171
 
172
+ ## 📱 发布建议
173
+ """
174
+
175
+ if target_ratio == '9:16':
176
+ readme_content += """- 添加动感背景音乐
177
+ - 考虑添加字幕提升观看体验
178
+ - 开头3秒要有吸引力
179
+ - 时长控制在15-60秒最佳
180
+ - 发布时间:晚上7-9点黄金时段
181
+ """
182
+ else:
183
+ readme_content += """- 制作精美封面图
184
+ - 添加详细标题和描述
185
+ - 考虑制作系列内容
186
+ - 时长可以3-15分钟
187
+ - 注意SEO关键词优化
188
+ """
189
+
190
+ readme_content += """
191
+ ## 💡 后续处理
192
+ - 可用剪映、PR等软件进一步编辑
193
+ - 建议添加个人水印
194
+ - 支持再次调整分辨率
195
+ - 可添加转场特效和滤镜
196
 
197
  ---
198
+ 🎬 感谢使用 FFmpeg 自动混剪工具!
199
  """
200
 
201
  # 将说明文件添加到zip
 
207
  shutil.rmtree(package_dir, ignore_errors=True)
208
  raise e
209
 
210
+ def process_and_package_with_ratio(video_files, clip_duration, num_output_videos, target_ratio):
211
  if not video_files or len(video_files) == 0:
212
  return "❌ 请上传至少一个视频文件", None, ""
213
 
 
217
 
218
  # 1. 视频处理
219
  clips, clips_temp_dir = extract_clips_from_videos(video_files, clip_duration)
220
+ output_files, output_temp_dir = generate_mixed_videos(clips, num_output_videos, target_ratio)
221
 
222
  # 清理切片临时目录
223
  shutil.rmtree(clips_temp_dir, ignore_errors=True)
224
 
225
  # 2. 打包所有视频
226
+ zip_file_path = create_video_package(output_files, original_names, target_ratio)
227
 
228
  # 计算总大小
229
  total_size = os.path.getsize(zip_file_path) / (1024 * 1024) # MB
230
 
231
+ # 平台信息
232
+ platform_info = ""
233
+ if target_ratio == '9:16':
234
+ platform_info = "📱 抖音、快手、小红书等短视频平台"
235
+ else:
236
+ platform_info = "🖥️ YouTube、B站等长视频平台"
237
+
238
  status_msg = f"""✅ 处理完成!
239
 
240
  📊 **生成统计:**
241
  • 混剪视频数量: {len(output_files)} 个
242
+ • 视频比例: {target_ratio}
243
+ • 适合平台: {platform_info}
244
  • 打包文件大小: {total_size:.1f}MB
245
  • 处理时间: {datetime.now().strftime('%H:%M:%S')}
246
 
247
  📦 **打包内容:**
248
+ • {len(output_files)} 个 {target_ratio} 比例混剪视频
249
+ • 1 个详细使用说明文档
250
+ • 平台发布建议和技术参数
251
  • 所有文件已压缩打包
252
 
253
  💾 **下载说明:**
 
255
  """
256
 
257
  # 生成详细信息
258
+ details = f"""🎬 **视频详情 ({target_ratio}):**
259
 
260
  """
261
  for i, video_file in enumerate(output_files, 1):
 
264
 
265
  details += f"""
266
  🔧 **技术参数:**
267
+ • 视频比例: {target_ratio}
268
  • 切片时长: {clip_duration}秒
269
+ 随机混剪: 智能重组算法
270
  • 视频编码: H.264
271
  • 音频编码: AAC
272
+ """
273
 
274
+ if target_ratio == '9:16':
275
+ details += """
276
+ 📱 **竖屏优势:**
277
+ 符合移动端观看习惯
278
+ 抖音算法友好
279
+ • 全屏沉浸式体验
280
+ • 适合碎片化观看
281
 
282
+ 🎯 **发布建议:**
283
+ 开头3秒要抓眼球
284
+ 添加热门背景音乐
285
+ 考虑添加字幕
286
+ • 时长15-60秒最佳
287
+ """
288
+ else:
289
+ details += """
290
+ 🖥️ **横屏优势:**
291
+ • 传统影视观看体验
292
+ • 适合详细内容展示
293
+ • YouTube推荐算法友好
294
+ • 便于添加复杂字幕
295
+
296
+ 🎯 **发布建议:**
297
+ • 制作吸引人的封面
298
+ • 详细标题和描述
299
+ • 3-15分钟时长合适
300
+ • SEO关键词优化
301
  """
302
 
303
+ # 清理视频临时目录
304
  shutil.rmtree(output_temp_dir, ignore_errors=True)
305
 
306
  return status_msg, zip_file_path, details
 
310
 
311
  def main():
312
  with gr.Blocks(
313
+ title="FFmpeg自动剪辑+比例调整+打包下载",
314
  theme=gr.themes.Soft()
315
  ) as demo:
316
 
317
  gr.HTML("""
318
+ <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; color: white; margin-bottom: 20px;">
319
+ <h1>🎬 FFmpeg 自动剪辑 + 比例调整 + 打包下载</h1>
320
+ <p style="margin: 10px 0 0 0;">长视频自动切片 → 智能混剪 → 比例调整 → 一键打包下载</p>
321
  </div>
322
  """)
323
 
 
344
  maximum=8
345
  )
346
 
347
+ # 新增比例选择
348
+ ratio_selection = gr.Radio(
349
+ choices=["9:16", "16:9"],
350
+ value="9:16",
351
+ label="📐 选择视频比例",
352
+ info="9:16适合抖音快手,16:9适合YouTube B站"
353
+ )
354
+
355
  process_btn = gr.Button(
356
  "🎬 开始自动剪辑并打包",
357
  variant="primary",
 
361
  with gr.Column(scale=1):
362
  status_output = gr.Textbox(
363
  label="📊 处理状态",
364
+ lines=12,
365
  interactive=False,
366
  show_copy_button=True
367
  )
 
376
  with gr.Column(scale=1):
377
  details_output = gr.Textbox(
378
  label="📝 详细信息",
379
+ lines=18,
380
  interactive=False,
381
  show_copy_button=True
382
  )
383
 
384
  process_btn.click(
385
+ fn=process_and_package_with_ratio,
386
+ inputs=[video_input, clip_duration, num_output, ratio_selection],
387
  outputs=[status_output, download_file, details_output]
388
  )
389
 
 
393
 
394
  **🎬 视频处理流程:**
395
  1. **上传视频** → 支持 MP4、MOV、AVI、MKV 格式
396
+ 2. **设置参数**切片时长、输出数量、视频比例
397
+ 3. **自动切片**按指定时长将视频切成小段
398
+ 4. **智能混剪**随机重组片段生成新视频
399
+ 5. **比例调整**自动适配选择的目标比例
400
+ 6. **自动打包** → 所有视频 + 说明文档打包成ZIP
401
+ 7. **一键下载** → 保存到本地硬盘
402
+
403
+ **📐 比例选择指南:**
404
+
405
+ **🔥 9:16 竖屏 (推荐短视频)**
406
+ - 📱 **适合平台:** 抖音、快手、小红书、Instagram Stories
407
+ - 🎯 **内容类型:** 短视频、Vlog、才艺展示、产品介绍
408
+ - ⏱️ **最佳时长:** 15-60秒
409
+ - 🎵 **建议配乐:** 动感节拍强的背景音乐
410
+
411
+ **🖥️ 16:9 横屏 (推荐长视频)**
412
+ - 📺 **适合平台:** YouTube、B站、腾讯视频、爱奇艺
413
+ - 🎯 **内容类型:** 教程、游戏、影视解说、直播回放
414
+ - ⏱️ **最佳时长:** 3-15分钟
415
+ - 🖼️ **建议优化:** 精美封面、详细描述
416
 
417
  **💾 打包内容:**
418
+ - ✅ 所有生成的混剪视频文件(指定比例)
419
  - ✅ 详细的使用说明文档
420
+ - ✅ 平台发布建议和优化技巧
421
+ - ✅ 技术参数和后续处理指南
422
  - ✅ 压缩打包,节省存储空间
423
 
 
 
 
 
 
 
 
424
  **⚠️ 系统要求:**
425
  - 需要安装 FFmpeg 和 FFprobe
426
  - 建议使用稳定的网络连接