v1.1.0 화질 선택 기능 추가

화질 선택 기능 추가
잘못된 예외처리 수정
This commit is contained in:
joyfuI
2020-02-11 20:43:20 +09:00
parent 39a2867d31
commit a190335de2
6 changed files with 57 additions and 11 deletions

View File

@@ -5,10 +5,18 @@ SJVA에서 유튜브, 네이버TV 등 동영상 사이트 영상을 다운로드
## 잡담 ## 잡담
시놀로지 docker 환경에서 테스트했습니다. 시놀로지 docker 환경에서 테스트했습니다.
다른 분들이 만든 플러그인을 참고하며 주먹구구식으로 만들었기 때문에 손볼 곳이 많습니다. 다른 분들이 만든 플러그인을 참고하며 주먹구구식으로 만들었습니다;;
일단 어느 정도 코드가 정리되면 그때 화질 선택 등 옵션을 추가할 예정
## Changelog ## Changelog
v1.1.0
* 화질 선택 기능 추가
* 잘못된 예외처리 수정
v1.0.2
v1.0.1
* 로그 좀 더 상세히 찍도록 수정
v1.0.0 v1.0.0
* 바이너리 실행 방식에서 파이썬 임베딩 방식으로 변경 * 바이너리 실행 방식에서 파이썬 임베딩 방식으로 변경
* SJVA 시작 시 자동으로 youtube-dl 업데이트 * SJVA 시작 시 자동으로 youtube-dl 업데이트

View File

@@ -1 +1 @@
{"more": "", "version": "1.0.2", "name": "youtube-dl", "developer": "joyfuI", "home": "https://github.com/joyfuI/youtube-dl", "description": "\uc720\ud29c\ube0c, \ub124\uc774\ubc84TV \ub4f1 \ub3d9\uc601\uc0c1 \uc0ac\uc774\ud2b8\uc5d0\uc11c \ub3d9\uc601\uc0c1 \ub2e4\uc6b4\ub85c\ub4dc", "icon": "", "category_name": "vod"} {"more": "", "version": "1.1.0", "name": "youtube-dl", "developer": "joyfuI", "home": "https://github.com/joyfuI/youtube-dl", "description": "\uc720\ud29c\ube0c, \ub124\uc774\ubc84TV \ub4f1 \ub3d9\uc601\uc0c1 \uc0ac\uc774\ud2b8\uc5d0\uc11c \ub3d9\uc601\uc0c1 \ub2e4\uc6b4\ub85c\ub4dc", "icon": "", "category_name": "vod"}

View File

@@ -89,6 +89,21 @@ class Logic(object):
youtube_dl_list = [] youtube_dl_list = []
@staticmethod
def get_preset_list():
preset_list = [
['bestvideo+bestaudio/best', '최고 화질'],
['bestvideo[height<=1080]+bestaudio/best[height<=1080]', '1080p'],
['worstvideo+worstaudio/worst', '최저 화질'],
['bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]', '최고 화질(mp4)'],
['bestvideo[ext=mp4][height<=1080]+bestaudio[ext=m4a]/best[ext=mp4][height<=1080]', '1080p(mp4)'],
['webm', 'webm'],
['bestvideo[filesize<50M]+bestaudio/best[filesize<50M]', '50MB 미만'],
['bestaudio', '오디오만'],
['_custom', '사용자 정의']
]
return preset_list
@staticmethod @staticmethod
def get_data(youtube_dl): def get_data(youtube_dl):
try: try:

View File

@@ -3,6 +3,7 @@ from __future__ import unicode_literals
# python # python
import os import os
import traceback
import shutil import shutil
import tempfile import tempfile
import glob import glob
@@ -42,11 +43,12 @@ class Youtube_dl(object):
_index = 0 _index = 0
_last_msg = '' _last_msg = ''
def __init__(self, url, filename, temp_path, save_path): def __init__(self, url, filename, temp_path, save_path, format_code=None):
self.url = url self.url = url
self.filename = filename self.filename = filename
self.temp_path = tempfile.mkdtemp(prefix='youtube-dl_', dir=temp_path) self.temp_path = tempfile.mkdtemp(prefix='youtube-dl_', dir=temp_path)
self.save_path = save_path self.save_path = save_path
self.format_code = format_code
self.index = Youtube_dl._index self.index = Youtube_dl._index
Youtube_dl._index += 1 Youtube_dl._index += 1
self.status = Status.READY self.status = Status.READY
@@ -73,12 +75,12 @@ class Youtube_dl(object):
def start(self): def start(self):
self._thread = Thread(target=self.run) self._thread = Thread(target=self.run)
self.start_time = datetime.now()
self._thread.start() self._thread.start()
self.status = Status.START
def run(self): def run(self):
try: try:
self.start_time = datetime.now()
self.status = Status.START
info_dict = Youtube_dl.get_info_dict(self.url) # 동영상 정보 가져오기 info_dict = Youtube_dl.get_info_dict(self.url) # 동영상 정보 가져오기
if info_dict is None: # 가져오기 실패 if info_dict is None: # 가져오기 실패
self.status = Status.ERROR self.status = Status.ERROR
@@ -93,17 +95,21 @@ class Youtube_dl(object):
# 'match_filter': self.match_filter_func, # 'match_filter': self.match_filter_func,
'outtmpl': os.path.join(self.temp_path, self.filename) 'outtmpl': os.path.join(self.temp_path, self.filename)
} }
if self.format_code is not None:
ydl_opts['format'] = self.format_code
with youtube_dl.YoutubeDL(ydl_opts) as ydl: with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([self.url]) ydl.download([self.url])
if self.status == Status.FINISHED: # 다운로드 성공 if self.status == Status.FINISHED: # 다운로드 성공
for i in glob.glob(self.temp_path + '/*'): for i in glob.glob(self.temp_path + '/*'):
shutil.move(i, self.save_path) # 파일 이동 shutil.move(i, self.save_path) # 파일 이동
self.status = Status.COMPLETED self.status = Status.COMPLETED
shutil.rmtree(self.temp_path) # 임시폴더 삭제
self.end_time = datetime.now()
except Exception as e: except Exception as e:
self.status = Status.ERROR
logger.error('Exception:%s', e) logger.error('Exception:%s', e)
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
finally:
shutil.rmtree(self.temp_path, ignore_errors=True) # 임시폴더 삭제
self.end_time = datetime.now()
def stop(self): def stop(self):
self.status = Status.STOP self.status = Status.STOP

View File

@@ -33,7 +33,7 @@ def plugin_unload():
Logic.plugin_unload() Logic.plugin_unload()
plugin_info = { plugin_info = {
'version': '1.0.2', 'version': '1.1.0',
'name': 'youtube-dl', 'name': 'youtube-dl',
'category_name': 'vod', 'category_name': 'vod',
'icon': '', 'icon': '',
@@ -74,6 +74,7 @@ def detail(sub):
arg = { } arg = { }
arg['package_name'] = package_name arg['package_name'] = package_name
arg['file_name'] = '%(title)s-%(id)s.%(ext)s' arg['file_name'] = '%(title)s-%(id)s.%(ext)s'
arg['preset_list'] = Logic.get_preset_list()
return render_template('%s_download.html' % package_name, arg=arg) return render_template('%s_download.html' % package_name, arg=arg)
elif sub == 'list': elif sub == 'list':
@@ -104,7 +105,8 @@ def ajax(sub):
filename = request.form['filename'] filename = request.form['filename']
temp_path = Logic.get_setting_value('temp_path') temp_path = Logic.get_setting_value('temp_path')
save_path = Logic.get_setting_value('save_path') save_path = Logic.get_setting_value('save_path')
youtube_dl = Youtube_dl(url, filename, temp_path, save_path) format_code = request.form['format'] if request.form['format'] else None
youtube_dl = Youtube_dl(url, filename, temp_path, save_path, format_code)
Logic.youtube_dl_list.append(youtube_dl) # 리스트 추가 Logic.youtube_dl_list.append(youtube_dl) # 리스트 추가
youtube_dl.start() youtube_dl.start()
return jsonify([]) return jsonify([])

View File

@@ -4,6 +4,9 @@
<div> <div>
{{ macros.setting_input_text('url', 'URL', placeholder='http:// 주소', desc='유튜브, 네이버TV 등 동영상 주소') }} {{ macros.setting_input_text('url', 'URL', placeholder='http:// 주소', desc='유튜브, 네이버TV 등 동영상 주소') }}
{{ macros.setting_input_text('filename', '파일명', value=arg['file_name'], desc='템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/blob/master/README.md#output-template 참고') }} {{ macros.setting_input_text('filename', '파일명', value=arg['file_name'], desc='템플릿 규칙은 https://github.com/ytdl-org/youtube-dl/blob/master/README.md#output-template 참고') }}
{{ macros.setting_select('preset', '동영상 포맷 프리셋', arg['preset_list'], col='3') }}
{{ macros.setting_input_text('format', '동영상 포맷', desc=['포맷 지정은 https://github.com/ytdl-org/youtube-dl/blob/master/README.md#format-selection 참고', '빈칸으로 설정 시 최고 화질로 다운로드합니다.']) }}
<!-- {{ macros.setting_select('merge_output_format', '파일 포맷', [['auto', '자동'], ['mkv', 'mkv'], ['mp4', 'mp4'], ['ogg', 'ogg'], ['webm', 'webm'], ['flv', 'flv']], col='3', value=arg['merge_output_format'], desc='병합이 필요한 경우 지정한 포맷으로 병합을 합니다.') }} -->
{{ macros.setting_button([['download_start', '다운로드']]) }} {{ macros.setting_button([['download_start', '다운로드']]) }}
</div> </div>
@@ -12,6 +15,17 @@
var package_name = '{{ arg["package_name"] }}'; var package_name = '{{ arg["package_name"] }}';
$(function () { $(function () {
// 프리셋 변경
$('#preset').change(function (e) {
if ($(this).val() == '_custom') {
return;
}
$('#format').val($(this).val());
});
$('#format').change(function (e) {
$('#preset').val('_custom');
});
// 다운로드 // 다운로드
$('#download_start').click(function (e) { $('#download_start').click(function (e) {
if ($('#url').val().startsWith('http') == false) { if ($('#url').val().startsWith('http') == false) {
@@ -26,7 +40,8 @@
cache: false, cache: false,
data: { data: {
url: $('#url').val(), url: $('#url').val(),
filename: $('#filename').val() filename: $('#filename').val(),
format: $('#format').val()
}, },
dataType: 'json', dataType: 'json',
success: function (data) { success: function (data) {