Ryanus commited on
Commit
41cc9f0
·
verified ·
1 Parent(s): dc323de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -33
app.py CHANGED
@@ -4,7 +4,6 @@ import tempfile
4
  import random
5
  import subprocess
6
  import shutil
7
- from datetime import datetime
8
 
9
  def ffmpeg_cut_video(input_path, start_time, duration, output_path):
10
  command = [
@@ -23,7 +22,6 @@ def concat_videos_ffmpeg(file_list, output_path):
23
  list_file = tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt')
24
  try:
25
  for f in file_list:
26
- # 安全写入文件名,避免单引号破坏格式
27
  list_file.write("file '{}'\n".format(f.replace("'", r"'\''")))
28
  list_file.close()
29
 
@@ -41,17 +39,12 @@ def concat_videos_ffmpeg(file_list, output_path):
41
  finally:
42
  os.unlink(list_file.name)
43
 
44
- def process_videos(video_files, clip_duration=2, num_output_videos=3):
45
- if not video_files or len(video_files) == 0:
46
- return "❌ 请上传至少一个视频文件", []
47
-
48
  temp_dir = tempfile.mkdtemp()
49
- all_clips = []
50
-
51
  try:
52
  for idx, video_file in enumerate(video_files):
53
  video_path = video_file.name
54
- # 获取视频时长
55
  cmd_duration = [
56
  'ffprobe', '-v', 'error',
57
  '-show_entries', 'format=duration',
@@ -67,48 +60,63 @@ def process_videos(video_files, clip_duration=2, num_output_videos=3):
67
  clip_path = os.path.join(temp_dir, f"clip_{idx}_{count}.mp4")
68
  ok = ffmpeg_cut_video(video_path, start, duration, clip_path)
69
  if not ok:
70
- return f"视频剪辑失败: {video_path}", []
71
- all_clips.append(clip_path)
72
  start += duration
73
  count += 1
 
 
 
 
74
 
75
- random.shuffle(all_clips)
76
-
77
- clips_per_video = max(1, len(all_clips) // num_output_videos)
78
- output_files = []
79
-
 
80
  for i in range(num_output_videos):
81
  start_idx = i * clips_per_video
82
- end_idx = len(all_clips) if i == num_output_videos - 1 else (start_idx + clips_per_video)
83
- selected_clips = all_clips[start_idx:end_idx]
84
- output_path = os.path.join(temp_dir, f"mixed_video_{i + 1}.mp4")
85
  ok = concat_videos_ffmpeg(selected_clips, output_path)
86
  if not ok:
87
- return "视频合并失败", []
88
  output_files.append(output_path)
 
 
 
 
89
 
90
- return f"成功生成 {len(output_files)} 个混剪视频", output_files
91
-
 
 
 
 
 
 
 
92
  except Exception as e:
93
- return f"❌ 处理异常: {str(e)}", []
94
 
95
  def main():
96
  with gr.Blocks() as demo:
97
- gr.Markdown("## FFmpeg 自动剪辑混剪视频 (无 API,纯本地 ffmpeg)")
98
- video_input = gr.File(file_types=[".mp4", ".mov", ".avi", ".mkv"], file_count="multiple", label="上传视频文件")
99
- clip_duration = gr.Number(value=2, label="剪辑片段时长 (秒)", minimum=1, maximum=30)
100
- num_output = gr.Number(value=3, label="输出混剪视频数量", minimum=1, maximum=10)
101
- btn = gr.Button("开始剪辑")
102
 
103
- status = gr.Textbox(label="剪辑状态", interactive=False, lines=5)
104
- outputs = gr.File(file_count="multiple", label="下载混剪视频")
 
 
105
 
106
- def process(video_files, clip_duration, num_output):
107
- return process_videos(video_files, clip_duration, num_output)
108
 
109
- btn.click(process, inputs=[video_input, clip_duration, num_output], outputs=[status, outputs])
110
 
111
  demo.launch()
112
 
113
  if __name__ == "__main__":
114
  main()
 
 
4
  import random
5
  import subprocess
6
  import shutil
 
7
 
8
  def ffmpeg_cut_video(input_path, start_time, duration, output_path):
9
  command = [
 
22
  list_file = tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.txt')
23
  try:
24
  for f in file_list:
 
25
  list_file.write("file '{}'\n".format(f.replace("'", r"'\''")))
26
  list_file.close()
27
 
 
39
  finally:
40
  os.unlink(list_file.name)
41
 
42
+ def extract_clips_from_videos(video_files, clip_duration):
43
+ clips = []
 
 
44
  temp_dir = tempfile.mkdtemp()
 
 
45
  try:
46
  for idx, video_file in enumerate(video_files):
47
  video_path = video_file.name
 
48
  cmd_duration = [
49
  'ffprobe', '-v', 'error',
50
  '-show_entries', 'format=duration',
 
60
  clip_path = os.path.join(temp_dir, f"clip_{idx}_{count}.mp4")
61
  ok = ffmpeg_cut_video(video_path, start, duration, clip_path)
62
  if not ok:
63
+ raise RuntimeError(f"视频剪辑失败: {video_path}")
64
+ clips.append(clip_path)
65
  start += duration
66
  count += 1
67
+ return clips, temp_dir
68
+ except Exception:
69
+ shutil.rmtree(temp_dir, ignore_errors=True)
70
+ raise
71
 
72
+ def generate_mixed_videos(clips, num_output_videos):
73
+ temp_dir = tempfile.mkdtemp()
74
+ random.shuffle(clips)
75
+ clips_per_video = max(1, len(clips) // num_output_videos)
76
+ output_files = []
77
+ try:
78
  for i in range(num_output_videos):
79
  start_idx = i * clips_per_video
80
+ end_idx = len(clips) if i == num_output_videos - 1 else (start_idx + clips_per_video)
81
+ selected_clips = clips[start_idx:end_idx]
82
+ output_path = os.path.join(temp_dir, f"mixed_video_{i+1}.mp4")
83
  ok = concat_videos_ffmpeg(selected_clips, output_path)
84
  if not ok:
85
+ raise RuntimeError("视频合并失败")
86
  output_files.append(output_path)
87
+ return output_files, temp_dir
88
+ except Exception:
89
+ shutil.rmtree(temp_dir, ignore_errors=True)
90
+ raise
91
 
92
+ def process_auto_mixing(video_files, clip_duration, num_output_videos):
93
+ if not video_files or len(video_files) == 0:
94
+ return "❌ 请上传至少一个视频文件", []
95
+ try:
96
+ clips, clips_temp_dir = extract_clips_from_videos(video_files, clip_duration)
97
+ output_files, output_temp_dir = generate_mixed_videos(clips, num_output_videos)
98
+ # 清理临时切割片段目录
99
+ shutil.rmtree(clips_temp_dir, ignore_errors=True)
100
+ return f"成功生成 {len(output_files)} 个自动混剪视频", output_files
101
  except Exception as e:
102
+ return f"❌ 处理失败: {str(e)}", []
103
 
104
  def main():
105
  with gr.Blocks() as demo:
106
+ gr.Markdown("# FFmpeg 自动剪辑 + 长视频自动切片 + 自动混剪")
 
 
 
 
107
 
108
+ video_input = gr.File(label="上传视频文件", file_types=[".mp4", ".mov", ".avi"], file_count="multiple")
109
+ clip_duration = gr.Number(value=8, label="单个剪辑片段时长(秒)", minimum=1, maximum=60)
110
+ num_output = gr.Number(value=3, label="生成混剪视频数量", minimum=1, maximum=10)
111
+ btn = gr.Button("开始自动剪辑并混剪")
112
 
113
+ status_box = gr.Textbox(label="处理状态", interactive=False, lines=4)
114
+ output_files = gr.File(label="下载混剪视频文件", file_count="multiple")
115
 
116
+ btn.click(process_auto_mixing, inputs=[video_input, clip_duration, num_output], outputs=[status_box, output_files])
117
 
118
  demo.launch()
119
 
120
  if __name__ == "__main__":
121
  main()
122
+