Tim13ekd commited on
Commit
ea1c088
·
verified ·
1 Parent(s): e5b621e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +36 -17
app.py CHANGED
@@ -3,28 +3,41 @@ import subprocess
3
  import tempfile
4
  from pathlib import Path
5
  import uuid
6
- import shutil
7
 
8
  allowed_medias = [".png", ".jpg", ".jpeg", ".bmp", ".gif", ".tiff"]
9
 
10
- def execute_ffmpeg_image_to_video(image_file):
11
- if image_file is None:
12
- return None, "❌ Keine Datei ausgewählt"
 
 
 
 
13
 
14
- # Gradio liefert Upload-Pfad
15
- image_path = Path(image_file.name) if hasattr(image_file, "name") else Path(image_file)
16
-
17
- # Erstelle temporäres Verzeichnis
18
  temp_dir = tempfile.mkdtemp()
19
- output_file = Path(temp_dir) / f"output_{uuid.uuid4().hex}.mp4"
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  cmd = [
22
  "ffmpeg",
23
  "-y",
24
- "-loop", "1",
25
- "-i", str(image_path),
 
26
  "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2,fps=25,format=yuv420p",
27
- "-t", "5",
28
  str(output_file)
29
  ]
30
 
@@ -33,19 +46,25 @@ def execute_ffmpeg_image_to_video(image_file):
33
  except subprocess.CalledProcessError as e:
34
  return None, f"❌ FFmpeg Fehler:\n{e.stderr}"
35
 
36
- # Gradio benötigt einen String-Pfad oder URL
37
  if output_file.exists():
38
- return str(output_file), "✅ Video erfolgreich erstellt"
39
  else:
40
  return None, "❌ Video konnte nicht erstellt werden"
41
 
42
  # Gradio UI
43
  with gr.Blocks() as demo:
44
- gr.Markdown("# Bild Video Konverter")
45
- img_input = gr.File(file_types=allowed_medias, label="Bild auswählen")
 
 
46
  out_video = gr.Video(interactive=False, label="Generiertes Video")
47
  status = gr.Textbox(interactive=False, label="Status")
 
48
  btn = gr.Button("Video erstellen")
49
- btn.click(fn=execute_ffmpeg_image_to_video, inputs=[img_input], outputs=[out_video, status])
 
 
 
 
50
 
51
  demo.launch()
 
3
  import tempfile
4
  from pathlib import Path
5
  import uuid
 
6
 
7
  allowed_medias = [".png", ".jpg", ".jpeg", ".bmp", ".gif", ".tiff"]
8
 
9
+ def generate_slideshow(images, duration):
10
+ """
11
+ Erzeugt ein Video aus mehreren Bildern in einer frei wählbaren Reihenfolge.
12
+ Dauer: Sekunden pro Bild
13
+ """
14
+ if not images:
15
+ return None, "❌ Keine Bilder ausgewählt"
16
 
17
+ # Temporäres Verzeichnis
 
 
 
18
  temp_dir = tempfile.mkdtemp()
19
+ filelist_path = Path(temp_dir) / "filelist.txt"
20
+ output_file = Path(temp_dir) / f"slideshow_{uuid.uuid4().hex}.mp4"
21
+
22
+ # FFmpeg braucht ein Filelist-Format:
23
+ # file 'path/to/image'
24
+ # duration 5
25
+ with open(filelist_path, "w") as f:
26
+ for img in images:
27
+ img_path = Path(img.name) if hasattr(img, "name") else Path(img)
28
+ # Breite/Höhe auf gerade Werte skalieren
29
+ f.write(f"file '{img_path}'\n")
30
+ f.write(f"duration {duration}\n")
31
+ # FFmpeg benötigt letztes Bild nochmal, um das Ende korrekt zu machen
32
+ f.write(f"file '{Path(images[-1].name if hasattr(images[-1], 'name') else images[-1])}'\n")
33
 
34
  cmd = [
35
  "ffmpeg",
36
  "-y",
37
+ "-f", "concat",
38
+ "-safe", "0",
39
+ "-i", str(filelist_path),
40
  "-vf", "scale=trunc(iw/2)*2:trunc(ih/2)*2,fps=25,format=yuv420p",
 
41
  str(output_file)
42
  ]
43
 
 
46
  except subprocess.CalledProcessError as e:
47
  return None, f"❌ FFmpeg Fehler:\n{e.stderr}"
48
 
 
49
  if output_file.exists():
50
+ return str(output_file), f"✅ Slideshow Video erstellt ({len(images)} Bilder, {duration}s pro Bild)"
51
  else:
52
  return None, "❌ Video konnte nicht erstellt werden"
53
 
54
  # Gradio UI
55
  with gr.Blocks() as demo:
56
+ gr.Markdown("# Slideshow Video Generator")
57
+
58
+ img_input = gr.File(file_types=allowed_medias, label="Bilder auswählen (mehrere)", file_types_allow_multiple=True)
59
+ duration_input = gr.Number(value=3, label="Dauer pro Bild in Sekunden", precision=1)
60
  out_video = gr.Video(interactive=False, label="Generiertes Video")
61
  status = gr.Textbox(interactive=False, label="Status")
62
+
63
  btn = gr.Button("Video erstellen")
64
+ btn.click(
65
+ fn=generate_slideshow,
66
+ inputs=[img_input, duration_input],
67
+ outputs=[out_video, status]
68
+ )
69
 
70
  demo.launch()