Merge branch 'youtube' of github.com:HeIIow2/music-downloader into youtube

This commit is contained in:
Hellow2 2023-06-16 08:39:35 +02:00
commit c513759f1e
6 changed files with 89 additions and 20 deletions

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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]
r = self.download_song_to_target(source=source, target=temp_target, desc=song.title) if not found_on_disc:
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)

View File

@ -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]

View File

@ -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}")