This commit is contained in:
KurtBestor 2021-08-11 14:50:48 +09:00
parent c1ec9bae97
commit ef3030f75c
26 changed files with 327 additions and 115 deletions

View File

@ -26,7 +26,7 @@ class Downloader_coub(Downloader):
return get_id(url)
def read(self):
video = Video(self.url)
video = Video(self.url, cw=self.cw)
video.url()#
self.urls.append(video.url)
@ -41,15 +41,16 @@ class Downloader_coub(Downloader):
class Video(object):
_url = None
def __init__(self, url):
def __init__(self, url, cw=None):
self.url = LazyUrl(url, self.get, self, pp=self.pp)
self.cw = cw
@try_n(2)
def get(self, url):
if self._url:
return self._url
ydl = ytdl.YoutubeDL()
ydl = ytdl.YoutubeDL(cw=self.cw)
info = ydl.extract_info(url)
fs = [f for f in info['formats'] if f['ext'] == 'mp4']
f = sorted(fs, key=lambda f: int(f.get('filesize', 0)))[-1]

View File

@ -28,7 +28,7 @@ class Downloader_etc(Downloader):
if video.artist:
self.artist = video.artist
self.urls.append(video.url)
self.print_('url_thumb: {}'.format(video.url_thumb))
@ -37,7 +37,7 @@ class Downloader_etc(Downloader):
self.enableSegment()#
if isinstance(video.url(), M3u8_stream):
self.disableSegment()
self.title = '[{}] {}'.format(video.header, video.title)
@ -54,16 +54,29 @@ def format_(f):
return '{} - {} - {} - {}'.format(f['format'], f['_resolution'], f['_audio'], f['url'])
@try_n(4)
def get_video(url, session, cw, ie_key=None):
print_ = get_print(cw)
try:
video = _get_video(url, session, cw, ie_key, allow_m3u8=True)
if isinstance(video.url(), M3u8_stream):
c = video.url().segs[0].download(cw)
if not c:
raise Exception('invalid m3u8')
return video
except Exception as e:
print_(e)
return _get_video(url, session, cw, ie_key, allow_m3u8=False)
@try_n(4)
def _get_video(url, session, cw, ie_key=None, allow_m3u8=True):
print_ = get_print(cw)
print_('get_video: {}, {}'.format(allow_m3u8, url))
options = {
'noplaylist': True,
#'extract_flat': True,
'playlistend': 1,
}
ydl = ytdl.YoutubeDL(options)
ydl = ytdl.YoutubeDL(options, cw=cw)
info = ydl.extract_info(url)
if not ie_key:
ie_key = ytdl.get_extractor_name(url)
@ -79,7 +92,7 @@ def get_video(url, session, cw, ie_key=None):
url_new = entry.get('url') or entry['webpage_url']
if url_new != url:
return get_video(url_new, session, cw, ie_key=get_ie_key(info))
session.headers.update(info.get('http_headers', {}))
#session.cookies.update(ydl.cookiejar)
@ -100,8 +113,20 @@ def get_video(url, session, cw, ie_key=None):
if not fs:
raise Exception('No videos')
f = sorted(fs, key=lambda f:(f['_resolution'], f['_index']))[-1]
if f['_audio']:
def filter_f(fs):
for f in fs:
if allow_m3u8:
return f
ext = get_ext_(f['url'], session, url)
if ext.lower() != '.m3u8':
return f
print_('invalid url: {}'.format(f['url']))
return list(fs)[0]#
f_video = filter_f(reversed(sorted(fs, key=lambda f:(f['_resolution'], f['_index']))))
print_('video0: {}'.format(format_(f_video)))
if f_video['_audio']:
f_audio = None
else:
fs_audio = sorted([f_audio for f_audio in fs if (not f_audio['_resolution'] and f_audio['_audio'])], key=lambda f:(f['_audio'], f['_index']))
@ -109,13 +134,14 @@ def get_video(url, session, cw, ie_key=None):
f_audio = fs_audio[-1]
else:
try:
f = sorted([f for f in fs if f['_audio']], key=lambda f:(f['_resolution'], f['_index']))[-1]
except IndexError:
pass
print_('trying to get f_video with audio')
f_video = filter_f(reversed(sorted([f for f in fs if f['_audio']], key=lambda f:(f['_resolution'], f['_index']))))
except Exception as e:
print_('failed to get f_video with audio: {}'.format(e))
f_audio = None
print_('video: {}'.format(format_(f)))
print_('video: {}'.format(format_(f_video)))
print_('audio: {}'.format(format_(f_audio)))
video = Video(f, f_audio, info, session, url, cw=cw)
video = Video(f_video, f_audio, info, session, url, cw=cw)
return video
@ -128,6 +154,15 @@ def get_ie_key(info):
return ie_key
def get_ext_(url, session, referer):
try:
ext = downloader.get_ext(url, session, referer)
except Exception as e:
print(e)
ext = get_ext(url)
return ext
class Video(object):
def __init__(self, f, f_audio, info, session, referer, cw=None):
self.f_audio = f_audio
@ -145,11 +180,7 @@ class Video(object):
if self.url_thumb:
downloader.download(self.url_thumb, referer=referer, buffer=self.thumb, session=session)
try:
ext = downloader.get_ext(self.url, session, referer)
except Exception as e:
print(e)
ext = get_ext(self.url)
ext = get_ext_(self.url, session, referer)
if not ext:
print('empty ext')
@ -157,7 +188,7 @@ class Video(object):
ext = '.mp4'
else:
ext = '.mp3'
if ext.lower() == '.m3u8':
try:
url = playlist2stream(self.url, referer, session=session, n_thread=4)
@ -182,5 +213,3 @@ class Video(object):
downloader.download(self.f_audio['url'], buffer=f, referer=self.referer, session=self.session)
ffmpeg.merge(filename, f, cw=self.cw)
return filename

View File

@ -1,12 +1,8 @@
# uncompyle6 version 3.5.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:30:55) [MSC v.1500 32 bit (Intel)]
# Embedded file name: file_downloader.pyo
# Compiled at: 2019-10-02 14:06:58
import downloader, json, os
from constants import try_n
from utils import Downloader, query_url, clean_title, get_ext
from timee import sleep
from hashlib import md5
@Downloader.register
@ -32,10 +28,20 @@ class Downloader_file(Downloader):
for esc in ['?', '#']:
name = name.split(esc)[0]
if not get_ext(name):
name += downloader.get_ext(self.url)
ext = get_ext(name)
if not ext:
try:
ext = downloader.get_ext(self.url)
except:
ext = ''
name = os.path.splitext(name)[0]
self.urls.append(self.url)
self.filenames[self.url] = clean_title(name)
self.title = name
id_ = md5(self.url.encode('utf8')).hexdigest()[:8]
tail = ' ({}){}'.format(id_, ext)
filename = clean_title(name, n=-len(tail)) + tail
self.filenames[self.url] = filename
self.title = filename

View File

@ -69,7 +69,7 @@ def get_pages(url, session):
pages = []
ids = set()
for p in range(100):
for p in range(500): #2966
url_api = 'https://api2-page.kakao.com/api/v5/store/singles'
data = {
'seriesid': id_,

View File

@ -17,7 +17,7 @@ class Downloader_vlive(Downloader):
return url.split('?')[0].strip('/')
def read(self):
video = Video(self.url)
video = Video(self.url, cw=self.cw)
video.url()#
self.urls.append(video.url)
@ -32,15 +32,16 @@ class Downloader_vlive(Downloader):
class Video(object):
_url = None
def __init__(self, url):
def __init__(self, url, cw=None):
self.url = LazyUrl(url, self.get, self)
self.cw = cw
@try_n(2)
def get(self, url):
if self._url:
return self._url
ydl = ytdl.YoutubeDL()
ydl = ytdl.YoutubeDL(cw=self.cw)
info = ydl.extract_info(url)
fs = [f for f in info['formats'] if f['ext'] == 'mp4']
f = sorted(fs, key=lambda f: f['height'])[-1]

View File

@ -37,19 +37,26 @@ class Page(object):
@Downloader.register
class Downloader_lhscan(Downloader):
type = 'lhscan'
URLS = ['lhscan.net', 'loveheaven.net', 'lovehug.net']
URLS = [
#'lhscan.net', 'loveheaven.net',
'lovehug.net', 'welovemanga.net', 'weloma.net',
]
MAX_CORE = 16
display_name = 'LHScan'
_soup = None
def init(self):
self.url = self.url.replace('lhscan.net', 'loveheaven.net')
self.session = Session()
#clf2.solve(self.url, session=self.session, cw=self.cw)
soup = self.soup
if not soup.find('ul', class_='manga-info'):
self.Invalid(u'{}: {}'.format(tr_(u'목록 주소를 입력해주세요'), self.url))
@classmethod
def fix_url(cls, url):
url = url.replace('lovehug.net', 'welovemanga.net')
return url
@property
def soup(self):
if self._soup is None:
@ -58,9 +65,10 @@ class Downloader_lhscan(Downloader):
html = downloader.read_html(self.url, session=self.session)
break
except Exception as e:
e_ = e
print(e)
else:
raise
raise e_
self._soup = Soup(html)
return self._soup
@ -99,14 +107,20 @@ def get_imgs_page(page, session, cw=None):
src = base64.b64decode(src).strip().decode('utf8')
except:
pass
src = urljoin(page.url, src)
src0 = src
src = src.replace('welovemanga.net', '1')#
src = urljoin(page.url, src).strip()
if 'Credit_LHScan_' in src or '5e1ad960d67b2_5e1ad962338c7' in src:
continue
if 'fe132b3d32acc39f5adcea9075bedad4LoveHeaven' in src:
continue
if 'LoveHug_600cfd96e98ff.jpg' in src:
continue
img = Image(src.strip(), page, len(imgs))
if 'image_5f0ecf23aed2e.png' in src:
continue
if not imgs:
print_(src0)
img = Image(src, page, len(imgs))
imgs.append(img)
return imgs

View File

@ -1,6 +1,9 @@
from utils import Downloader, LazyUrl, clean_title
from m3u8_tools import playlist2stream, M3u8_stream
import os
from hashlib import md5
from translator import tr_
DEFAULT_N_THREAD = 1
@Downloader.register
@ -10,24 +13,42 @@ class Downloader_m3u8(Downloader):
single = True
display_name = 'M3U8'
def init(self):
if '://' not in self.url:
self.url = 'http://' + self.url
@classmethod
def fix_url(cls, url):
if '://' not in url:
url = 'http://' + url
return url
def read(self):
video = Video(self.url)
n_thread = self.cw.format or DEFAULT_N_THREAD
self.print_('n_thread: {}'.format(n_thread))
video = Video(self.url, n_thread)
self.urls.append(video.url)
self.title = video.title
self.title = '{} ({})'.format(video.title, video.id_)
class Video(object):
def __init__(self, url):
def __init__(self, url, n_thread):
try:
m = playlist2stream(url)
m = playlist2stream(url, n_thread=n_thread)
except:
m = M3u8_stream(url)
m = M3u8_stream(url, n_thread=n_thread)
self.url = LazyUrl(url, lambda _: m, self)
self.title = os.path.splitext(os.path.basename(url))[0]
self.filename = clean_title(self.title, n=-4) + '.mp4'
self.id_ = md5(url.encode('utf8')).hexdigest()[:8]
tail = ' ({}).mp4'.format(self.id_)
self.filename = clean_title(self.title, n=-len(tail)) + tail
import selector
@selector.options('m3u8')
def options():
def f(urls):
from Qt import QInputDialog
n_thread, ok = QInputDialog.getInt(Downloader.mainWindow, tr_('Set number of threads'), tr_('Number of threads?'), value=DEFAULT_N_THREAD, min=1, max=4, step=1)
if not ok:
return
return n_thread
return [
{'text': 'Set number of threads...', 'format': f},
]

View File

@ -48,14 +48,15 @@ class Downloader_manatoki(Downloader):
else:
raise Exception('no selected option')
self.session, self.soup, url = get_soup(url)
self.url = self.fix_url(url)
url_page = self.fix_url(url)
for i, page in enumerate(get_pages(self.url, self.soup)):
for i, page in enumerate(get_pages(url_page, self.soup)):
if page.id == int(op['value']):
break
else:
raise Exception('can not find page')
self.cw.range_p = [i]
self.url = url_page
self.name

View File

@ -21,7 +21,7 @@ class Downloader_navertv(Downloader):
self.url = 'https://tv.naver.com/v/{}'.format(self.url)
def read(self):
video = Video(self.url)
video = Video(self.url, cw=self.cw)
video.url()#
self.urls.append(video.url)
@ -36,15 +36,16 @@ class Downloader_navertv(Downloader):
class Video(object):
_url = None
def __init__(self, url):
def __init__(self, url, cw=None):
self.url = LazyUrl(url, self.get, self)
self.cw = cw
@try_n(4)
def get(self, url):
if self._url:
return self._url
ydl = ytdl.YoutubeDL()
ydl = ytdl.YoutubeDL(cw=self.cw)
info = ydl.extract_info(url)
fs = [f for f in info['formats'] if f['protocol'] in ['http', 'https']]
fs = sorted(fs, key=lambda f: int(f.get('width', 0)), reverse=True)

View File

@ -179,6 +179,7 @@ class Image():
self.p = p
self.format_ = format_
self.artist = info['artist']
self.artistid = info['artist_id'] #3636
self.title = info['raw_title']
self.utime = info['create_date']
self.cw = cw
@ -187,8 +188,14 @@ class Image():
def get(self, referer):
ext = get_ext(self._url)
name = self.format_.replace('id', '###id*').replace('page', '###page*').replace('artist', '###artist*').replace('title', '###title*')
name = name.replace('###id*', str(self.id_)).replace('###page*', str(self.p)).replace('###artist*', self.artist).replace('###title*', self.title)
d ={
'id': self.id_,
'page': self.p,
'artist': self.artist,
'artistid': self.artistid,
'title': self.title,
}
name = utils.format(self.format_, d)
self.filename = clean_title(name.strip(), allow_dot=True, n=-len(ext)) + ext
if self.ugoira and self.ugoira['ext']: #3355
filename_local = os.path.join(self.cw.dir, self.filename)

View File

@ -122,7 +122,7 @@ class Video(object):
#title = j['video_title']
title = soup.find('h1', class_='title').text.strip()
ydl = ytdl.YoutubeDL()
ydl = ytdl.YoutubeDL(cw=self.cw)
info = ydl.extract_info(url)
url_thumb = info['thumbnail']
videos = []

View File

@ -148,7 +148,7 @@ def get_audios(url, cw, album_art):
#'extract_flat': True,
}
ydl = ytdl.YoutubeDL()
ydl = ytdl.YoutubeDL(cw=cw)
info = ydl.extract_info(url)
if 'entries' in info:
entries = info['entries']

View File

@ -142,15 +142,24 @@ def get_title_artist(soup):
def get_text(url, subtitle, update, session):
html = downloader.read_html(url, session=session)
soup = Soup(html)
p = soup.find('div', id='novel_p')
p = '' if p is None else p.text.strip()
story = soup.find('div', id='novel_honbun').text.strip()
if update:
update = u' ' + update
else:
update = ''
story = soup.find('div', id='novel_honbun').text.strip()
p = soup.find('div', id='novel_p')
p = '' if p is None else p.text.strip()
if p:
story = (u'{}\n\n{}').format(p, story)
story = '{}\n\n════════════════════════════════\n\n{}'.format(p, story)
#2888
a = soup.find('div', id='novel_a')
a = '' if a is None else a.text.strip()
if a:
story = '{}\n\n════════════════════════════════\n\n{}'.format(story, a)
text =u'''────────────────────────────────
{}{}

View File

@ -6,6 +6,7 @@ from io import BytesIO
from m3u8_tools import M3u8_stream
import ree as re
from translator import tr_
import errors
@Downloader.register
@ -47,7 +48,7 @@ class Downloader_twitch(Downloader):
filter = None
if filter is None:
video = Video(self.url)
video = Video(self.url, self.cw)
video.url()
self.urls.append(video.url)
self.title = video.title
@ -94,7 +95,7 @@ def get_videos(url, cw=None):
for edge in data[0]['data']['user']['clips']['edges']:
url_video = edge['node']['url']
info['name'] = edge['node']['broadcaster']['displayName']
video = Video(url_video)
video = Video(url_video, cw)
video.id = int(edge['node']['id'])
videos.append(video)
cursor_new = edge['cursor']
@ -124,15 +125,26 @@ def alter(seg):
class Video(object):
_url = None
def __init__(self, url):
def __init__(self, url, cw):
self.url = LazyUrl(url, self.get, self)
self.cw = cw
@try_n(4)
def get(self, url):
print_ = get_print(self.cw)
if self._url:
return self._url
ydl = ytdl.YoutubeDL()
info = ydl.extract_info(url)
ydl = ytdl.YoutubeDL(cw=self.cw)
try:
info = ydl.extract_info(url)
except Exception as e:
ex = type(ytdl.get_extractor(url))(ydl)
_download_info = getattr(ex, '_download_info', None)
if _download_info is not None:
vod_id = ex._match_id(url)
info = _download_info(vod_id)
print_(info)
raise
video_best = info['formats'][-1]
video = video_best['url']

View File

@ -113,7 +113,7 @@ def _guest_token(session, headers, cache=True, cw=None):
data = json.loads(r.text)
token = data['guest_token']
print_('token type: {}'.format(type(token)))
if isinstance(token ,int): #3525
if isinstance(token, int): #3525
token = str(token)
CACHE_GUEST_TOKEN = token, time()
return token
@ -410,19 +410,23 @@ def get_imgs_more(username, session, title, types, n=None, format='[%y-%m-%d] id
continue
ids_set.add(id)
tweets.append(tweet)
imgs_ = []
for tweet in tweets:
imgs_ += get_imgs_from_tweet(tweet, session, types, format, cw)
if tweets:
if imgs_:
if count_no_imgs:
print_('reset count_no_imgs: {}'.format(len(imgs_)))
imgs += imgs_
count_no_imgs = 0
else:
count_no_imgs += 1
change_ua(session)
if count_no_imgs >= RETRY_MORE:
break
print_('retry...')
print_('retry... {}'.format(count_no_imgs))
continue
for tweet in tweets:
imgs += get_imgs_from_tweet(tweet, session, types, format, cw)
msg = '{} {} (@{}) - {}'.format(tr_('읽는 중...'), artist, username, len(imgs))
if cw:
@ -576,7 +580,7 @@ class Image(object):
print_ = get_print(self.cw)
for try_ in range(self.try_n):
try:
d = ytdl.YoutubeDL()
d = ytdl.YoutubeDL(cw=self.cw)
info = d.extract_info(self._url)
url = info['url']

View File

@ -18,7 +18,7 @@ class Downloader_vimeo(Downloader):
self.url = u'https://vimeo.com/{}'.format(self.url)
def read(self):
video = Video(self.url)
video = Video(self.url, cw=self.cw)
video.url()#
self.urls.append(video.url)
@ -32,15 +32,16 @@ class Downloader_vimeo(Downloader):
class Video(object):
_url = None
def __init__(self, url):
def __init__(self, url, cw=None):
self.url = LazyUrl(url, self.get, self)
self.cw = cw
@try_n(4)
def get(self, url):
if self._url:
return self._url
ydl = ytdl.YoutubeDL()
ydl = ytdl.YoutubeDL(cw=self.cw)
info = ydl.extract_info(url)
fs = [f for f in info['formats'] if f['protocol'] in ['http', 'https']]
fs = sorted(fs, key=lambda f: int(f.get('width', 0)), reverse=True)

View File

@ -19,7 +19,7 @@ class Downloader_vlive(Downloader):
raise NotImplementedError('channel')
def read(self):
video = get_video(self.url)
video = get_video(self.url, cw=self.cw)
self.urls.append(video.url)
@ -30,12 +30,12 @@ class Downloader_vlive(Downloader):
@try_n(4)
def get_video(url):
def get_video(url, cw=None):
options = {
'noplaylist': True,
}
ydl = ytdl.YoutubeDL(options)
ydl = ytdl.YoutubeDL(options, cw=cw)
info = ydl.extract_info(url)
fs = []

View File

@ -13,7 +13,7 @@ class Downloader_youku(Downloader):
URLS = ['v.youku.com']
def read(self):
video = Video(self.url)
video = Video(self.url, cw=self.cw)
video.url()# get thumb
self.urls.append(video.url)
@ -25,14 +25,15 @@ class Downloader_youku(Downloader):
class Video(object):
_url = None
def __init__(self, url):
def __init__(self, url, cw=None):
self.url = LazyUrl(url, self.get, self)
self.cw = cw
def get(self, url):
if self._url:
return self._url
ydl = ytdl.YoutubeDL()
ydl = ytdl.YoutubeDL(cw=self.cw)
info = ydl.extract_info(url)
# get best video

View File

@ -23,7 +23,7 @@ class Downloader_youporn(Downloader):
return url
def read(self):
video = Video(self.url)
video = Video(self.url, cw=self.cw)
self.urls.append(video.url)
self.setIcon(video.thumb)
@ -35,8 +35,8 @@ class Downloader_youporn(Downloader):
class Video(object):
@try_n(4)
def __init__(self, url):
ydl = ytdl.YoutubeDL()
def __init__(self, url, cw=None):
ydl = ytdl.YoutubeDL(cw=cw)
info = ydl.extract_info(url)
f = info['formats'][-1]

View File

@ -27,7 +27,7 @@ def print_streams(streams, cw):
print_ = get_print(cw)
for stream in streams:
print_(u'[{}][{}fps][{}{}][{}] {} [{} / {}] ─ {}'.format(stream.resolution, stream.fps, stream.abr_str, '(fixed)' if stream.abr_fixed else '', stream.tbr, stream.subtype, stream.video_codec, stream.audio_codec, stream.format))
print_('[{}][{}fps][{}{}][{}] {} [{} / {}] ─ {}'.format(stream.resolution, stream.fps, stream.abr_str, '(fixed)' if stream.abr_fixed else '', stream.tbr, stream.subtype, stream.video_codec, stream.audio_codec, stream.format))
print_('')
@ -63,7 +63,7 @@ class Video(object):
print('max_res: {}'.format(max_res))
for try_ in range(8):
try:
yt = ytdl.YouTube(url)
yt = ytdl.YouTube(url, cw=self.cw)
break
except Exception as e:
e_ = e
@ -124,7 +124,7 @@ class Video(object):
streams.append(stream)
#'''
else:
raise Exception(u'type "{}" is not supported'.format(type))
raise Exception('type "{}" is not supported'.format(type))
# Pick the best
while streams:
@ -146,7 +146,7 @@ class Video(object):
foo = False
if stream_final is None or (stream_final.fps <= stream.fps and (foo or (stream_final.subtype.lower()!=prefer_format and stream.subtype.lower()==prefer_format) or stream_final.fps < stream.fps)):
#print(foo)
print_(u'# stream_final {} {} {} {} {} {}fps'.format(stream, stream.format, stream.resolution, stream.subtype, stream.audio_codec, stream.fps))
print_('# stream_final {} {} {} {} {} {}fps'.format(stream, stream.format, stream.resolution, stream.subtype, stream.audio_codec, stream.fps))
stream_final = stream
ok = downloader.ok_url(stream_final.url, referer=url) if isinstance(stream_final.url, str) else True
@ -183,7 +183,7 @@ class Video(object):
print('audio required')
streams = [stream for stream in yt.streams.all() if stream.abr]
print_streams(streams, cw)
# only mp4; https://github.com/KurtBestor/Hitomi-Downloader-issues/issues/480
# only mp4; https://github.com/KurtBestor/Hitomi-Downloader/issues/480
def isGood(stream):
return stream.audio_codec.lower().startswith('mp4')
streams_good = [stream for stream in streams if isGood(stream)]
@ -238,14 +238,14 @@ class Video(object):
#soup = Soup(yt.watch_html)
#title = soup.title.text.replace('- YouTube', '').strip()
self.title = title
ext = u'.' + self.stream.subtype
ext = '.' + self.stream.subtype
self.filename = format_filename(title, self.id, ext)
print_(u'Resolution: {}'.format(stream.resolution))
print_(u'Codec: {} / {}'.format(stream.video_codec, stream.audio_codec))
print_(u'Abr: {}'.format(stream.abr))
print_(u'Subtype: {}'.format(stream.subtype))
print_(u'FPS: {}\n'.format(stream.fps))
print_('Resolution: {}'.format(stream.resolution))
print_('Codec: {} / {}'.format(stream.video_codec, stream.audio_codec))
print_('Abr: {}'.format(stream.abr))
print_('Subtype: {}'.format(stream.subtype))
print_('FPS: {}\n'.format(stream.fps))
return self._url
@ -263,13 +263,13 @@ class Video(object):
ui_setting = utils.ui_setting
ext = os.path.splitext(filename)[1].lower()
if not os.path.isfile(filename):
print(u'no file: {}'.format(filename))
print('no file: {}'.format(filename))
return
filename_new = None
if self.type == 'video' and (self.audio is not None or ext != '.mp4'): # UHD or non-mp4
if self.audio is not None: # merge
print_(u'Download audio: {}'.format(self.audio))
print_('Download audio: {}'.format(self.audio))
hash = uuid()
path = os.path.join(os.path.dirname(filename), '{}_a.tmp'.format(hash))
if cw is not None:
@ -282,19 +282,19 @@ class Video(object):
#print(out)
name, ext_old = os.path.splitext(filename)
if ext_old.lower() != ext.lower():
print_(u'rename ext {} --> {}'.format(ext_old, ext))
filename_new = u'{}{}'.format(name, ext)
print_('rename ext {} --> {}'.format(ext_old, ext))
filename_new = '{}{}'.format(name, ext)
if os.path.isfile(filename_new):
os.remove(filename_new)
os.rename(filename, filename_new)
else: # convert non-mp4 video -> mp4
name, ext_old = os.path.splitext(filename)
filename_new = u'{}.mp4'.format(name)
print_(u'Convert video: {} -> {}'.format(filename, filename_new))
filename_new = '{}.mp4'.format(name)
print_('Convert video: {} -> {}'.format(filename, filename_new))
ffmpeg.convert(filename, filename_new, cw=cw)
elif self.type == 'audio' and ext != '.mp3': # convert non-mp3 audio -> mp3
name, ext_old = os.path.splitext(filename)
filename_new = u'{}.mp3'.format(name)
filename_new = '{}.mp3'.format(name)
ffmpeg.convert(filename, filename_new, '-shortest -preset ultrafast -b:a {}k'.format(get_abr()), cw=cw)
if self.type == 'audio' and ui_setting.albumArt.isChecked():
@ -310,9 +310,9 @@ class Video(object):
if lang in self.subtitles:
try:
subtitle = self.subtitles[lang]
filename_sub = u'{}.vtt'.format(os.path.splitext(filename)[0])
filename_sub = '{}.vtt'.format(os.path.splitext(filename)[0])
downloader.download(subtitle, os.path.dirname(filename_sub), fileName=os.path.basename(filename_sub), overwrite=True)
filename_sub_new = u'{}.srt'.format(os.path.splitext(filename_sub)[0])
filename_sub_new = '{}.srt'.format(os.path.splitext(filename_sub)[0])
cw.imgs.append(filename_sub_new)
cw.dones.add(os.path.realpath(filename_sub_new).replace('\\\\?\\', ''))
srt_converter.convert(filename_sub, filename_sub_new)
@ -420,13 +420,13 @@ def get_videos(url, type='video', only_mp4=False, audio_included=False, max_res=
if '/channel/' in url or '/user/' in url or '/c/' in url:
info = read_channel(url, n=n, cw=cw)
info['type'] = 'channel'
info['title'] = u'[Channel] {}'.format(info['uploader'])
info['title'] = '[Channel] {}'.format(info['uploader'])
if cw:
info['urls'] = filter_range(info['urls'], cw.range)
elif '/playlist' in url:
info = read_playlist(url, n=n, cw=cw)
info['type'] = 'playlist'
info['title'] = u'[Playlist] {}'.format(info['title'])
info['title'] = '[Playlist] {}'.format(info['title'])
if cw:
info['urls'] = filter_range(info['urls'], cw.range)
else:
@ -455,7 +455,7 @@ def read_playlist(url, n, cw=None):
'extract_flat': True,
'playlistend': n,
}
ydl = ytdl.YoutubeDL(options)
ydl = ytdl.YoutubeDL(options, cw=cw)
info = ydl.extract_info(url)
es = info['entries']
@ -479,7 +479,7 @@ import selector
@selector.register('youtube')
def select():
if utils.ui_setting.askYoutube.isChecked():
value = utils.messageBox(tr_(u'Youtube format?'), icon=QtGui.QMessageBox.Question, buttons=[tr_(u'MP4 (동영상)'), tr_(u'MP3 (음원)')])
value = utils.messageBox(tr_('Youtube format?'), icon=QtGui.QMessageBox.Question, buttons=[tr_('MP4 (동영상)'), tr_('MP3 (음원)')])
format = ['mp4', 'mp3'][value]
return format

View File

@ -1,3 +1,49 @@
3.6 【】
[버그 해결 / 사이트 변경에 의한 수정]
- #2966
- Twitter 일부 계정 무한 로딩 문제 해결
- LHScan 새 도메인 지원 (#3603)
- Hitomi.la 업데이트 대응 (#3638)
- #3641
- 기타 자잘한 것들
[변경/추가된 기능]
- 초기 로딩 시간 최적화
- 썸네일 로딩 시간 최적화
- 설정 파일 (*.ini) 크기 최적화
- 설정 파일 (*.ini) 구조 변경 (신버전에서 작성한 설정 파일 구버전에서 읽을 수 없음)
- 고급 설정에서 스크롤할 때 콤보박스나 슬라이더 반응하지 않도록 수정
- 미리보기 창 크기 조절 가능하게 수정
- 다운로더 작업 목록 필터링했을 때 그룹에 해당 갯수 표시
- 소설가가 되자 꼬릿말 추가 (#2888, #3610)
- 일시정지 후 완료시킬 수 있게 수정 (#3482, #3609)
- 작업 레이지 로딩 끄는 옵션 (#3613)
- Pixiv 파일명 형식 "artistid" 추가 (#3636)
- 기타 자잘한 것들
--------------------------------------------------------------------------------------------------------------------------------------------
3.5 【July 11, 2021】
[버그 해결 / 사이트 변경에 의한 수정]

View File

@ -1,3 +1,49 @@
3.6 【】
[버그 해결 / 사이트 변경에 의한 수정]
- #2966
- Twitter 일부 계정 무한 로딩 문제 해결
- LHScan 새 도메인 지원 (#3603)
- Hitomi.la 업데이트 대응 (#3638)
- #3641
- 기타 자잘한 것들
[변경/추가된 기능]
- 초기 로딩 시간 최적화
- 썸네일 로딩 시간 최적화
- 설정 파일 (*.ini) 크기 최적화
- 설정 파일 (*.ini) 구조 변경 (신버전에서 작성한 설정 파일 구버전에서 읽을 수 없음)
- 고급 설정에서 스크롤할 때 콤보박스나 슬라이더 반응하지 않도록 수정
- 미리보기 창 크기 조절 가능하게 수정
- 다운로더 작업 목록 필터링했을 때 그룹에 해당 갯수 표시
- 소설가가 되자 꼬릿말 추가 (#2888, #3610)
- 일시정지 후 완료시킬 수 있게 수정 (#3482, #3609)
- 작업 레이지 로딩 끄는 옵션 (#3613)
- Pixiv 파일명 형식 "artistid" 추가 (#3636)
- 기타 자잘한 것들
--------------------------------------------------------------------------------------------------------------------------------------------
3.5 【July 11, 2021】
[버그 해결 / 사이트 변경에 의한 수정]

View File

@ -164,6 +164,7 @@
"비슷한 이미지 포함 (느림)": "Include similar images (Slow)",
"비율 유지": "Aspect ratio",
"비정상적인 로그인 시도": "Abnormal login attempt",
"빠른 시작을 위한 작업 레이지 로딩": "Lazy load tasks for quick start",
"빠른 실행 도구 모음 사용자 지정": "Customize Quick Access Toolbar",
"뽑기": "Random",
"뽑을 갯수": "Number of galleries",
@ -182,6 +183,7 @@
"상태": "Status",
"새 그룹 만들기": "Create a new group",
"새 버전이 있습니다. 업데이트 하실래요?": "There is a new version. Would you like to update?",
"서명": "Certificate",
"서버": "Server",
"선택 화 다운로드": "Select chapters && Download",
"선택된 작업들 내보내기": "Export selected tasks",
@ -291,6 +293,7 @@
"작업": "Tasks",
"작업 개수": "Number of tasks",
"작업 수정": "Edit task",
"작업 왼쪽에서 순서 변경": "Reorder on the left side",
"작업 용량": "File size of tasks",
"작업 정보": "Task info",
"작업 정보... (&I)": "Info... (&I)",

View File

@ -164,6 +164,7 @@
"비슷한 이미지 포함 (느림)": "Incluir imágenes similares (lento)",
"비율 유지": "Mantener relación de aspecto",
"비정상적인 로그인 시도": "Intento de conexión anormal",
"빠른 시작을 위한 작업 레이지 로딩": "Lazy load tasks for quick start",
"빠른 실행 도구 모음 사용자 지정": "Customize Quick Access Toolbar",
"뽑기": "Aleatorio",
"뽑을 갯수": "Numero de galerias",
@ -182,6 +183,7 @@
"상태": "Estado",
"새 그룹 만들기": "Crear un grupo nuevo",
"새 버전이 있습니다. 업데이트 하실래요?": "Hay una nueva versión ¿Quiere actualizar?",
"서명": "Certificate",
"서버": "Servidor",
"선택 화 다운로드": "Seleccionar capítulos && Descargar",
"선택된 작업들 내보내기": "Exportar tareas seleccionadas",
@ -291,6 +293,7 @@
"작업": "Tareas",
"작업 개수": "Número de tareas",
"작업 수정": "Edit task",
"작업 왼쪽에서 순서 변경": "Reorder on the left side",
"작업 용량": "Tamaño de archivo de tarea",
"작업 정보": "Información del trabajo",
"작업 정보... (&I)": "Info... (&I)",

View File

@ -164,6 +164,7 @@
"비슷한 이미지 포함 (느림)": "Inclure les images similaires (lent)",
"비율 유지": "Conserver les proportions",
"비정상적인 로그인 시도": "Tentative de connexion anormale",
"빠른 시작을 위한 작업 레이지 로딩": "Lazy load tasks for quick start",
"빠른 실행 도구 모음 사용자 지정": "Personnaliser la barre d'accès rapide",
"뽑기": "Au hasard",
"뽑을 갯수": "Nombre de galeries",
@ -182,6 +183,7 @@
"상태": "Statut",
"새 그룹 만들기": "Créer un nouveau groupe",
"새 버전이 있습니다. 업데이트 하실래요?": "Il y a une nouvelle version. Voulez-vous mettre à jour ?",
"서명": "Certificate",
"서버": "Serveur",
"선택 화 다운로드": "Sélectionnez les chapitres && Télécharger",
"선택된 작업들 내보내기": "Exporter les tâches sélectionnées",
@ -291,6 +293,7 @@
"작업": "Tâches",
"작업 개수": "Nombre de tâches",
"작업 수정": "Modifier la tâche",
"작업 왼쪽에서 순서 변경": "Reorder on the left side",
"작업 용량": "Taille des fichiers",
"작업 정보": "Informations de la tâche",
"작업 정보... (&I)": "Info... (&I)",
@ -440,4 +443,4 @@
"후원": "Sponsor",
"휴지통으로 이동": "Déplacer dans la corbeille"
}
}
}

View File

@ -164,6 +164,7 @@
"비슷한 이미지 포함 (느림)": "包括相似的图像 (慢)",
"비율 유지": "宽高比",
"비정상적인 로그인 시도": "登录异常",
"빠른 시작을 위한 작업 레이지 로딩": "Lazy load tasks for quick start",
"빠른 실행 도구 모음 사용자 지정": "自定义快速访问工具栏",
"뽑기": "随机",
"뽑을 갯수": "画廊数",
@ -182,6 +183,7 @@
"상태": "状态",
"새 그룹 만들기": "创建新组",
"새 버전이 있습니다. 업데이트 하실래요?": "发现新版本现在更新么?",
"서명": "Certificate",
"서버": "服务器",
"선택 화 다운로드": "选择章节 && 下载",
"선택된 작업들 내보내기": "导出所选任务",
@ -291,6 +293,7 @@
"작업": "任务",
"작업 개수": "完成任务数量",
"작업 수정": "Edit task",
"작업 왼쪽에서 순서 변경": "Reorder on the left side",
"작업 용량": "完成文件大小",
"작업 정보": "任务信息",
"작업 정보... (&I)": "信息... (&I)",