53 lines
2.2 KiB
Python
53 lines
2.2 KiB
Python
import yt_dlp
|
|
import os
|
|
import time
|
|
|
|
def download_audio(url, output_folder, max_length_seconds=600):
|
|
"""
|
|
Downloads audio from a YouTube URL.
|
|
Returns the path to the downloaded file or raises an Exception.
|
|
Enforces max_length_seconds (default 10 mins).
|
|
"""
|
|
|
|
timestamp = int(time.time())
|
|
output_template = os.path.join(output_folder, f'yt_{timestamp}_%(id)s.%(ext)s')
|
|
|
|
ydl_opts = {
|
|
'format': 'bestaudio/best',
|
|
'outtmpl': output_template,
|
|
'postprocessors': [{
|
|
'key': 'FFmpegExtractAudio',
|
|
'preferredcodec': 'mp3',
|
|
'preferredquality': '192',
|
|
}],
|
|
'quiet': True,
|
|
'no_warnings': True,
|
|
'noplaylist': True,
|
|
'match_filter': yt_dlp.utils.match_filter_func("duration <= " + str(max_length_seconds))
|
|
}
|
|
|
|
try:
|
|
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
info = ydl.extract_info(url, download=True)
|
|
# The file path might differ slightly because of the postprocessor (mp3 conversion)
|
|
# yt-dlp usually returns the final filename in 'requested_downloads' or similar,
|
|
# but constructing it from info is safer if we know the template.
|
|
# However, extract_info returns the info dict.
|
|
|
|
# Since we force mp3, the file will end in .mp3
|
|
# We used %(id)s in template, so we can reconstruct or find it.
|
|
|
|
# Let's find the file in the folder that matches the timestamp prefix
|
|
# This is safer than guessing what yt-dlp named it exactly
|
|
|
|
valid_files = [f for f in os.listdir(output_folder) if f.startswith(f'yt_{timestamp}_') and f.endswith('.mp3')]
|
|
if not valid_files:
|
|
raise Exception("Download failed: Audio file not found after processing.")
|
|
|
|
return os.path.join(output_folder, valid_files[0])
|
|
|
|
except yt_dlp.utils.DownloadError as e:
|
|
if "video is too long" in str(e).lower() or "duration" in str(e).lower():
|
|
raise Exception(f"Video is too long. Maximum allowed duration is {max_length_seconds} seconds.")
|
|
raise Exception(f"Failed to download video: {str(e)}")
|