Tim13ekd commited on
Commit
b6a8e09
·
verified ·
1 Parent(s): 0b567d9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +13 -18
app.py CHANGED
@@ -20,25 +20,22 @@ def save_temp_audio(audio_file):
20
  """
21
  Speichert die hochgeladene Datei sicher mit korrekter Endung in einem temporären Verzeichnis.
22
  """
23
- # Wenn audio_file ein NamedString (Byte-Inhalt) ist
24
- if isinstance(audio_file, str): # Gradio gibt es als NamedString zurück, wenn es sich um einen String handelt
25
- # Hier können wir die Datei als binären Inhalt behandeln
26
  ext = Path(audio_file).suffix
27
  if ext.lower() not in allowed_audios:
28
  ext = ".mp3" # Standard, falls Endung fehlt
29
  temp_audio = Path(tempfile.mkdtemp()) / f"input{ext}"
30
  with open(temp_audio, "wb") as f:
31
- f.write(audio_file.encode()) # Binäre Datei schreiben
32
  return temp_audio
33
-
34
- elif hasattr(audio_file, 'name'): # Wenn es sich um eine echte Datei handelt
35
  ext = Path(audio_file.name).suffix
36
  if ext.lower() not in allowed_audios:
37
- ext = ".mp3" # Standard, falls Endung fehlt
38
  temp_audio = Path(tempfile.mkdtemp()) / f"input{ext}"
39
- audio_file.seek(0) # Setzt den Zeiger zurück
40
  with open(temp_audio, "wb") as f:
41
- shutil.copyfileobj(audio_file, f) # Kopiere den Inhalt der Datei
42
  return temp_audio
43
  else:
44
  raise ValueError("Das übergebene Audio ist kein gültiges Dateiformat oder NamedString.")
@@ -66,7 +63,7 @@ def transcribe_audio(audio_file):
66
  }
67
  try:
68
  response = requests.post(API_URL, json=payload)
69
- response.raise_for_status() # Dies wird eine Ausnahme werfen, wenn die Antwort ein Fehler ist
70
  except requests.RequestException as e:
71
  return None, f"❌ API Fehler: {e}"
72
 
@@ -74,7 +71,7 @@ def transcribe_audio(audio_file):
74
  text = result['choices'][0]['message']['content']
75
  return text
76
 
77
- def generate_slideshow_with_audio(images, audio_file, duration_per_image=3, y_pos=0.5, fade_duration=0.7, font_size=60):
78
  if not images:
79
  return None, "❌ Keine Bilder ausgewählt"
80
 
@@ -82,7 +79,6 @@ def generate_slideshow_with_audio(images, audio_file, duration_per_image=3, y_po
82
  temp_dir = tempfile.mkdtemp()
83
  clips = []
84
 
85
- # Transkription, falls Audio vorhanden
86
  if audio_file:
87
  transcript, err = transcribe_audio(audio_file)
88
  if err:
@@ -100,9 +96,8 @@ def generate_slideshow_with_audio(images, audio_file, duration_per_image=3, y_po
100
  texts = [""] * len(images)
101
  temp_audio_file = None
102
 
103
- # Einzelne Clips erstellen
104
  for i, img_path in enumerate(images):
105
- img_path = Path(img_path.name) # Hier muss .name verwendet werden, da Gradio temporäre Dateien liefert
106
  clip_path = Path(temp_dir) / f"clip_{i}.mp4"
107
  text = texts[i] if i < len(texts) else ""
108
 
@@ -113,8 +108,7 @@ def generate_slideshow_with_audio(images, audio_file, duration_per_image=3, y_po
113
  )
114
 
115
  if text:
116
- # Escape problematischer Zeichen für FFmpeg
117
- safe_text = shlex.quote(text) # Sichere Textverarbeitung
118
  drawtext_filter = (
119
  f",drawtext=text={safe_text}:fontcolor=white:fontsize={font_size}:borderw=2:"
120
  f"x=(w-text_w)/2:y=(h-text_h)*{y_pos}:"
@@ -160,7 +154,6 @@ def generate_slideshow_with_audio(images, audio_file, duration_per_image=3, y_po
160
  except subprocess.CalledProcessError as e:
161
  return None, f"❌ FFmpeg Concat Fehler:\n{e.stderr}"
162
 
163
- # Audio hinzufügen, falls vorhanden
164
  if temp_audio_file:
165
  final_output = Path(temp_dir) / f"slideshow_audio_{uuid.uuid4().hex}.mp4"
166
  cmd_audio = [
@@ -194,13 +187,15 @@ with gr.Blocks() as demo:
194
  fade_input = gr.Number(value=0.7, label="Fade Dauer in Sekunden", precision=1)
195
  ypos_input = gr.Slider(minimum=0.0, maximum=0.9, step=0.01, value=0.5, label="Y-Position für alle Texte (0=oben, 0.5=mitte, 0.9=unten)")
196
  font_size_input = gr.Number(value=60, label="Textgröße (px)")
 
 
197
  out_video = gr.Video(interactive=False, label="Generiertes Video")
198
  status = gr.Textbox(interactive=False, label="Status")
199
 
200
  btn = gr.Button("Video erstellen")
201
  btn.click(
202
  fn=generate_slideshow_with_audio,
203
- inputs=[img_input, audio_input, duration_input, ypos_input, fade_input, font_size_input],
204
  outputs=[out_video, status]
205
  )
206
 
 
20
  """
21
  Speichert die hochgeladene Datei sicher mit korrekter Endung in einem temporären Verzeichnis.
22
  """
23
+ if isinstance(audio_file, str):
 
 
24
  ext = Path(audio_file).suffix
25
  if ext.lower() not in allowed_audios:
26
  ext = ".mp3" # Standard, falls Endung fehlt
27
  temp_audio = Path(tempfile.mkdtemp()) / f"input{ext}"
28
  with open(temp_audio, "wb") as f:
29
+ f.write(audio_file.encode())
30
  return temp_audio
31
+ elif hasattr(audio_file, 'name'):
 
32
  ext = Path(audio_file.name).suffix
33
  if ext.lower() not in allowed_audios:
34
+ ext = ".mp3"
35
  temp_audio = Path(tempfile.mkdtemp()) / f"input{ext}"
36
+ audio_file.seek(0)
37
  with open(temp_audio, "wb") as f:
38
+ shutil.copyfileobj(audio_file, f)
39
  return temp_audio
40
  else:
41
  raise ValueError("Das übergebene Audio ist kein gültiges Dateiformat oder NamedString.")
 
63
  }
64
  try:
65
  response = requests.post(API_URL, json=payload)
66
+ response.raise_for_status()
67
  except requests.RequestException as e:
68
  return None, f"❌ API Fehler: {e}"
69
 
 
71
  text = result['choices'][0]['message']['content']
72
  return text
73
 
74
+ def generate_slideshow_with_audio(images, audio_file, duration_per_image=3, y_pos=0.5, fade_duration=0.7, font_size=60, speed=1.0):
75
  if not images:
76
  return None, "❌ Keine Bilder ausgewählt"
77
 
 
79
  temp_dir = tempfile.mkdtemp()
80
  clips = []
81
 
 
82
  if audio_file:
83
  transcript, err = transcribe_audio(audio_file)
84
  if err:
 
96
  texts = [""] * len(images)
97
  temp_audio_file = None
98
 
 
99
  for i, img_path in enumerate(images):
100
+ img_path = Path(img_path.name) # Gradio liefert temporäre Dateipfade
101
  clip_path = Path(temp_dir) / f"clip_{i}.mp4"
102
  text = texts[i] if i < len(texts) else ""
103
 
 
108
  )
109
 
110
  if text:
111
+ safe_text = shlex.quote(text)
 
112
  drawtext_filter = (
113
  f",drawtext=text={safe_text}:fontcolor=white:fontsize={font_size}:borderw=2:"
114
  f"x=(w-text_w)/2:y=(h-text_h)*{y_pos}:"
 
154
  except subprocess.CalledProcessError as e:
155
  return None, f"❌ FFmpeg Concat Fehler:\n{e.stderr}"
156
 
 
157
  if temp_audio_file:
158
  final_output = Path(temp_dir) / f"slideshow_audio_{uuid.uuid4().hex}.mp4"
159
  cmd_audio = [
 
187
  fade_input = gr.Number(value=0.7, label="Fade Dauer in Sekunden", precision=1)
188
  ypos_input = gr.Slider(minimum=0.0, maximum=0.9, step=0.01, value=0.5, label="Y-Position für alle Texte (0=oben, 0.5=mitte, 0.9=unten)")
189
  font_size_input = gr.Number(value=60, label="Textgröße (px)")
190
+ speed_input = gr.Slider(minimum=0.1, maximum=3.0, value=1.0, label="Geschwindigkeit der Texteinblendung")
191
+
192
  out_video = gr.Video(interactive=False, label="Generiertes Video")
193
  status = gr.Textbox(interactive=False, label="Status")
194
 
195
  btn = gr.Button("Video erstellen")
196
  btn.click(
197
  fn=generate_slideshow_with_audio,
198
+ inputs=[img_input, audio_input, duration_input, ypos_input, fade_input, font_size_input, speed_input],
199
  outputs=[out_video, status]
200
  )
201