danilotpnta commited on
Commit
f62c279
·
1 Parent(s): 48a5d9c

update: app and added yt_dlp for faster download

Browse files
Files changed (4) hide show
  1. .gitignore +1 -0
  2. app.py +40 -22
  3. download_video.py +37 -93
  4. 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 os
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, and logs
14
- title, thumbnail_url, logs_output = download_mp3_selenium(url)
15
- audio_file = "downloaded_video.mp4" # Path to the downloaded audio (MP4)
16
 
17
- return audio_file, title, thumbnail_url, logs_output
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, thumbnail, and logs, then transcribe
28
- def get_video_info_and_transcribe(youtube_url, model_size="base"):
29
- # Fetch title, thumbnail, and logs first
30
- audio_path, title, thumbnail_url, logs_output = download_video_info(youtube_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=f"Error fetching video: {thumbnail_url}"), None, None, gr.update(value=logs_output)
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), gr.update(value=logs_output)
49
 
50
  # Gradio interface setup using gradio.components
51
- with gr.Blocks() as interface:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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, logs_output]
70
  )
71
 
72
  # Launch the app
73
  if __name__ == "__main__":
74
- interface.launch(server_name="0.0.0.0", server_port=7860)
 
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
- from selenium import webdriver
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 download_mp3_selenium(youtube_url):
11
- # Set up the Selenium WebDriver
12
- options = webdriver.ChromeOptions()
13
- options.add_argument("--headless")
14
- options.add_argument("--no-sandbox")
15
- options.add_argument('--disable-dev-shm-usage')
16
- options.add_argument('--disable-gpu') # Disable GPU to ensure it runs in cloud environments
17
-
18
- log_contents = "" # Initialize log_contents
19
- driver = webdriver.Chrome(options=options)
20
-
21
- # Set up WebDriverWait (with a timeout of 10 seconds)
22
- wait = WebDriverWait(driver, 20)
23
-
24
- # Open the YouTube video page
25
- driver.get(youtube_url)
26
- # Wait for the title to be available
27
- wait.until(EC.title_contains("YouTube"))
28
-
29
- # Scrape the title
30
- title = driver.title # This gives you the video title
31
-
32
- # Wait for the thumbnail to load and scrape it
33
- thumbnail_meta = wait.until(EC.presence_of_element_located((By.XPATH, "//meta[@property='og:image']")))
34
- thumbnail_url = thumbnail_meta.get_attribute('content')
35
-
36
- # Open the YouTube downloader site
37
- driver.get("https://yt1d.com/en/")
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
- # Write the video content to a file
65
- output_file = "downloaded_video.mp4"
66
- with open(output_file, "wb") as f:
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 video. HTTP Status Code: {response.status_code}")
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 for display
96
- return title, thumbnail_url, log_contents
97
 
98
  # Example usage:
99
  # youtube_url = "https://youtu.be/MAZyQ-38b8M?si=q0dai-wF6FQz6MGN"
100
- # title, thumbnail_url = download_mp3_selenium(youtube_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