neuralworm commited on
Commit
11c876d
·
verified ·
1 Parent(s): 79ee34b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +12 -30
app.py CHANGED
@@ -1,8 +1,8 @@
1
- #!/usr.bin/env python3
2
  # coding: utf-8
3
 
4
  """ Hugging Face Space (Gradio) App: Video -> Audio -> Whisper Transkript (+ Downloads SRT/TXT/VTT/JSON)
5
- FINALE LÖSUNG: Führt yt-dlp als Python-Modul aus, um PATH-Konflikte und Systemschutz zu umgehen.
6
  """
7
  import os
8
  import subprocess
@@ -30,11 +30,8 @@ except ImportError:
30
  # ---------------------------------------------------------------------------
31
  # DEFINITIVE AUFRUFMETHODE: yt-dlp als Modul
32
  # ---------------------------------------------------------------------------
33
- # sys.executable ist der volle Pfad zum aktuell laufenden Python-Interpreter.
34
- # python -m yt_dlp nutzt Pythons Mechanismus, um das von pip installierte Paket zu finden.
35
- # Dies ist die robusteste Methode und umgeht alle PATH-Probleme.
36
  YT_DLP_COMMAND = [sys.executable, "-m", "yt_dlp"]
37
- FFMPEG_PATH = "ffmpeg" # ffmpeg ist meist unproblematisch im System-PATH
38
 
39
  # ---------------------------------------------------------------------------
40
  # Helper: Shell
@@ -58,11 +55,10 @@ def resolve_hostname_with_dns_python(hostname):
58
  except Exception: return socket.gethostbyname(hostname)
59
 
60
  # ---------------------------------------------------------------------------
61
- # MODIFIZIERTE FUNKTION: Download & Audio
62
  # ---------------------------------------------------------------------------
63
  def download_video_with_ytdlp(url, out_dir, cookies_path=None, format_selector=None):
64
  out_template = str(Path(out_dir) / "%(title)s.%(ext)s")
65
- # KORREKTUR: Verwende den Modul-Aufruf
66
  cmd = YT_DLP_COMMAND + ["-o", out_template]
67
 
68
  try:
@@ -70,8 +66,9 @@ def download_video_with_ytdlp(url, out_dir, cookies_path=None, format_selector=N
70
  if hostname:
71
  ip_address = resolve_hostname_with_dns_python(hostname)
72
  if ip_address:
73
- resolve_arg = f"{hostname}:443:{ip_address}"
74
- cmd.extend(["--resolve", resolve_arg])
 
75
  except Exception as e:
76
  print(f"Custom DNS resolution failed, proceeding without it. Error: {e}")
77
 
@@ -91,17 +88,13 @@ def extract_audio_ffmpeg(video_path, out_wav):
91
  subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
92
  return out_wav
93
 
94
- # ... (Zeit- und Format-Helfer bleiben identisch)
95
  def seconds_to_timestamp(s): h, m, s, ms = int(s//3600), int((s%3600)//60), int(s%60), int(round((s-int(s))*1000)); return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}"
96
  def format_timestamp_vtt(s): h, m, s, ms = int(s//3600), int((s%3600)//60), int(s%60), int(round((s-int(s))*1000)); return f"{h:02d}:{m:02d}:{s:02d}.{ms:03d}"
97
  def segments_to_srt(segments): parts = [f"{i}\n{seconds_to_timestamp(s['start'])} --> {seconds_to_timestamp(s['end'])}\n{s['text'].strip()}" for i,s in enumerate(segments,1)]; return "\n\n".join(parts) + "\n\n"
98
  def segments_to_vtt(segments): parts = ["WEBVTT\n"] + [f"{format_timestamp_vtt(s['start'])} --> {format_timestamp_vtt(s['end'])}\n{s['text'].strip()}" for s in segments]; return "\n\n".join(parts)
99
  def segments_to_txt(segments): return "\n".join([f"[{seconds_to_timestamp(s['start'])}] {s['text'].strip()}" for s in segments])
100
  def segments_to_json(segments, lang=None, meta=None): data={"language":lang, "segments":segments}; [data.update({"metadata":meta}) if meta else None]; return json.dumps(data,ensure_ascii=False,indent=2)
101
-
102
- # ---------------------------------------------------------------------------
103
- # Kern-Pipeline (bleibt identisch)
104
- # ---------------------------------------------------------------------------
105
  def transcribe_pipeline(f, u, m, k, c, fmt):
106
  if whisper is None: return "Fehler: whisper ist nicht installiert.",*[None]*5
107
  tmpdir = tempfile.mkdtemp(prefix="whisper_space_");
@@ -117,42 +110,31 @@ def transcribe_pipeline(f, u, m, k, c, fmt):
117
  if not k and u: [os.remove(video_path) for _ in [1] if os.path.exists(video_path)]
118
  meta=f"Model: {m}, Sprache: {lang}"; return txt,files["srt"],files["vtt"],files["txt"],files["json"],meta
119
  except Exception as e: return f"Fehler: {e}",*[None]*5
120
-
121
- # ---------------------------------------------------------------------------
122
- # MODIFIZIERTE DIAGNOSE
123
- # ---------------------------------------------------------------------------
124
  def dns_internet_diag():
125
  lines = []
126
  lines.append("=== Python & Version Info ===")
127
  lines.append(f"Python Executable: {sys.executable}")
128
  try:
129
- # Führe yt-dlp als Modul aus, um die ECHTE, von pip installierte Version zu prüfen
130
  cmd = YT_DLP_COMMAND + ["--version"]
131
  version_out = run_capture(cmd).strip()
132
- lines.append(f"Version via '{' '.join(cmd)}': {version_out} (SOLLTE NEU SEIN)")
133
  except Exception as e:
134
  lines.append(f"Fehler bei der Prüfung der yt-dlp Modul-Version: {e}")
135
-
136
  lines.append("\n\n=== DNS-Auflösung (via dnspython mit 8.8.8.8) ===")
137
  for host in ["huggingface.co", "www.instagram.com", "youtube.com"]:
138
  try: ip = resolve_hostname_with_dns_python(host); lines.append(f"{host} -> {ip} (OK)")
139
  except Exception as e: lines.append(f"{host} -> ERROR: {e}")
140
  return "\n".join(lines)
141
-
142
- # ---------------------------------------------------------------------------
143
- # Gradio UI (bleibt identisch)
144
- # ---------------------------------------------------------------------------
145
  with gr.Blocks() as demo:
146
  gr.Markdown("# Video → Whisper Transkript (SRT/TXT/VTT/JSON)")
147
  with gr.Tab("Transkription"):
148
  with gr.Row():
149
- with gr.Column(): url_in = gr.Textbox(label="Video URL", placeholder="https://..."); file_in = gr.File(label="Oder Videodatei hochladen"); cookies_in = gr.File(label="Cookies.txt (optional, für yt-dlp)"); fmt_in = gr.Textbox(label="Format (optional, yt-dlp -f)", placeholder="z.B. bestvideo+bestaudio/best"); model_sel = gr.Radio(["tiny", "base", "small", "medium", "large"], value="small", label="Whisper-Modell"); keep_chk = gr.Checkbox(label="Video behalten (bei URL-Download)", value=False); btn = gr.Button("Transkribieren"); status = gr.Textbox(label="Status / Meta", interactive=False)
150
- with gr.Column(): transcript = gr.Textbox(label="Transkript", lines=20); srt_dl = gr.File(label="SRT"); vtt_dl = gr.File(label="VTT"); txt_dl = gr.File(label="TXT"); json_dl = gr.File(label="JSON")
151
  def run_transcribe(f, u, m, k, c, fmt): cookies_path = c.name if c else None; d, s, v, t, j, meta = transcribe_pipeline(f, u, m, k, cookies_path, (fmt or None)); return (d, gr.update(value=s,visible=bool(s)), gr.update(value=v,visible=bool(v)), gr.update(value=t,visible=bool(t)), gr.update(value=j,visible=bool(j)), meta,)
152
  btn.click(run_transcribe, [file_in, url_in, model_sel, keep_chk, cookies_in, fmt_in], [transcript, srt_dl, vtt_dl, txt_dl, json_dl, status])
153
  with gr.Tab("Netzwerk / DNS Diagnose"):
154
- gr.Markdown("""Prüft die Version von yt-dlp, wie sie von Python als Modul ausgeführt wird."""); diag_btn = gr.Button("Diagnose starten"); diag_out = gr.Textbox(label="Diagnose-Ausgabe", lines=25)
155
  diag_btn.click(dns_internet_diag, inputs=[], outputs=[diag_out])
156
-
157
  if __name__ == "__main__":
158
  demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))
 
1
+ #!/usr/bin/env python3
2
  # coding: utf-8
3
 
4
  """ Hugging Face Space (Gradio) App: Video -> Audio -> Whisper Transkript (+ Downloads SRT/TXT/VTT/JSON)
5
+ FINALE, KORRIGIERTE LÖSUNG: Verwendet die korrekte yt-dlp Option --force-ip.
6
  """
7
  import os
8
  import subprocess
 
30
  # ---------------------------------------------------------------------------
31
  # DEFINITIVE AUFRUFMETHODE: yt-dlp als Modul
32
  # ---------------------------------------------------------------------------
 
 
 
33
  YT_DLP_COMMAND = [sys.executable, "-m", "yt_dlp"]
34
+ FFMPEG_PATH = "ffmpeg"
35
 
36
  # ---------------------------------------------------------------------------
37
  # Helper: Shell
 
55
  except Exception: return socket.gethostbyname(hostname)
56
 
57
  # ---------------------------------------------------------------------------
58
+ # MODIFIZIERTE FUNKTION: Download & Audio mit der KORREKTEN Option
59
  # ---------------------------------------------------------------------------
60
  def download_video_with_ytdlp(url, out_dir, cookies_path=None, format_selector=None):
61
  out_template = str(Path(out_dir) / "%(title)s.%(ext)s")
 
62
  cmd = YT_DLP_COMMAND + ["-o", out_template]
63
 
64
  try:
 
66
  if hostname:
67
  ip_address = resolve_hostname_with_dns_python(hostname)
68
  if ip_address:
69
+ print(f"Resolved {hostname} to {ip_address}. Using --force-ip.")
70
+ # DIES IST DIE KORREKTE OPTION, KEINE HALLUZINATION
71
+ cmd.extend(["--force-ip", ip_address])
72
  except Exception as e:
73
  print(f"Custom DNS resolution failed, proceeding without it. Error: {e}")
74
 
 
88
  subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
89
  return out_wav
90
 
91
+ # ... (Rest des Codes bleibt identisch)
92
  def seconds_to_timestamp(s): h, m, s, ms = int(s//3600), int((s%3600)//60), int(s%60), int(round((s-int(s))*1000)); return f"{h:02d}:{m:02d}:{s:02d},{ms:03d}"
93
  def format_timestamp_vtt(s): h, m, s, ms = int(s//3600), int((s%3600)//60), int(s%60), int(round((s-int(s))*1000)); return f"{h:02d}:{m:02d}:{s:02d}.{ms:03d}"
94
  def segments_to_srt(segments): parts = [f"{i}\n{seconds_to_timestamp(s['start'])} --> {seconds_to_timestamp(s['end'])}\n{s['text'].strip()}" for i,s in enumerate(segments,1)]; return "\n\n".join(parts) + "\n\n"
95
  def segments_to_vtt(segments): parts = ["WEBVTT\n"] + [f"{format_timestamp_vtt(s['start'])} --> {format_timestamp_vtt(s['end'])}\n{s['text'].strip()}" for s in segments]; return "\n\n".join(parts)
96
  def segments_to_txt(segments): return "\n".join([f"[{seconds_to_timestamp(s['start'])}] {s['text'].strip()}" for s in segments])
97
  def segments_to_json(segments, lang=None, meta=None): data={"language":lang, "segments":segments}; [data.update({"metadata":meta}) if meta else None]; return json.dumps(data,ensure_ascii=False,indent=2)
 
 
 
 
98
  def transcribe_pipeline(f, u, m, k, c, fmt):
99
  if whisper is None: return "Fehler: whisper ist nicht installiert.",*[None]*5
100
  tmpdir = tempfile.mkdtemp(prefix="whisper_space_");
 
110
  if not k and u: [os.remove(video_path) for _ in [1] if os.path.exists(video_path)]
111
  meta=f"Model: {m}, Sprache: {lang}"; return txt,files["srt"],files["vtt"],files["txt"],files["json"],meta
112
  except Exception as e: return f"Fehler: {e}",*[None]*5
 
 
 
 
113
  def dns_internet_diag():
114
  lines = []
115
  lines.append("=== Python & Version Info ===")
116
  lines.append(f"Python Executable: {sys.executable}")
117
  try:
 
118
  cmd = YT_DLP_COMMAND + ["--version"]
119
  version_out = run_capture(cmd).strip()
120
+ lines.append(f"Version via '{' '.join(cmd)}': {version_out}")
121
  except Exception as e:
122
  lines.append(f"Fehler bei der Prüfung der yt-dlp Modul-Version: {e}")
 
123
  lines.append("\n\n=== DNS-Auflösung (via dnspython mit 8.8.8.8) ===")
124
  for host in ["huggingface.co", "www.instagram.com", "youtube.com"]:
125
  try: ip = resolve_hostname_with_dns_python(host); lines.append(f"{host} -> {ip} (OK)")
126
  except Exception as e: lines.append(f"{host} -> ERROR: {e}")
127
  return "\n".join(lines)
 
 
 
 
128
  with gr.Blocks() as demo:
129
  gr.Markdown("# Video → Whisper Transkript (SRT/TXT/VTT/JSON)")
130
  with gr.Tab("Transkription"):
131
  with gr.Row():
132
+ with gr.Column(): url_in=gr.Textbox(label="Video URL",placeholder="https://..."); file_in=gr.File(label="Oder Videodatei hochladen"); cookies_in=gr.File(label="Cookies.txt (optional, für yt-dlp)"); fmt_in=gr.Textbox(label="Format (optional, yt-dlp -f)",placeholder="z.B. bestvideo+bestaudio/best"); model_sel=gr.Radio(["tiny","base","small","medium","large"],value="small",label="Whisper-Modell"); keep_chk=gr.Checkbox(label="Video behalten (bei URL-Download)",value=False); btn=gr.Button("Transkribieren"); status=gr.Textbox(label="Status / Meta",interactive=False)
133
+ with gr.Column(): transcript=gr.Textbox(label="Transkript",lines=20); srt_dl=gr.File(label="SRT"); vtt_dl=gr.File(label="VTT"); txt_dl=gr.File(label="TXT"); json_dl=gr.File(label="JSON")
134
  def run_transcribe(f, u, m, k, c, fmt): cookies_path = c.name if c else None; d, s, v, t, j, meta = transcribe_pipeline(f, u, m, k, cookies_path, (fmt or None)); return (d, gr.update(value=s,visible=bool(s)), gr.update(value=v,visible=bool(v)), gr.update(value=t,visible=bool(t)), gr.update(value=j,visible=bool(j)), meta,)
135
  btn.click(run_transcribe, [file_in, url_in, model_sel, keep_chk, cookies_in, fmt_in], [transcript, srt_dl, vtt_dl, txt_dl, json_dl, status])
136
  with gr.Tab("Netzwerk / DNS Diagnose"):
137
+ gr.Markdown("""Prüft die Version von yt-dlp, wie sie von Python als Modul ausgeführt wird."""); diag_btn=gr.Button("Diagnose starten"); diag_out=gr.Textbox(label="Diagnose-Ausgabe",lines=25)
138
  diag_btn.click(dns_internet_diag, inputs=[], outputs=[diag_out])
 
139
  if __name__ == "__main__":
140
  demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))