Alot of misc changes and fixes. Titles with a forward slash are now being corrected for insert in db.
This commit is contained in:
parent
f6eb82ed6a
commit
306d3b6c88
@ -5,13 +5,12 @@ YouTube Media Library Server aims to make downloading and updating media librari
|
||||
- Download of channels, playlists and videos in mp3 or mp4
|
||||
- Download of processed files either individually or entire channels and playlists as a .zip
|
||||
- Update of channels and playlists from the library
|
||||
- Watching videos via an embed
|
||||
|
||||
|
||||
# currently not supported
|
||||
Having the same video in mp3 _and_ mp4 is not possible with how the download process and database work. This includes channels and playlists. The chosen type on initial download dictates what you have.
|
||||
|
||||
Deleting files will be added soon:tm:.
|
||||
|
||||
|
||||
# media sources
|
||||
Currently supported is YouTube but its possible expand since the download itself is handled by yt-dlp.
|
||||
|
47
backend.py
47
backend.py
@ -82,7 +82,10 @@ def process_download(url, ext, parent, query, current_thread):
|
||||
try:
|
||||
# this throws KeyError when downloading single file
|
||||
for video in query['entries']:
|
||||
if video is not None and check_already_exists(video['id']):
|
||||
if video is None:
|
||||
continue
|
||||
|
||||
if check_already_exists(video['id']):
|
||||
add_new_video_to_collection(parent, video['id'])
|
||||
continue
|
||||
|
||||
@ -91,11 +94,14 @@ def process_download(url, ext, parent, query, current_thread):
|
||||
download=False)
|
||||
|
||||
# replace url with name of playlist
|
||||
queued_downloads[0][0] = parent
|
||||
queued_downloads[0][0] = parent.replace('/', '⧸')
|
||||
|
||||
if max_video_length and video['duration'] > max_video_length:
|
||||
continue
|
||||
|
||||
# add new entry to file_cache
|
||||
ids.append(video['id'])
|
||||
titles.append(video['title'])
|
||||
titles.append(video['title'].replace('/', '⧸'))
|
||||
urls.append('https://www.youtube.com/watch?v=' + video['id'])
|
||||
|
||||
# start download
|
||||
@ -113,18 +119,24 @@ def process_download(url, ext, parent, query, current_thread):
|
||||
for tab in query['entries']:
|
||||
# for every video in their respective tabs
|
||||
for video in tab['entries']:
|
||||
if video is not None and check_already_exists(video['id']):
|
||||
if video is None:
|
||||
continue
|
||||
|
||||
if check_already_exists(video['id']):
|
||||
add_new_video_to_collection(parent, video['id'])
|
||||
continue
|
||||
|
||||
# replace url with name of channel
|
||||
queued_downloads[0][0] = parent
|
||||
queued_downloads[0][0] = parent.replace('/', '⧸')
|
||||
|
||||
if max_video_length and video['duration'] > max_video_length:
|
||||
continue
|
||||
|
||||
# there have been cases of duplicate urls or some with '/watch?v=@channel_name'
|
||||
# but no consistency has been observed
|
||||
# still works though so will not be checked for now
|
||||
ids.append(video['id'])
|
||||
titles.append(video['title'])
|
||||
titles.append(video['title'].replace('/', '⧸'))
|
||||
urls.append('https://www.youtube.com/watch?v=' + video['id'])
|
||||
|
||||
# start download
|
||||
@ -141,11 +153,11 @@ def process_download(url, ext, parent, query, current_thread):
|
||||
# when downloading single files that already exist, there's no need for adjustments in db
|
||||
if not check_already_exists(query['id']):
|
||||
ids.append(query['id'])
|
||||
titles.append(query['title'])
|
||||
titles.append(query['title'].replace('/', '⧸'))
|
||||
urls.append('https://www.youtube.com/watch?v=' + query['id'])
|
||||
|
||||
# replace url with name of video
|
||||
queued_downloads[0][0] = query['title']
|
||||
queued_downloads[0][0] = query['title'].replace('/', '⧸')
|
||||
|
||||
# start download
|
||||
download_all(url, ext=ext)
|
||||
@ -167,6 +179,9 @@ def process_update(parent, query, current_thread):
|
||||
try:
|
||||
# this throws KeyError when downloading single file
|
||||
for video in query['entries']:
|
||||
if video is None:
|
||||
continue
|
||||
|
||||
if check_already_exists(video['id']):
|
||||
add_new_video_to_collection(parent, video['id'])
|
||||
continue
|
||||
@ -175,6 +190,9 @@ def process_update(parent, query, current_thread):
|
||||
ydl.YoutubeDL({'quiet': True}).extract_info('https://www.youtube.com/watch?v=' + video['id'],
|
||||
download=False)
|
||||
|
||||
if max_video_length and video['duration'] > max_video_length:
|
||||
continue
|
||||
|
||||
# add new entry to file_cache
|
||||
ids.append(video['id'])
|
||||
titles.append(video['title'])
|
||||
@ -195,10 +213,16 @@ def process_update(parent, query, current_thread):
|
||||
for tab in query['entries']:
|
||||
# for every video in their respective tabs
|
||||
for video in tab['entries']:
|
||||
if video is None:
|
||||
continue
|
||||
|
||||
if check_already_exists(video['id']):
|
||||
add_new_video_to_collection(parent, video['id'])
|
||||
continue
|
||||
|
||||
if max_video_length and video['duration'] > max_video_length:
|
||||
continue
|
||||
|
||||
# there have been cases of duplicate urls or some with '/watch?v=@channel_name'
|
||||
# but no consistency has been observed
|
||||
# still works though so will not be checked for now
|
||||
@ -339,7 +363,7 @@ def yt_download(location, ext='mp3'):
|
||||
# if videos are wanted, adjust the options
|
||||
if ext == 'mp4':
|
||||
opts['format'] = 'bestvideo[height<=1080]+bestaudio/best[height<=1080]'
|
||||
opts.pop('format')
|
||||
opts['merge_output_format'] = 'mp4'
|
||||
opts.pop('postprocessors')
|
||||
|
||||
# try to download all new files
|
||||
@ -455,3 +479,8 @@ def delete_file_or_playlist(file_name):
|
||||
rmtree(downloads_path() + folder)
|
||||
return
|
||||
|
||||
|
||||
# checks if file is somewhere in downloads directory and returns true if so
|
||||
def check_file_path(path):
|
||||
downloads = downloads_path()
|
||||
return downloads in os.path.abspath(downloads + path)
|
||||
|
@ -3,3 +3,4 @@ titles = []
|
||||
urls = []
|
||||
thread_queue = []
|
||||
queued_downloads = []
|
||||
max_video_length = 600
|
||||
|
26
frontend.py
26
frontend.py
@ -1,5 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os.path
|
||||
|
||||
from flask import (
|
||||
Blueprint,
|
||||
request,
|
||||
@ -14,7 +16,8 @@ from backend import (
|
||||
zip_folder_not_in_directory,
|
||||
enqueue_download,
|
||||
internet_available,
|
||||
delete_file_or_playlist
|
||||
delete_file_or_playlist,
|
||||
check_file_path
|
||||
)
|
||||
from forms.download import DownloadForm
|
||||
from db_tools import query_db
|
||||
@ -50,7 +53,7 @@ def downloader():
|
||||
# if there has been a problem with the form (empty or error) or the link is not valid
|
||||
if not form.validate_on_submit() or not valid_link:
|
||||
valid_link = True if url == 'None' else False # if url is empty, don't show error
|
||||
return render_template('downloader.html', form=form, ytLink=valid_link, amount=len(urls))
|
||||
return render_template('downloader.html', form=form, amount=len(urls))
|
||||
|
||||
if not internet_available():
|
||||
flash('No internet connection available.', 'danger')
|
||||
@ -113,7 +116,6 @@ def download():
|
||||
# else a directory is requested
|
||||
else:
|
||||
zip_path, zip_name = zip_folder(file_path)
|
||||
print(zip_path, zip_name)
|
||||
zip_folder_not_in_directory(zip_path + zip_name)
|
||||
|
||||
# zip and send
|
||||
@ -155,23 +157,25 @@ def update():
|
||||
# todo: add functionality to library
|
||||
@frontend.route('/player', methods=['GET'])
|
||||
def player():
|
||||
return render_template('video-player.html')
|
||||
return render_template('player.html', file=request.args.get('file'))
|
||||
|
||||
|
||||
@frontend.route('/serve', methods=['GET'])
|
||||
def serve():
|
||||
file = request.args.get('file', None)
|
||||
if 'audio' in file:
|
||||
file = r'downloads\\CptCatman\\my vital organs all lift together.mp3'
|
||||
file = request.args.get('file').replace('/', '').replace('\\', '')
|
||||
if not check_file_path(file):
|
||||
flash('Video not found', 'danger')
|
||||
return render_template('flash-message.html')
|
||||
|
||||
if 'mp3' in file:
|
||||
return send_file(
|
||||
file,
|
||||
downloads_path() + file,
|
||||
'audio/mpeg',
|
||||
True
|
||||
)
|
||||
else:
|
||||
file = r'downloads\\Rick Astley - Never Gonna Give You Up (Official Music Video).webm'
|
||||
elif 'mp4' in file:
|
||||
return send_file(
|
||||
file,
|
||||
downloads_path() + file,
|
||||
'video/webm',
|
||||
True
|
||||
)
|
||||
|
@ -1,9 +1,11 @@
|
||||
from waitress import serve
|
||||
from app import create_app
|
||||
import file_cache
|
||||
import os
|
||||
|
||||
PORT = 5000
|
||||
MAX_VIDEO_DOWNLOAD_LENGTH_MINUTES = 10
|
||||
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
file_cache.max_video_length = MAX_VIDEO_DOWNLOAD_LENGTH_MINUTES * 60
|
||||
serve(create_app(), port=PORT)
|
||||
|
@ -15,7 +15,7 @@
|
||||
<tbody>
|
||||
{% for video in videos %}
|
||||
<tr>
|
||||
<td class="text-center">{{ video['name'] }}</td>
|
||||
<td class="text-center"><a class="btn btn-link" href="/player?file={{ video['path'] + video['name'] + video['ext'] }}">{{ video['name'] }}</a></td>
|
||||
<td class="text-center"><a class="btn btn-link" href="/download?file={{ video['path'] + video['name'] + video['ext'] }}" download>Download</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -16,7 +16,7 @@
|
||||
<tbody>
|
||||
{% for entry in running_downloads %}
|
||||
<tr>
|
||||
<td class="text-center"><a href="{{ entry[0] }}" target="_blank">{{ entry[0] }}</a></td>
|
||||
<td class="text-center">{{ entry[0] }}</td>
|
||||
<td class="text-center">{{ entry[1] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@ -33,7 +33,7 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="text-center">Currently processing</th>
|
||||
<th scope="col" class="text-center">New downloads in {{ running_downloads[0][0] }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -43,7 +43,7 @@
|
||||
{% for video in videos %}
|
||||
{% if 'mp3' in video['ext'] %}
|
||||
<tr>
|
||||
<td class="text-center align-middle">{{ video['name'] }}</td>
|
||||
<td class="text-center align-middle"><a class="btn btn-link" href="/player?file={{ video['path'] + video['name'] + video['ext'] }}">{{ video['name'] }}</a></td>
|
||||
<td class="text-center align-middle"><a class="btn btn-link" href="/download?file={{ video['path'] + video['name'] + video['ext'] }}" download>Download</a></td>
|
||||
<td class="text-center align-middle"><a class="btn btn-danger" href="/delete?file={{ video['path'] + video['name'] + video['ext'] }}&from=/library"> </a></td>
|
||||
</tr>
|
||||
|
21
templates/player.html
Normal file
21
templates/player.html
Normal file
@ -0,0 +1,21 @@
|
||||
{%- extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{{ super() }}
|
||||
<div class="container-fluid">
|
||||
{% if 'mp4' in file %}
|
||||
<div class="section d-flex justify-content-center embed-responsive embed-responsive-16by9" style="padding: 1.5%">
|
||||
<video class="embed-responsive-item" style="width: 100%; height: auto" controls>
|
||||
<source src="serve?file={{ file }}" type="video/webm">
|
||||
</video>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if 'mp3' in file %}
|
||||
<div class="section d-flex justify-content-center embed-responsive" style="padding: 1.5%">
|
||||
<audio class="embed-responsive-item" controls>
|
||||
<source src="serve?file={{ file }}" type="audio/mpeg">
|
||||
</audio>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{%- endblock %}
|
@ -1,12 +0,0 @@
|
||||
{%- extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{{ super() }}
|
||||
<div class="container-fluid">
|
||||
<div id="trailer" class="section d-flex justify-content-center embed-responsive embed-responsive-16by9">
|
||||
<video class="embed-responsive-item" style="width: 100%; padding: 1.5%; height: auto" controls>
|
||||
<source src="serve?file=video" type="video/webm">
|
||||
</video>
|
||||
</div>
|
||||
</div>
|
||||
{%- endblock %}
|
Loading…
x
Reference in New Issue
Block a user