Merge branch 'youtube' of github.com:HeIIow2/music-downloader into youtube
This commit is contained in:
commit
c513759f1e
@ -45,9 +45,9 @@ def correct_codec(target: Target, bitrate_kb: int = BITRATE, audio_format: str =
|
|||||||
|
|
||||||
# run the ffmpeg command with a progressbar
|
# run the ffmpeg command with a progressbar
|
||||||
ff = FfmpegProgress(ffmpeg_command)
|
ff = FfmpegProgress(ffmpeg_command)
|
||||||
with tqdm(total=100, position=1, desc="ffmpeg") as pbar:
|
with tqdm(total=100, desc="ffmpeg") as pbar:
|
||||||
for progress in ff.run_command_with_progress():
|
for progress in ff.run_command_with_progress():
|
||||||
pbar.update(progress - pbar.n)
|
pbar.update(int(progress)-pbar.n)
|
||||||
|
|
||||||
LOGGER.debug(ff.stderr)
|
LOGGER.debug(ff.stderr)
|
||||||
|
|
||||||
|
@ -4,9 +4,11 @@ from urllib.parse import urlparse, urlunsplit, ParseResult
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
from .rotating import RotatingProxy
|
from .rotating import RotatingProxy
|
||||||
from ..utils.shared import PROXIES_LIST
|
from ..utils.shared import PROXIES_LIST, CHUNK_SIZE
|
||||||
|
from ..objects import Target
|
||||||
|
|
||||||
|
|
||||||
class Connection:
|
class Connection:
|
||||||
@ -196,3 +198,51 @@ class Connection:
|
|||||||
self.LOGGER.warning(f"Max attempts ({self.TRIES}) exceeded for: GET:{url}")
|
self.LOGGER.warning(f"Max attempts ({self.TRIES}) exceeded for: GET:{url}")
|
||||||
self.LOGGER.warning(f"payload: {json}")
|
self.LOGGER.warning(f"payload: {json}")
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
def stream_into(
|
||||||
|
self,
|
||||||
|
url: str,
|
||||||
|
target: Target,
|
||||||
|
description: str = "download",
|
||||||
|
refer_from_origin: bool = True,
|
||||||
|
accepted_response_codes: set = None,
|
||||||
|
timeout: float = None,
|
||||||
|
headers: dict = None,
|
||||||
|
raw_url: bool = False,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
r = self._request(
|
||||||
|
request=self.session.get,
|
||||||
|
try_count=0,
|
||||||
|
accepted_response_code=accepted_response_codes or self.ACCEPTED_RESPONSE_CODES,
|
||||||
|
url=url,
|
||||||
|
timeout=timeout,
|
||||||
|
headers=headers,
|
||||||
|
raw_url=raw_url,
|
||||||
|
refer_from_origin=refer_from_origin,
|
||||||
|
stream=True,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
if r is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
target.create_path()
|
||||||
|
total_size = int(r.headers.get('content-length'))
|
||||||
|
|
||||||
|
with target.open("wb") as f:
|
||||||
|
try:
|
||||||
|
"""
|
||||||
|
https://en.wikipedia.org/wiki/Kilobyte
|
||||||
|
> The internationally recommended unit symbol for the kilobyte is kB.
|
||||||
|
"""
|
||||||
|
with tqdm(total=total_size, unit='B', unit_scale=True, unit_divisor=1024, desc=description) as t:
|
||||||
|
|
||||||
|
for chunk in r.iter_content(chunk_size=CHUNK_SIZE):
|
||||||
|
size = f.write(chunk)
|
||||||
|
t.update(size)
|
||||||
|
return True
|
||||||
|
|
||||||
|
except requests.exceptions.ConnectionError:
|
||||||
|
self.LOGGER.error("Stream timed out.")
|
||||||
|
return False
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple, TextIO
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
@ -99,5 +99,8 @@ class Target(DatabaseObject):
|
|||||||
shared.DOWNLOAD_LOGGER.error("Stream timed out.")
|
shared.DOWNLOAD_LOGGER.error("Stream timed out.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def open(self, file_mode: str, **kwargs) -> TextIO:
|
||||||
|
return self.file_path.open(file_mode, **kwargs)
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
self.file_path.unlink(missing_ok=True)
|
self.file_path.unlink(missing_ok=True)
|
||||||
|
@ -382,6 +382,7 @@ class Page:
|
|||||||
file=DOWNLOAD_FILE.format(**{part[1]: naming_dict[part[1]] for part in file_parts})
|
file=DOWNLOAD_FILE.format(**{part[1]: naming_dict[part[1]] for part in file_parts})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if song.target_collection.empty:
|
if song.target_collection.empty:
|
||||||
song.target_collection.append(new_target)
|
song.target_collection.append(new_target)
|
||||||
|
|
||||||
@ -394,16 +395,29 @@ class Page:
|
|||||||
file=str(random.randint(0, 999999))
|
file=str(random.randint(0, 999999))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
found_on_disc = False
|
||||||
|
target: Target
|
||||||
|
for target in song.target_collection:
|
||||||
|
if target.exists:
|
||||||
|
target.copy_content(temp_target)
|
||||||
|
found_on_disc = True
|
||||||
|
break
|
||||||
|
|
||||||
|
r = DownloadResult(1)
|
||||||
|
|
||||||
source = sources[0]
|
source = sources[0]
|
||||||
|
if not found_on_disc:
|
||||||
r = self.download_song_to_target(source=source, target=temp_target, desc=song.title)
|
r = self.download_song_to_target(source=source, target=temp_target, desc=song.title)
|
||||||
|
else:
|
||||||
|
self.LOGGER.info(f"{song.option_string} already exists, thus not downloading again.")
|
||||||
|
|
||||||
if not r.is_fatal_error:
|
if not r.is_fatal_error:
|
||||||
r.merge(self._post_process_targets(song, temp_target, source))
|
r.merge(self._post_process_targets(song, temp_target, [] if found_on_disc else self.get_skip_intervals(song, source)))
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def _post_process_targets(self, song: Song, temp_target: Target, source: Source) -> DownloadResult:
|
def _post_process_targets(self, song: Song, temp_target: Target, interval_list: List) -> DownloadResult:
|
||||||
correct_codec(temp_target, interval_list=self.get_skip_intervals(song, source))
|
correct_codec(temp_target, interval_list=interval_list)
|
||||||
|
|
||||||
self.post_process_hook(song, temp_target)
|
self.post_process_hook(song, temp_target)
|
||||||
|
|
||||||
|
@ -5,8 +5,6 @@ from enum import Enum
|
|||||||
import sponsorblock
|
import sponsorblock
|
||||||
from sponsorblock.errors import HTTPException, NotFoundException
|
from sponsorblock.errors import HTTPException, NotFoundException
|
||||||
|
|
||||||
from music_kraken.objects import Song, Source
|
|
||||||
|
|
||||||
from ..objects import Source, DatabaseObject, Song, Target
|
from ..objects import Source, DatabaseObject, Song, Target
|
||||||
from .abstract import Page
|
from .abstract import Page
|
||||||
from ..objects import (
|
from ..objects import (
|
||||||
@ -373,11 +371,9 @@ class YouTube(Page):
|
|||||||
|
|
||||||
endpoint = audio_format["url"]
|
endpoint = audio_format["url"]
|
||||||
|
|
||||||
r = self.download_connection.get(endpoint, stream=True, raw_url=True)
|
self.download_connection.stream_into(endpoint, target, description=desc, raw_url=True)
|
||||||
if r is None:
|
|
||||||
return DownloadResult(error_message=f"Couldn't connect to {endpoint}")
|
|
||||||
|
|
||||||
if target.stream_into(r, desc=desc):
|
if self.download_connection.get(endpoint, stream=True, raw_url=True):
|
||||||
return DownloadResult(total=1)
|
return DownloadResult(total=1)
|
||||||
return DownloadResult(error_message=f"Streaming to the file went wrong: {endpoint}, {str(target.file_path)}")
|
return DownloadResult(error_message=f"Streaming to the file went wrong: {endpoint}, {str(target.file_path)}")
|
||||||
|
|
||||||
@ -398,4 +394,7 @@ class YouTube(Page):
|
|||||||
except HTTPException as e:
|
except HTTPException as e:
|
||||||
self.LOGGER.warning(f"{e}")
|
self.LOGGER.warning(f"{e}")
|
||||||
|
|
||||||
|
if len(segments) > 0:
|
||||||
|
print(f"Removing {len(segments)} interruptions in the audio...")
|
||||||
|
|
||||||
return [(segment.start, segment.end) for segment in segments]
|
return [(segment.start, segment.end) for segment in segments]
|
||||||
|
@ -58,7 +58,7 @@ class Config:
|
|||||||
self._name_section_map[name] = element
|
self._name_section_map[name] = element
|
||||||
self._length += 1
|
self._length += 1
|
||||||
|
|
||||||
def set_name_to_value(self, name: str, value: str):
|
def set_name_to_value(self, name: str, value: str, silent: bool = True):
|
||||||
"""
|
"""
|
||||||
:raises SettingValueError, SettingNotFound:
|
:raises SettingValueError, SettingNotFound:
|
||||||
:param name:
|
:param name:
|
||||||
@ -66,6 +66,9 @@ class Config:
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if name not in self._name_section_map:
|
if name not in self._name_section_map:
|
||||||
|
if silent:
|
||||||
|
LOGGER.warning(f"The setting \"{name}\" is either deprecated, or doesn't exist.")
|
||||||
|
return
|
||||||
raise SettingNotFound(setting_name=name)
|
raise SettingNotFound(setting_name=name)
|
||||||
|
|
||||||
LOGGER.debug(f"setting: {name} value: {value}")
|
LOGGER.debug(f"setting: {name} value: {value}")
|
||||||
|
Loading…
Reference in New Issue
Block a user