Efficient Video Downloading
Introduction
In educational settings, such as lectures and presentations, the utilization of video content from platforms like YouTube can significantly enhance explanatory efforts. While numerous online tools exist for downloading videos locally, they often present challenges such as intrusive advertisements and inefficiency when handling multiple downloads. To address these issues, I have developed a Python script that streamlines this process. This article will elucidate the functionality and implementation of this tool.
Important Considerations
It is crucial to emphasize the importance of adhering to copyright laws and regulations. When utilizing this tool, one must ensure that the selected videos are either under Creative Commons licenses or that proper permissions have been obtained. Additionally, the use of copyrighted materials for educational purposes may have specific guidelines that must be carefully reviewed and followed.
Script Overview
The developed Python script offers the following key functionalities:
Input Flexibility: The script can process video URLs from either command-line arguments or a CSV file, allowing for both individual and batch processing of videos.
Download Execution: It facilitates the downloading of video content from various platforms, including YouTube, with options for both video and audio-only downloads.
Time Range Specification: Users can define specific start and end times for video downloads, enabling the extraction of relevant segments rather than entire videos.
Progress Monitoring: The script implements a progress bar to display download status and provides completion notifications.
Environment Setup
To utilize this script, the following environmental configurations are necessary:
# For mac
brew install ffmpeg
# For ubuntu
sudo apt update && sudo apt install ffmpeg -y
Creation of a Conda virtual environment:
mkdir video_downloader
cd video_downloader
nano video_downloader.yml
# video_downloader.yml
name: video_downloader
channels:
- defaults
- conda-forge
dependencies:
- python=3.12
- yt-dlp
- tqdm
conda env create -f video_downloader.yml
conda activate video_downloader
Script Implementation
import argparse
import os
import yt_dlp
import csv
from tqdm import tqdm
class DownloadProgress:
def __init__(self):
self.pbar = None
def download_hook(self, d):
if d['status'] == 'downloading':
if self.pbar is None:
total = d.get('total_bytes') or d.get('total_bytes_estimate')
self.pbar = tqdm(total=total, unit='B', unit_scale=True, desc=d['filename'])
downloaded = d.get('downloaded_bytes', 0)
self.pbar.update(downloaded - self.pbar.n)
elif d['status'] == 'finished':
if self.pbar is not None:
self.pbar.close()
print(f"Download completed. Converting...")
def download_media(url, quality, format, audio_only, audio_quality, output_dir, start_time, end_time):
progress = DownloadProgress()
if audio_only:
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': format,
'preferredquality': str(audio_quality),
}],
'outtmpl': os.path.join(output_dir, '%(title)s.%(ext)s'),
'quiet': True,
'no_warnings': True,
'progress_hooks': [progress.download_hook],
}
else:
ydl_opts = {
'format': f'{format}[height<={quality}]' if quality else f'{format}/bestvideo+bestaudio/best',
'outtmpl': os.path.join(output_dir, '%(title)s.%(ext)s'),
'quiet': True,
'no_warnings': True,
'progress_hooks': [progress.download_hook],
}
# Add time range options if specified
if start_time or end_time:
ydl_opts['download_ranges'] = download_range_func(start_time, end_time)
ydl_opts['force_generic_extractor'] = True
# Error handling options
ydl_opts.update({
'ignoreerrors': True,
'no_color': True,
'geo_bypass': True,
'nocheckcertificate': True,
'extractor_args': {'youtube': {'skip': ['dash', 'hls']}},
})
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
try:
ydl.download([url])
print(f"Media saved in {output_dir}")
except Exception as e:
print(f"An error occurred: {str(e)}")
print("Trying alternative method...")
try:
ydl_opts['format'] = 'bestvideo+bestaudio/best'
ydl.download([url])
print(f"Media saved in {output_dir} using alternative method")
except Exception as e:
print(f"Alternative method also failed: {str(e)}")
print("Please try updating yt-dlp or check if the video is available in your region.")
def download_range_func(start_time, end_time):
start_seconds = time_to_seconds(start_time)
end_seconds = time_to_seconds(end_time)
def func(info_dict, ydl_obj):
return [{
'start_time': start_seconds,
'end_time': end_seconds,
}]
return func
def time_to_seconds(time_str):
if time_str:
h, m, s = map(int, time_str.split(':'))
return h * 3600 + m * 60 + s
return None
def read_urls_from_csv(file_path):
"""Reads a CSV file and extracts URLs from it."""
urls = []
with open(file_path, newline='') as csvfile:
reader = csv.reader(csvfile)
for row in reader:
if row: # Check if row is not empty
urls.append(row[0]) # Assuming URLs are in the first column
return urls
def main():
parser = argparse.ArgumentParser(description="Video/Audio Downloader")
parser.add_argument("url", nargs='?', help="URL of the video (if not using --file)")
parser.add_argument("-q", "--quality", type=int, default=1080,
choices=[1080, 720, 480, 360],
help="Maximum video quality (height in pixels). "
"Choices are 1080 (default), 720, 480, or 360. "
"The highest available quality not exceeding "
"this value will be downloaded. "
"Ignored if --audio-only is used.")
parser.add_argument("-f", "--format", default="mp4",
help="Desired media format (default: mp4). "
"For video: mp4, webm, mkv. "
"For audio (with --audio-only): mp3, m4a, wav, etc.")
parser.add_argument("-o", "--output", default=".",
help="Output directory (default: current directory)")
parser.add_argument("--audio-only", action="store_true",
help="Download audio only")
parser.add_argument("--audio-quality", type=int, default=192,
help="Audio bitrate in kbps (default: 192). "
"Common values: 128, 192, 256, 320. "
"Only applicable with --audio-only.")
parser.add_argument("--start-time", type=str,
help="Start time of the video (format: HH:MM:SS)")
parser.add_argument("--end-time", type=str,
help="End time of the video (format: HH:MM:SS)")
parser.add_argument("--file", type=str,
help="Path to a CSV file containing URLs of videos to download")
args = parser.parse_args()
if not os.path.exists(args.output):
os.makedirs(args.output)
if args.file:
# If a file is specified, read URLs from the file and download each video
urls = read_urls_from_csv(args.file)
for url in urls:
download_media(url, args.quality, args.format, args.audio_only, args.audio_quality,
args.output, args.start_time, args.end_time)
elif args.url:
# If a URL is specified, download the single video
download_media(args.url, args.quality, args.format, args.audio_only, args.audio_quality,
args.output, args.start_time, args.end_time)
else:
print("Error: You must provide either a URL or a CSV file with the --file option.")
parser.print_help()
if __name__ == "__main__":
main()
Usage Instructions
python video_downloader.py --help
usage: video_downloader.py [-h] [-q {1080,720,480,360}] [-f FORMAT] [-o OUTPUT] [--audio-only] [--audio-quality AUDIO_QUALITY]
[--start-time START_TIME] [--end-time END_TIME] [--file FILE]
[url]
YouTube Video/Audio Downloader
positional arguments:
url URL of the video (if not using --file)
options:
-h, --help show this help message and exit
-q {1080,720,480,360}, --quality {1080,720,480,360}
Maximum video quality (height in pixels). Choices are 1080 (default), 720, 480, or 360. The highest
available quality not exceeding this value will be downloaded. Ignored if --audio-only is used.
-f FORMAT, --format FORMAT
Desired media format (default: mp4). For video: mp4, webm, mkv. For audio (with --audio-only): mp3, m4a,
wav, etc.
-o OUTPUT, --output OUTPUT
Output directory (default: current directory)
--audio-only Download audio only
--audio-quality AUDIO_QUALITY
Audio bitrate in kbps (default: 192). Common values: 128, 192, 256, 320. Only applicable with --audio-only.
--start-time START_TIME
Start time of the video (format: HH:MM:SS)
--end-time END_TIME End time of the video (format: HH:MM:SS)
--file FILE Path to a CSV file containing URLs of videos to download
Usage Examples
Standard Usage (Default Settings):
python video_downloader.py "https://www.example.com/video"
This command employs the script with its default configuration to download a single video.
Batch Download of Multiple Videos:
python video_downloader.py --file videos.csv
This command facilitates the simultaneous download of multiple videos listed in a CSV file.
Example CSV file content:
Copyhttps://example.com/video1
https://example.com/video2
https://example.com/video3
Quality-Specific Download:
python video_downloader.py "https://www.example.com/video" -q 360
This command specifies a maximum video quality of 360p.
Format-Specific Download:
python video_downloader.py "https://www.example.com/video" -f webm
This command requests the video in WebM format.
Quality and Format Specification:
python video_downloader.py "https://www.example.com/video" -q 480 -f mp4
This command combines quality (480p) and format (MP4) specifications.
Custom Output Directory:
python video_downloader.py "https://www.example.com/video" -o ~/Downloads
This command designates a specific directory for the downloaded content.
Audio-Only Download:
python video_downloader.py "https://www.example.com/video" --audio-only
This command extracts only the audio from the video.
Audio Download with Specific Quality and Format:
python video_downloader.py "https://www.example.com/video" --audio-only -f m4a --audio-quality 256
This command downloads audio in M4A format with a bitrate of 256 kbps.
Playlist Video Download:
python video_downloader.py "https://www.example.com/playlist"
This command downloads a specific video from a playlist.
Minimum Quality Download (Data Conservation):
python video_downloader.py "https://www.example.com/video" -q 360
This command limits the download to 360p quality, which is useful for conserving data.
Custom Filename Download:
python video_downloader.py "https://www.example.com/video" -o "~/Videos/%(title)s-%(resolution)s.%(ext)s"
This command specifies a custom filename pattern for the downloaded video, incorporating the title, resolution, and file extension.
Conclusion
This Python script offers an efficient solution for downloading video content for educational purposes. By automating the download process and providing options for customization, it significantly reduces the time and effort required for manual downloads. This tool can enhance productivity in educational content preparation, allowing educators to allocate more time to other critical aspects of their work.
It is imperative to reiterate the importance of copyright compliance. Users must ensure they have the necessary rights or permissions for any content downloaded using this tool, particularly in educational contexts where specific usage guidelines may apply.
Future iterations of this tool may incorporate additional features based on user feedback and evolving needs in educational technology. Suggestions for improvements or questions regarding the script's functionality are welcome and can be submitted through the appropriate channels.