diff --git a/__pycache__/backend.cpython-39.pyc b/__pycache__/backend.cpython-39.pyc index aeff24d..fe8decf 100644 Binary files a/__pycache__/backend.cpython-39.pyc and b/__pycache__/backend.cpython-39.pyc differ diff --git a/backend.py b/backend.py index 06bcba0..d1d6d9c 100644 --- a/backend.py +++ b/backend.py @@ -1,5 +1,6 @@ from pytube import YouTube -import ffmpeg +import datetime +import os class Downloader: def __init__(self): @@ -9,7 +10,7 @@ def set_url(self, url): self.youtube = YouTube(url) def get_videos(self): - return [stream for stream in self.youtube.streams.filter(only_video=True)] + return [stream for stream in self.youtube.streams.filter(only_video=True, video_codec="vp9")] def get_audios(self): return [stream for stream in self.youtube.streams.filter(only_audio=True)] @@ -17,11 +18,58 @@ def get_audios(self): def get_audio_videos(self): return [stream for stream in self.youtube.streams.filter(progressive=True)] - def combine_audio_video(self, audio, video): - pass - #video_stream = ffmpeg.input(video.download().split("//")[-1]) - #audio_stream = ffmpeg.input(audio.download().split("//")[-1]) - #ffmpeg.output(audio_stream, video_stream, 'out.mp4').run() + def find_video(self, resolution, fps): + video = None + + for stream in self.get_videos(): + if str(stream.resolution) == resolution: + if str(stream.fps) == fps: + video = stream + break + + return video + + def find_audio(self, bitrate): + audio = None + + for stream in self.get_audios(): + print(bitrate) + print(stream.abr) + if str(stream.abr) == bitrate: + audio = stream + break + + print(audio) + return audio + + def find_audio_videos(self, resolution, fps, bitrate): + video = None + + for stream in self.get_audio_videos(): + if str(stream.resolution) == resolution: + if str(stream.fps) == fps: + if str(stream.abr) == bitrate: + video = stream + break + + print(video) + return video + + def download(self, video): + print(video) + local_path = video.download() + fname = local_path.split("//")[-1] + + return fname + def get_title(self): + return self.youtube.title + + def get_thumbnail(self): + return self.youtube.thumbnail_url + + def get_views(self): + return self.youtube.views - #fix this \ No newline at end of file + def get_duration(self): + return str(datetime.timedelta(seconds=self.youtube.length)) diff --git a/main.py b/main.py index 0cacc88..b0c57ec 100644 --- a/main.py +++ b/main.py @@ -5,6 +5,7 @@ app = Flask(__name__) downloader = Downloader() +app.secret_key = "37825789567878456784867878680" @app.context_processor def override_url_for(): @@ -23,19 +24,40 @@ def dated_url_for(endpoint, **values): @app.route("/", methods=["POST", "GET"]) def home(): if request.method == "POST": - url = request.form["ur"] - downloader.set_url(url) - videos = downloader.get_videos() - audios = downloader.get_audios() - audiovideos = downloader.get_audio_videos() + if "video_button" in request.form: + quality_list = request.form["video_button"].split(",") + video = downloader.find_video(quality_list[0], quality_list[1]) + fname = downloader.download(video) + return send_file(fname, as_attachment=True) + elif "audio_button" in request.form: + video = downloader.find_audio(request.form["audio_button"]) + fname = downloader.download(video) + return send_file(fname, as_attachment=True) + elif "audiovideo_button" in request.form: + quality_list = request.form["audiovideo_button"].split(",") + video = downloader.find_audio_videos(quality_list[0], quality_list[1], quality_list[2]) + fname = downloader.download(video) + return send_file(fname, as_attachment=True) + else: + url = request.form["ur"] + session["url"] = url + downloader.set_url(session["url"]) + videos = downloader.get_videos() + audios = downloader.get_audios() + audiovideos = downloader.get_audio_videos() + title = downloader.get_title() + thumbnail = downloader.get_thumbnail() + views = downloader.get_views() + duration = downloader.get_duration() - print(videos) - print(audios) - print(audiovideos) + print(duration) - return render_template("index.html") + return render_template("index.html", url=session["url"], videos=videos, audios=audios, audiovideos=audiovideos, title=title, thumbnail=thumbnail, views=views, duration=duration) else: - return render_template("index.html") + if "url" in session: + return render_template("index.html", url=session["url"]) + else: + return render_template("index.html", url="") @app.route("/about") def about(): @@ -46,5 +68,5 @@ def contact(): return "contact" if __name__ == "__main__": - app.run(debug=True, host="0.0.0.0") + app.run(debug=True) diff --git a/static/base.css b/static/base.css index ae318b8..f45d2af 100644 --- a/static/base.css +++ b/static/base.css @@ -4,7 +4,7 @@ --hover: #4b4b4b; --main-text-color: #ffffff; --secondary-text-color: #aaaaaa; - --red: #ff0000; + --red: #c00; --search-color: #121212; --search-color-2: #313131; --search-color-3: #585858; diff --git a/static/index.css b/static/index.css index 54a0265..4fb6d7e 100644 --- a/static/index.css +++ b/static/index.css @@ -16,7 +16,7 @@ color: var(--secondary-text-color); } -.center-container form { +.center-container .form { margin-top: 2rem; background-color: var(--secondary-bg-color); padding: 1.5rem 2rem; @@ -29,7 +29,7 @@ } .center-container form input[type=search] { - padding: 1.5rem 2rem; + padding: 1.5% 2%; box-sizing: border-box; border: 1px solid var(--main-bg-color); background-color: var(--search-color); @@ -45,8 +45,8 @@ color: var(--secondary-text-color); } -.center-container form button { - padding: 1.5rem 2rem; +.center-container form .search_button { + padding: 1.5% 2%; flex: 1; background-color: var(--search-color-2); border: 1px solid var(--main-bg-color); @@ -54,6 +54,114 @@ font-size: 1.1rem; } -.center-container form button:hover { +.center-container form .search_button:hover { + color: var(--main-text-color); +} + +.result_container { + display: flex; + flex-direction: row; + justify-content: space-between; + width: 90%; + gap: 2%; +} + +.downloads { + display: grid; + grid-template-areas: "video videoaudio audio"; + height: 100%; + grid-template-rows: auto auto auto; + margin-top: 2%; + flex: 3; +} + +.video { + grid-area: video; +} + +.videoaudio { + grid-area: videoaudio; +} + +.audio { + grid-area: audio; +} + +.downloads h2 { + margin-bottom: 5%; + color: var(--secondary-text-color) +} + +.result_box { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.result_box p { + margin-right: 2%; + color: var(--secondary-text-color); +} + +.result_box button { + padding: 10% 20%; + text-transform: uppercase; color: var(--main-text-color); + background-color: var(--red); + border: none; + border-radius: 25px; + cursor: pointer; } + +.main_text { + color: var(--main-text-color) !important; +} + +.videoaudio p { + color: var(--main-text-color) !important; +} + +.information { + margin-top: 2%; + margin-right: auto; + display: flex; + flex-direction: column; + flex: 2; +} + +.information h2 { + margin-right: auto; +} + +.information img { + max-width: 100%; + max-height: 100%; + margin-right: auto; + margin-bottom: 2%; +} + +.information p { + margin-right: auto; +} + +@media only screen and (max-width: 1370px) { + .downloads { + grid-template-areas: "videoaudio" + "video" + "audio"; + width: 100%; + } +} + +@media only screen and (max-width: 600px) { + .information { + display: none; + } +} + +@media only screen and (min-width: 600px) { + .downloads { + margin-left: auto; + } +} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 5784147..11ade79 100644 --- a/templates/index.html +++ b/templates/index.html @@ -8,8 +8,52 @@

YT Buddy

Convert and download YouTube video and audio online, for free.

- - + +
+ {% if audiovideos is defined %} +
+
+

{{ title }}

+ +

Views: {{ views }}

+

Duration: {{ duration }}

+
+
+
+

Video Only

+ {% for video in videos %} +
+

{{ video.resolution }}, {{ video.fps }} fps

+
+ +
+
+ {% endfor %} +
+
+

Video & Audio (Recommended)

+ {% for av in audiovideos %} +
+

{{ av.resolution }}, {{ av.fps }} fps, {{ av.abr }}

+
+ +
+
+ {% endfor %} +
+
+

Audio Only

+ {% for audio in audios %} +
+

{{ audio.abr }}

+
+ +
+
+ {% endfor %} +
+
+ {% endif %}
{% endblock %} \ No newline at end of file