-
Notifications
You must be signed in to change notification settings - Fork 1
/
YoutubeDownloader.py
140 lines (105 loc) · 4.06 KB
/
YoutubeDownloader.py
1
2
3
4
5
6
7
8
9
10
11
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# -*- coding: utf-8 -*-
# !/usr/bin/python3
# sudo apt install ffmpeg -y
import os
import re
import shutil
import sys
from pytube import YouTube, Channel, Playlist
def checkURL():
# Set Channel/Playlist
try:
p = Channel(YoutubeURL)
print("INFO: Youtube Channel - " + p.channel_name)
except Exception:
try:
p = Playlist(YoutubeURL)
print("INFO: Playlist: " + p.title)
except Exception:
print("ERROR - Couldn't reach Channel or Playlist - " + YoutubeURL)
return None
return p
def download(vodURL):
# Get video
video = YouTube(vodURL)
print("INFO - Video: " + video.title)
# Download the best video quality
print("INFO - Downloading video")
video_only = video.streams.filter(type='video').order_by('resolution').last()
video_only.download(filename=tmpVideo)
# Download the best audio quality
print("INFO - Downloading audio")
audio_only = video.streams.filter(type='audio').order_by('abr').last()
audio_only.download(filename=tmpAudio)
return video
def process(video, idx):
print("INFO - Processing")
# Set filename, fullPath and temporary video/audio files
# Set titles, allow only Alphanumeric and " .,_-" -> Remove multi-spaces
title = re.sub('\s+', ' ', re.sub(r'[^A-Za-z0-9 .,_-]+', '', video.title)).strip()
filename = idx + " - " + title
fullPath = os.path.join(folderPath, filename + ".mp4")
# Merge two files
cmd = "ffmpeg -i '" + tmpVideo + "' -i '" + tmpAudio + "' -c:v copy -c:a aac '" + fullPath + "' -loglevel error"
os.system(cmd)
# Set modified date of file with video publication date
pubDate = video.publish_date.timestamp()
os.utime(fullPath, (pubDate, pubDate))
# Remove tmp video/audio files
os.remove(tmpVideo)
os.remove(tmpAudio)
def writeLog(failedVideos):
# Create log file for unsuccessful videos
with open(os.path.join(folderPath, "log.txt"), "w") as logFile:
for idx, vodURL in failedVideos.items():
logFile.write(idx + " - " + vodURL + "\n")
logFile.close()
def main():
print("--------------------------------\n")
os.chdir(os.path.dirname(os.path.abspath(__file__)))
# Check if folder already exists ? Empty : Create
if os.path.exists(folderPath):
shutil.rmtree(folderPath)
os.mkdir(folderPath)
# Start from oldest to newest | Failed videos track | Number total videos
# Set number of total videos and numbering format
video_urls, failedVideos = list(reversed(yt.video_urls)), {}
formatIdx = "{:0" + str(len(str(len(video_urls)))) + "}"
# Iterate over every video URL
for idx, vodURL in enumerate(video_urls):
# Set index format (001, 002, 003, ..., 323)
idx = formatIdx.format(idx + 1)
# Show progress
percentage = str(round(int(idx) / len(video_urls) * 100, 2)) + "%"
print(percentage + " - " + idx + "/" + str(len(video_urls)) + "(" + str(len(failedVideos)) + ") - " + vodURL)
try:
# Download Video -> Process video
video = download(vodURL)
process(video, idx)
# Success
print("INFO - Download Successful")
except Exception:
print("ERROR: Failed - " + vodURL)
failedVideos[idx] = vodURL
print("\n--------------------------------\n")
# Create log file for unsuccessful videos
if len(failedVideos) != 0:
writeLog(failedVideos)
print("--------------------------------")
print("INFO - Finished Downloading")
print("INFO - Failed Videos: " + formatIdx.format(len(failedVideos)))
print("INFO - Location:" + sys.argv[2])
return True
if __name__ == '__main__':
if len(sys.argv) < 3:
print("script.py playlist folder")
exit()
# Global Variables
YoutubeURL = sys.argv[1]
folderPath = sys.argv[2]
tmpVideo, tmpAudio = os.path.join(folderPath, "tmp_video"), os.path.join(folderPath, "tmp_audio")
# Check YoutubeURL ? Run main : exit
yt = checkURL()
if yt:
main()
exit()