Spaces:
Runtime error
Runtime error
danilotpnta
commited on
Commit
·
f62c279
1
Parent(s):
48a5d9c
update: app and added yt_dlp for faster download
Browse files- .gitignore +1 -0
- app.py +40 -22
- download_video.py +37 -93
- requirements.txt +2 -3
.gitignore
CHANGED
@@ -166,3 +166,4 @@ cython_debug/
|
|
166 |
.DS_Store
|
167 |
*.mp4
|
168 |
*.m4v
|
|
|
|
166 |
.DS_Store
|
167 |
*.mp4
|
168 |
*.m4v
|
169 |
+
thumbnail.jpg
|
app.py
CHANGED
@@ -1,37 +1,36 @@
|
|
|
|
1 |
import whisper
|
2 |
import gradio as gr
|
3 |
-
import
|
4 |
|
5 |
import warnings
|
6 |
warnings.filterwarnings("ignore", category=FutureWarning, module="torch")
|
7 |
|
8 |
-
from download_video import download_mp3_selenium
|
9 |
-
|
10 |
# Function to download the audio, title, and thumbnail from YouTube
|
11 |
def download_video_info(url):
|
12 |
try:
|
13 |
-
# Call the function to download video and get title, thumbnail
|
14 |
-
title, thumbnail_url
|
15 |
-
audio_file = "downloaded_video.
|
16 |
|
17 |
-
return audio_file, title, thumbnail_url
|
18 |
except Exception as e:
|
19 |
return None, None, None, str(e)
|
20 |
|
21 |
# Function to transcribe the downloaded audio using Whisper
|
22 |
-
def transcribe_audio(audio_path, model_size="base"):
|
23 |
model = whisper.load_model(model_size)
|
24 |
-
result = model.transcribe(audio_path)
|
25 |
return result['text']
|
26 |
|
27 |
-
# Split logic: First fetch title
|
28 |
-
def get_video_info_and_transcribe(youtube_url, model_size="base"):
|
29 |
-
# Fetch title
|
30 |
-
audio_path, title, thumbnail_url
|
31 |
|
32 |
# If fetching video info fails
|
33 |
if not audio_path or not os.path.exists(audio_path):
|
34 |
-
return gr.update(value=
|
35 |
|
36 |
# Show title and thumbnail to the user while the transcription is happening
|
37 |
title_output = gr.update(value=title)
|
@@ -43,15 +42,36 @@ def get_video_info_and_transcribe(youtube_url, model_size="base"):
|
|
43 |
thumbnail_output = gr.update(visible=False) # Hide if no thumbnail
|
44 |
|
45 |
# Start transcription
|
46 |
-
transcription = transcribe_audio(audio_path, model_size)
|
47 |
|
48 |
-
return title_output, thumbnail_output, gr.update(value=transcription)
|
49 |
|
50 |
# Gradio interface setup using gradio.components
|
51 |
-
with gr.Blocks() as
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
with gr.Row():
|
53 |
youtube_url = gr.Textbox(label="YouTube Link", elem_id="yt_link", scale=5)
|
54 |
model_size = gr.Dropdown(choices=["tiny", "base", "small", "medium", "large"], label="Model Size", value="base", scale=1)
|
|
|
55 |
|
56 |
title_output = gr.Textbox(label="Video Title", interactive=False)
|
57 |
|
@@ -59,16 +79,14 @@ with gr.Blocks() as interface:
|
|
59 |
thumbnail_output = gr.Image(label="Thumbnail", interactive=False, scale=1)
|
60 |
transcription_output = gr.Textbox(label="Transcription", interactive=False, scale=1)
|
61 |
|
62 |
-
logs_output = gr.Textbox(label="ChromeDriver Logs", interactive=False)
|
63 |
-
|
64 |
transcribe_button = gr.Button("Transcribe")
|
65 |
|
66 |
transcribe_button.click(
|
67 |
get_video_info_and_transcribe,
|
68 |
-
inputs=[youtube_url, model_size],
|
69 |
-
outputs=[title_output, thumbnail_output, transcription_output
|
70 |
)
|
71 |
|
72 |
# Launch the app
|
73 |
if __name__ == "__main__":
|
74 |
-
|
|
|
1 |
+
import os
|
2 |
import whisper
|
3 |
import gradio as gr
|
4 |
+
from download_video import download_mp3_yt_dlp
|
5 |
|
6 |
import warnings
|
7 |
warnings.filterwarnings("ignore", category=FutureWarning, module="torch")
|
8 |
|
|
|
|
|
9 |
# Function to download the audio, title, and thumbnail from YouTube
|
10 |
def download_video_info(url):
|
11 |
try:
|
12 |
+
# Call the function to download video and get title, thumbnail
|
13 |
+
title, thumbnail_url = download_mp3_yt_dlp(url)
|
14 |
+
audio_file = "downloaded_video.mp3" # Path to the downloaded audio (MP3)
|
15 |
|
16 |
+
return audio_file, title, thumbnail_url
|
17 |
except Exception as e:
|
18 |
return None, None, None, str(e)
|
19 |
|
20 |
# Function to transcribe the downloaded audio using Whisper
|
21 |
+
def transcribe_audio(audio_path, model_size="base", language="en"):
|
22 |
model = whisper.load_model(model_size)
|
23 |
+
result = model.transcribe(audio_path, language=language)
|
24 |
return result['text']
|
25 |
|
26 |
+
# Split logic: First fetch title and thumbnail, then transcribe
|
27 |
+
def get_video_info_and_transcribe(youtube_url, model_size="base", language="en"):
|
28 |
+
# Fetch title and thumbnail first
|
29 |
+
audio_path, title, thumbnail_url = download_video_info(youtube_url)
|
30 |
|
31 |
# If fetching video info fails
|
32 |
if not audio_path or not os.path.exists(audio_path):
|
33 |
+
return gr.update(value="Error fetching video."), None, None
|
34 |
|
35 |
# Show title and thumbnail to the user while the transcription is happening
|
36 |
title_output = gr.update(value=title)
|
|
|
42 |
thumbnail_output = gr.update(visible=False) # Hide if no thumbnail
|
43 |
|
44 |
# Start transcription
|
45 |
+
transcription = transcribe_audio(audio_path, model_size, language)
|
46 |
|
47 |
+
return title_output, thumbnail_output, gr.update(value=transcription)
|
48 |
|
49 |
# Gradio interface setup using gradio.components
|
50 |
+
with gr.Blocks() as demo:
|
51 |
+
|
52 |
+
title = "<center><h1>YouTube Whisper ⚡️ </h1></center>"
|
53 |
+
gr.HTML(title)
|
54 |
+
|
55 |
+
gr.Markdown(
|
56 |
+
"""
|
57 |
+
This tool lets you transcribe YouTube videos in multiple languages using **[Whisper](https://openai.com/research/whisper)**, an open-source speech recognition (ASR) model developed by OpenAI.
|
58 |
+
|
59 |
+
|
60 |
+
### Key Features:
|
61 |
+
- **Fast transcription**: Using the **base** model, transcribing a **3 minute** video takes approximately **30 seconds**.
|
62 |
+
- **Multiple language support**: Choose from **English**, **Spanish**, **French**, and more!
|
63 |
+
- **Simple workflow**:
|
64 |
+
1. Paste a YouTube link.
|
65 |
+
2. Select the model size and language.
|
66 |
+
3. Click "Transcribe" to get the text from the video.
|
67 |
+
|
68 |
+
_Transcription times may vary based on model size and video length._
|
69 |
+
""")
|
70 |
+
|
71 |
with gr.Row():
|
72 |
youtube_url = gr.Textbox(label="YouTube Link", elem_id="yt_link", scale=5)
|
73 |
model_size = gr.Dropdown(choices=["tiny", "base", "small", "medium", "large"], label="Model Size", value="base", scale=1)
|
74 |
+
language = gr.Dropdown(choices=["en", "es", "fr", "de", "it", "ja"], label="Language", value="en", scale=1)
|
75 |
|
76 |
title_output = gr.Textbox(label="Video Title", interactive=False)
|
77 |
|
|
|
79 |
thumbnail_output = gr.Image(label="Thumbnail", interactive=False, scale=1)
|
80 |
transcription_output = gr.Textbox(label="Transcription", interactive=False, scale=1)
|
81 |
|
|
|
|
|
82 |
transcribe_button = gr.Button("Transcribe")
|
83 |
|
84 |
transcribe_button.click(
|
85 |
get_video_info_and_transcribe,
|
86 |
+
inputs=[youtube_url, model_size, language],
|
87 |
+
outputs=[title_output, thumbnail_output, transcription_output]
|
88 |
)
|
89 |
|
90 |
# Launch the app
|
91 |
if __name__ == "__main__":
|
92 |
+
demo.launch(server_name="0.0.0.0", server_port=7860)
|
download_video.py
CHANGED
@@ -1,102 +1,46 @@
|
|
1 |
-
|
2 |
-
from selenium.webdriver.chrome.service import Service
|
3 |
-
from selenium.webdriver.common.by import By
|
4 |
-
from selenium.webdriver.common.keys import Keys
|
5 |
-
from selenium.webdriver.support.ui import WebDriverWait
|
6 |
-
from selenium.webdriver.support import expected_conditions as EC
|
7 |
-
import os
|
8 |
import requests
|
9 |
|
10 |
-
def
|
11 |
-
# Set up
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
# Wait until the page is loaded completely by checking an element presence
|
39 |
-
wait.until(EC.presence_of_element_located((By.ID, "txt-url")))
|
40 |
-
|
41 |
-
# Input the YouTube URL into the downloader
|
42 |
-
input_box = driver.find_element(By.ID, "txt-url")
|
43 |
-
input_box.send_keys(youtube_url)
|
44 |
-
input_box.send_keys(Keys.RETURN)
|
45 |
-
|
46 |
-
# Wait for the MP3 download button to appear
|
47 |
-
mp3_download_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-ftype='mp3']")))
|
48 |
-
onclick_attr = mp3_download_button.get_attribute("onclick")
|
49 |
-
|
50 |
-
# Extract parameters from the JavaScript function call
|
51 |
-
params = onclick_attr.split("'")
|
52 |
-
if len(params) >= 7:
|
53 |
-
mp3_download_url = params[1] # Extracted base download URL
|
54 |
-
|
55 |
-
# Wait for the final download URL to be available after JavaScript modifications
|
56 |
-
final_link = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "a[href*='googlevideo.com/videoplayback']")))
|
57 |
-
mp3_download_url = final_link.get_attribute("href")
|
58 |
-
print(f"Final MP3 Download URL: {mp3_download_url}")
|
59 |
-
|
60 |
-
response = requests.get(mp3_download_url, stream=True)
|
61 |
-
|
62 |
-
# Check if the request was successful
|
63 |
if response.status_code == 200:
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
for chunk in response.iter_content(chunk_size=1024):
|
68 |
-
if chunk:
|
69 |
-
f.write(chunk)
|
70 |
-
print(f"Video downloaded successfully as {output_file}")
|
71 |
else:
|
72 |
-
print(f"Failed to download
|
73 |
-
|
74 |
-
else:
|
75 |
-
print("Failed to extract MP3 download link from the page.")
|
76 |
-
|
77 |
-
# Close the browser
|
78 |
-
driver.quit()
|
79 |
-
|
80 |
-
# Check and print ChromeDriver logs
|
81 |
-
log_file_path = '/tmp/chromedriver.log'
|
82 |
-
# Create a log file if it doesn't exist
|
83 |
-
if not os.path.exists(log_file_path):
|
84 |
-
with open(log_file_path, 'w') as log_file:
|
85 |
-
log_file.write("ChromeDriver log file created.")
|
86 |
-
|
87 |
-
if os.path.exists(log_file_path):
|
88 |
-
with open(log_file_path, 'r') as log_file:
|
89 |
-
log_contents = log_file.read()
|
90 |
-
print("ChromeDriver Log Contents:\n", log_contents)
|
91 |
-
else:
|
92 |
-
print("ChromeDriver log not found.")
|
93 |
-
|
94 |
|
95 |
-
# Return the title and thumbnail
|
96 |
-
return title, thumbnail_url
|
97 |
|
98 |
# Example usage:
|
99 |
# youtube_url = "https://youtu.be/MAZyQ-38b8M?si=q0dai-wF6FQz6MGN"
|
100 |
-
# title, thumbnail_url =
|
101 |
# print(f"Title: {title}")
|
102 |
-
# print(f"Thumbnail: {thumbnail_url}")
|
|
|
1 |
+
import yt_dlp as youtube_dl
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import requests
|
3 |
|
4 |
+
def download_mp3_yt_dlp(youtube_url):
|
5 |
+
# Set up yt-dlp options
|
6 |
+
ydl_opts = {
|
7 |
+
'format': 'bestaudio/best',
|
8 |
+
'postprocessors': [{
|
9 |
+
'key': 'FFmpegExtractAudio',
|
10 |
+
'preferredcodec': 'mp3',
|
11 |
+
'preferredquality': '192',
|
12 |
+
}],
|
13 |
+
'outtmpl': 'downloaded_video.%(ext)s',
|
14 |
+
'quiet': False,
|
15 |
+
'no_warnings': True,
|
16 |
+
'progress_hooks': [lambda d: print(f"Downloading {d['filename']}: {d['_percent_str']}")],
|
17 |
+
}
|
18 |
+
|
19 |
+
# Extract video info including title and thumbnail
|
20 |
+
with youtube_dl.YoutubeDL() as ydl:
|
21 |
+
info_dict = ydl.extract_info(youtube_url, download=False)
|
22 |
+
title = info_dict.get('title', 'Unknown Title')
|
23 |
+
thumbnail_url = info_dict.get('thumbnail', None)
|
24 |
+
|
25 |
+
# Download the MP3 using yt-dlp
|
26 |
+
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
|
27 |
+
ydl.download([youtube_url])
|
28 |
+
|
29 |
+
# Fetch the thumbnail for display
|
30 |
+
if thumbnail_url:
|
31 |
+
response = requests.get(thumbnail_url)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
if response.status_code == 200:
|
33 |
+
with open('thumbnail.jpg', 'wb') as f:
|
34 |
+
f.write(response.content)
|
35 |
+
print(f"Thumbnail downloaded successfully.")
|
|
|
|
|
|
|
|
|
36 |
else:
|
37 |
+
print(f"Failed to download thumbnail. HTTP Status Code: {response.status_code}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
+
# Return the title and thumbnail URL
|
40 |
+
return title, thumbnail_url
|
41 |
|
42 |
# Example usage:
|
43 |
# youtube_url = "https://youtu.be/MAZyQ-38b8M?si=q0dai-wF6FQz6MGN"
|
44 |
+
# title, thumbnail_url = download_mp3_yt_dlp(youtube_url)
|
45 |
# print(f"Title: {title}")
|
46 |
+
# print(f"Thumbnail: {thumbnail_url}")
|
requirements.txt
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
-
selenium
|
2 |
-
webdriver-manager
|
3 |
requests
|
4 |
gradio
|
5 |
openai-whisper @ git+https://github.com/openai/whisper.git
|
6 |
-
tqdm
|
|
|
|
|
|
|
|
1 |
requests
|
2 |
gradio
|
3 |
openai-whisper @ git+https://github.com/openai/whisper.git
|
4 |
+
tqdm
|
5 |
+
yt_dlp
|