Tim13ekd commited on
Commit
36bfe7e
·
verified ·
1 Parent(s): a99862b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -28
app.py CHANGED
@@ -6,45 +6,71 @@ import uuid
6
 
7
  allowed_medias = [".png", ".jpg", ".jpeg", ".bmp", ".gif", ".tiff"]
8
 
9
- def generate_slideshow(images, duration):
 
 
 
10
  if not images:
11
  return None, "❌ Keine Bilder ausgewählt"
12
 
13
  temp_dir = tempfile.mkdtemp()
14
- filelist_path = Path(temp_dir) / "filelist.txt"
15
- output_file = Path(temp_dir) / f"slideshow_{uuid.uuid4().hex}.mp4"
16
-
17
- # FFmpeg Filelist
18
- with open(filelist_path, "w") as f:
19
- for img in images:
20
- f.write(f"file '{img.name}'\n")
21
- f.write(f"duration {duration}\n")
22
- f.write(f"file '{images[-1].name}'\n")
23
-
24
- cmd = [
25
- "ffmpeg",
26
- "-y",
27
- "-f", "concat",
28
- "-safe", "0",
29
- "-i", str(filelist_path),
30
- "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2,fps=25,format=yuv420p",
31
- str(output_file)
32
- ]
33
-
34
- subprocess.run(cmd, check=True)
35
-
36
- if output_file.exists():
37
- return str(output_file), f"✅ Slideshow Video erstellt ({len(images)} Bilder, {duration}s pro Bild)"
38
  else:
39
- return None, "❌ Video konnte nicht erstellt werden"
 
 
 
 
 
 
 
 
 
 
 
40
 
 
 
 
 
 
 
41
  with gr.Blocks() as demo:
42
- img_input = gr.File(label="Bilder auswählen (mehrere)", type="file", file_types=None)
 
 
 
 
 
43
  duration_input = gr.Number(value=3, label="Dauer pro Bild in Sekunden", precision=1)
44
  out_video = gr.Video(interactive=False, label="Generiertes Video")
45
  status = gr.Textbox(interactive=False, label="Status")
46
 
47
  btn = gr.Button("Video erstellen")
48
- btn.click(fn=generate_slideshow, inputs=[img_input, duration_input], outputs=[out_video, status])
 
 
 
 
49
 
50
  demo.launch()
 
6
 
7
  allowed_medias = [".png", ".jpg", ".jpeg", ".bmp", ".gif", ".tiff"]
8
 
9
+ def generate_slideshow_with_fade(images, duration):
10
+ """
11
+ Erzeugt ein Video aus mehreren Bildern mit Fade-Übergang zwischen allen Bildern.
12
+ """
13
  if not images:
14
  return None, "❌ Keine Bilder ausgewählt"
15
 
16
  temp_dir = tempfile.mkdtemp()
17
+ clips = []
18
+
19
+ # Schritt 1: Einzelne Clips erstellen
20
+ for idx, img_path in enumerate(images):
21
+ clip_file = Path(temp_dir) / f"clip_{idx}.mp4"
22
+ cmd = [
23
+ "ffmpeg",
24
+ "-y",
25
+ "-loop", "1",
26
+ "-i", str(img_path),
27
+ "-t", str(duration),
28
+ "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2,fps=25,format=yuv420p",
29
+ str(clip_file)
30
+ ]
31
+ subprocess.run(cmd, check=True)
32
+ clips.append(clip_file)
33
+
34
+ # Schritt 2: Übergänge mit xfade
35
+ if len(clips) == 1:
36
+ # Nur ein Clip, kein Übergang
37
+ return str(clips[0]), f"✅ Video erstellt ({len(clips)} Bild)"
 
 
 
38
  else:
39
+ # Dynamische Filterchain
40
+ inputs = ""
41
+ filter_chain = ""
42
+ for i, clip in enumerate(clips):
43
+ inputs += f" -i {clip}"
44
+ for i in range(len(clips)-1):
45
+ filter_chain += f"[{i}:v][{i+1}:v]xfade=transition=fade:duration=1:offset={duration*i}[v{i+1}];"
46
+ final_label = f"[v{len(clips)-1}]"
47
+
48
+ output_file = Path(temp_dir) / f"slideshow_{uuid.uuid4().hex}.mp4"
49
+ cmd = f"ffmpeg -y {inputs} -filter_complex \"{filter_chain[:-1]}\" -map {final_label} {output_file}"
50
+ subprocess.run(cmd, shell=True, check=True)
51
 
52
+ if output_file.exists():
53
+ return str(output_file), f"✅ Slideshow Video erstellt mit Fade ({len(clips)} Bilder)"
54
+ else:
55
+ return None, "❌ Video konnte nicht erstellt werden"
56
+
57
+ # Gradio UI
58
  with gr.Blocks() as demo:
59
+ gr.Markdown("# Slideshow Video Generator mit Fade-Übergängen")
60
+
61
+ img_input = gr.Files(
62
+ label="Bilder auswählen (mehrere)",
63
+ file_types=allowed_medias
64
+ )
65
  duration_input = gr.Number(value=3, label="Dauer pro Bild in Sekunden", precision=1)
66
  out_video = gr.Video(interactive=False, label="Generiertes Video")
67
  status = gr.Textbox(interactive=False, label="Status")
68
 
69
  btn = gr.Button("Video erstellen")
70
+ btn.click(
71
+ fn=generate_slideshow_with_fade,
72
+ inputs=[img_input, duration_input],
73
+ outputs=[out_video, status]
74
+ )
75
 
76
  demo.launch()