cstr commited on
Commit
d274746
·
verified ·
1 Parent(s): 0a64646

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -53
app.py CHANGED
@@ -8,9 +8,12 @@ import requests
8
  from urllib.parse import urlparse
9
 
10
  # Clone and install faster-whisper from GitHub
11
- subprocess.run(["git", "clone", "https://github.com/SYSTRAN/faster-whisper.git"], check=True)
12
- subprocess.run(["pip", "install", "-e", "./faster-whisper"], check=True)
13
- #subprocess.run(["pip", "install", "yt-dlp pytube ffmpeg-python"], check=True)
 
 
 
14
 
15
  # Add the faster-whisper directory to the Python path
16
  sys.path.append("./faster-whisper")
@@ -19,28 +22,30 @@ from faster_whisper import WhisperModel
19
  from faster_whisper.transcribe import BatchedInferencePipeline
20
  import yt_dlp
21
 
22
- def download_audio(url):
23
  parsed_url = urlparse(url)
24
  if parsed_url.netloc in ['www.youtube.com', 'youtu.be', 'youtube.com']:
25
- return download_youtube_audio(url)
26
  else:
27
- return download_direct_audio(url)
28
-
29
- def download_youtube_audio(url):
30
- methods = [
31
- youtube_dl_method,
32
- pytube_method,
33
- youtube_dl_alternative_method,
34
- ffmpeg_method
35
- ]
36
-
37
- for method in methods:
38
- try:
39
- return method(url)
40
- except Exception as e:
41
- print(f"Method {method.__name__} failed: {str(e)}")
42
 
43
- raise Exception("All download methods failed. Please try a different video or a direct audio URL.")
 
 
 
44
 
45
  def youtube_dl_method(url):
46
  ydl_opts = {
@@ -66,6 +71,21 @@ def pytube_method(url):
66
  os.rename(out_file, new_file)
67
  return new_file
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  def youtube_dl_alternative_method(url):
70
  ydl_opts = {
71
  'format': 'bestaudio/best',
@@ -79,7 +99,6 @@ def youtube_dl_alternative_method(url):
79
  'quiet': True,
80
  'no_check_certificate': True,
81
  'prefer_insecure': True,
82
- 'nocheckcertificate': True,
83
  }
84
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
85
  info = ydl.extract_info(url, download=True)
@@ -91,16 +110,34 @@ def ffmpeg_method(url):
91
  subprocess.run(command, check=True, capture_output=True)
92
  return output_file
93
 
94
- def download_direct_audio(url):
95
- response = requests.get(url)
96
- if response.status_code == 200:
97
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_file:
98
- temp_file.write(response.content)
99
- return temp_file.name
 
 
 
100
  else:
101
- raise Exception(f"Failed to download audio from {url}")
 
 
 
 
 
 
 
 
 
102
 
103
- def transcribe_audio(input_source, batch_size):
 
 
 
 
 
 
104
  try:
105
  # Initialize the model
106
  model = WhisperModel("cstr/whisper-large-v3-turbo-int8_float32", device="auto", compute_type="int8")
@@ -109,7 +146,10 @@ def transcribe_audio(input_source, batch_size):
109
  # Handle input source
110
  if isinstance(input_source, str) and (input_source.startswith('http://') or input_source.startswith('https://')):
111
  # It's a URL, download the audio
112
- audio_path = download_audio(input_source)
 
 
 
113
  else:
114
  # It's a local file path
115
  audio_path = input_source
@@ -119,28 +159,36 @@ def transcribe_audio(input_source, batch_size):
119
  segments, info = batched_model.transcribe(audio_path, batch_size=batch_size)
120
  end_time = time.time()
121
 
122
- # Generate transcription
123
- transcription = ""
124
- for segment in segments:
125
- transcription += f"[{segment.start:.2f}s -> {segment.end:.2f}s] {segment.text}\n"
126
-
127
- # Calculate metrics
128
  transcription_time = end_time - start_time
129
  real_time_factor = info.duration / transcription_time
130
  audio_file_size = os.path.getsize(audio_path) / (1024 * 1024) # Size in MB
131
 
132
- # Prepare output
133
- output = f"Transcription:\n\n{transcription}\n"
134
- output += f"\nLanguage: {info.language}, Probability: {info.language_probability:.2f}\n"
135
- output += f"Duration: {info.duration:.2f}s, Duration after VAD: {info.duration_after_vad:.2f}s\n"
136
- output += f"Transcription time: {transcription_time:.2f} seconds\n"
137
- output += f"Real-time factor: {real_time_factor:.2f}x\n"
138
- output += f"Audio file size: {audio_file_size:.2f} MB"
 
 
 
 
 
 
 
 
 
 
 
139
 
140
- return output
 
 
141
 
142
  except Exception as e:
143
- return f"An error occurred: {str(e)}"
144
 
145
  finally:
146
  # Clean up downloaded file if it was a URL
@@ -150,22 +198,33 @@ def transcribe_audio(input_source, batch_size):
150
  except:
151
  pass
152
 
 
 
 
 
 
 
153
  # Gradio interface
154
  iface = gr.Interface(
155
  fn=transcribe_audio,
156
  inputs=[
157
  gr.Textbox(label="Audio Source (Upload, MP3 URL, or YouTube URL)"),
158
- gr.Slider(minimum=1, maximum=32, step=1, value=16, label="Batch Size")
 
 
 
 
 
 
159
  ],
160
- outputs=gr.Textbox(label="Transcription and Metrics"),
161
  title="Faster Whisper Multi-Input Transcription",
162
- description="Enter an audio file path, MP3 URL, or YouTube URL to transcribe using Faster Whisper (GitHub version). Adjust the batch size for performance tuning.",
163
  examples=[
164
- ["https://www.youtube.com/watch?v=dQw4w9WgXcQ", 16],
165
- ["https://example.com/path/to/audio.mp3", 16],
166
- ["path/to/local/audio.mp3", 16]
167
  ],
168
  cache_examples=False # Prevents automatic processing of examples
169
  )
170
 
171
- iface.launch()
 
8
  from urllib.parse import urlparse
9
 
10
  # Clone and install faster-whisper from GitHub
11
+ try:
12
+ subprocess.run(["git", "clone", "https://github.com/SYSTRAN/faster-whisper.git"], check=True)
13
+ subprocess.run(["pip", "install", "-e", "./faster-whisper"], check=True)
14
+ except subprocess.CalledProcessError as e:
15
+ print(f"Error during faster-whisper installation: {e}")
16
+ sys.exit(1)
17
 
18
  # Add the faster-whisper directory to the Python path
19
  sys.path.append("./faster-whisper")
 
22
  from faster_whisper.transcribe import BatchedInferencePipeline
23
  import yt_dlp
24
 
25
+ def download_audio(url, method_choice):
26
  parsed_url = urlparse(url)
27
  if parsed_url.netloc in ['www.youtube.com', 'youtu.be', 'youtube.com']:
28
+ return download_youtube_audio(url, method_choice)
29
  else:
30
+ return download_direct_audio(url, method_choice)
31
+
32
+ # Additional YouTube download methods
33
+ def download_youtube_audio(url, method_choice):
34
+ methods = {
35
+ 'yt-dlp': youtube_dl_method,
36
+ 'pytube': pytube_method,
37
+ 'youtube-dl': youtube_dl_classic_method,
38
+ 'yt-dlp-alt': youtube_dl_alternative_method,
39
+ 'ffmpeg': ffmpeg_method,
40
+ 'aria2': aria2_method
41
+ }
42
+
43
+ method = methods.get(method_choice, youtube_dl_method)
 
44
 
45
+ try:
46
+ return method(url)
47
+ except Exception as e:
48
+ return f"Error downloading using {method_choice}: {str(e)}"
49
 
50
  def youtube_dl_method(url):
51
  ydl_opts = {
 
71
  os.rename(out_file, new_file)
72
  return new_file
73
 
74
+ def youtube_dl_classic_method(url):
75
+ # Classic youtube-dl method
76
+ ydl_opts = {
77
+ 'format': 'bestaudio/best',
78
+ 'postprocessors': [{
79
+ 'key': 'FFmpegExtractAudio',
80
+ 'preferredcodec': 'mp3',
81
+ 'preferredquality': '192',
82
+ }],
83
+ 'outtmpl': '%(id)s.%(ext)s',
84
+ }
85
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
86
+ info = ydl.extract_info(url, download=True)
87
+ return f"{info['id']}.mp3"
88
+
89
  def youtube_dl_alternative_method(url):
90
  ydl_opts = {
91
  'format': 'bestaudio/best',
 
99
  'quiet': True,
100
  'no_check_certificate': True,
101
  'prefer_insecure': True,
 
102
  }
103
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
104
  info = ydl.extract_info(url, download=True)
 
110
  subprocess.run(command, check=True, capture_output=True)
111
  return output_file
112
 
113
+ def aria2_method(url):
114
+ output_file = tempfile.mktemp(suffix='.mp3')
115
+ command = ['aria2c', '--split=4', '--max-connection-per-server=4', '--out', output_file, url]
116
+ subprocess.run(command, check=True, capture_output=True)
117
+ return output_file
118
+
119
+ def download_direct_audio(url, method_choice):
120
+ if method_choice == 'wget':
121
+ return wget_method(url)
122
  else:
123
+ try:
124
+ response = requests.get(url)
125
+ if response.status_code == 200:
126
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_file:
127
+ temp_file.write(response.content)
128
+ return temp_file.name
129
+ else:
130
+ raise Exception(f"Failed to download audio from {url}")
131
+ except Exception as e:
132
+ return f"Error downloading direct audio: {str(e)}"
133
 
134
+ def wget_method(url):
135
+ output_file = tempfile.mktemp(suffix='.mp3')
136
+ command = ['wget', '-O', output_file, url]
137
+ subprocess.run(command, check=True, capture_output=True)
138
+ return output_file
139
+
140
+ def transcribe_audio(input_source, batch_size, download_method):
141
  try:
142
  # Initialize the model
143
  model = WhisperModel("cstr/whisper-large-v3-turbo-int8_float32", device="auto", compute_type="int8")
 
146
  # Handle input source
147
  if isinstance(input_source, str) and (input_source.startswith('http://') or input_source.startswith('https://')):
148
  # It's a URL, download the audio
149
+ audio_path = download_audio(input_source, download_method)
150
+ if audio_path.startswith("Error"):
151
+ yield f"Error: {audio_path}", "", None
152
+ return
153
  else:
154
  # It's a local file path
155
  audio_path = input_source
 
159
  segments, info = batched_model.transcribe(audio_path, batch_size=batch_size)
160
  end_time = time.time()
161
 
162
+ # Show initial metrics as soon as possible
 
 
 
 
 
163
  transcription_time = end_time - start_time
164
  real_time_factor = info.duration / transcription_time
165
  audio_file_size = os.path.getsize(audio_path) / (1024 * 1024) # Size in MB
166
 
167
+ metrics_output = (
168
+ f"Language: {info.language}, Probability: {info.language_probability:.2f}\n"
169
+ f"Duration: {info.duration:.2f}s, Duration after VAD: {info.duration_after_vad:.2f}s\n"
170
+ f"Transcription time: {transcription_time:.2f} seconds\n"
171
+ f"Real-time factor: {real_time_factor:.2f}x\n"
172
+ f"Audio file size: {audio_file_size:.2f} MB\n"
173
+ )
174
+
175
+ yield metrics_output, "", None
176
+
177
+ transcription = ""
178
+
179
+ # Stream transcription output gradually
180
+ for segment in segments:
181
+ transcription_segment = f"[{segment.start:.2f}s -> {segment.end:.2f}s] {segment.text}\n"
182
+ transcription += transcription_segment
183
+
184
+ yield metrics_output, transcription, None
185
 
186
+ # Final output with download option
187
+ transcription_file = save_transcription(transcription)
188
+ yield metrics_output, transcription, transcription_file
189
 
190
  except Exception as e:
191
+ yield f"An error occurred: {str(e)}", "", None
192
 
193
  finally:
194
  # Clean up downloaded file if it was a URL
 
198
  except:
199
  pass
200
 
201
+ def save_transcription(transcription):
202
+ file_path = tempfile.mktemp(suffix='.txt')
203
+ with open(file_path, 'w') as f:
204
+ f.write(transcription)
205
+ return file_path
206
+
207
  # Gradio interface
208
  iface = gr.Interface(
209
  fn=transcribe_audio,
210
  inputs=[
211
  gr.Textbox(label="Audio Source (Upload, MP3 URL, or YouTube URL)"),
212
+ gr.Slider(minimum=1, maximum=32, step=1, value=16, label="Batch Size"),
213
+ gr.Dropdown(choices=["yt-dlp", "pytube", "youtube-dl", "yt-dlp-alt", "ffmpeg", "aria2", "wget"], label="Download Method", value="yt-dlp")
214
+ ],
215
+ outputs=[
216
+ gr.Textbox(label="Transcription Metrics and Verbose Messages", live=True),
217
+ gr.Textbox(label="Transcription", live=True),
218
+ gr.File(label="Download Transcription")
219
  ],
 
220
  title="Faster Whisper Multi-Input Transcription",
221
+ description="Enter an audio file path, MP3 URL, or YouTube URL to transcribe using Faster Whisper (GitHub version). Adjust the batch size and choose a download method.",
222
  examples=[
223
+ ["https://www.youtube.com/watch?v=daQ_hqA6HDo", 16, "yt-dlp"],
224
+ ["https://mcdn.podbean.com/mf/web/dir5wty678b6g4vg/HoP_453_-_The_Price_is_Right_-_Law_and_Economics_in_the_Second_Scholastic5yxzh.mp3", 16, "ffmpeg"],
225
+ ["path/to/local/audio.mp3", 16, "yt-dlp"]
226
  ],
227
  cache_examples=False # Prevents automatic processing of examples
228
  )
229
 
230
+ iface.launch()