draft: streaming the audio

This commit is contained in:
Hazel 2024-05-15 12:18:08 +02:00
parent 14f986a497
commit cc14253239
3 changed files with 47 additions and 22 deletions

View File

@ -16,6 +16,7 @@ from ..objects import (
Artist, Artist,
Label, Label,
) )
from ..audio import write_metadata_to_target, correct_codec
from ..utils.string_processing import fit_to_file_system from ..utils.string_processing import fit_to_file_system
from ..utils.config import youtube_settings, main_settings from ..utils.config import youtube_settings, main_settings
from ..utils.path_manager import LOCATIONS from ..utils.path_manager import LOCATIONS
@ -125,15 +126,10 @@ class Pages:
return data_object return data_object
def fetch_from_source(self, source: Source, **kwargs) -> Optional[DataObject]: def fetch_from_source(self, source: Source, **kwargs) -> Optional[DataObject]:
page: Page = self._get_page_from_enum(source.source_type) if not source.has_page:
if page is None:
return None return None
# getting the appropriate function for the page and the object type func = getattr(source.page, fetch_map[source_type])(source=source, **kwargs)
source_type = page.get_source_type(source)
if not hasattr(page, fetch_map[source_type]):
return None
func = getattr(page, fetch_map[source_type])(source=source, **kwargs)
# fetching the data object and marking it as fetched # fetching the data object and marking it as fetched
data_object: DataObject = func(source=source) data_object: DataObject = func(source=source)
@ -215,11 +211,6 @@ class Pages:
return possible_parts return possible_parts
def _get_pages_with_source(self, data_object: DataObject, sort_by_attribute: str = "DOWNLOAD_PRIORITY") -> List[Page]:
pages = [self._get_page_from_enum(s.source_type) for s in data_object.source_collection.get_sources()]
pages.sort(key=lambda p: getattr(p, sort_by_attribute), reverse=True)
return list(pages)
def _download_song(self, song: Song, naming: dict) -> DownloadOptions: def _download_song(self, song: Song, naming: dict) -> DownloadOptions:
""" """
TODO TODO
@ -248,7 +239,6 @@ class Pages:
# manage the targets # manage the targets
tmp: Target = Target.temp(file_extension=main_settings["audio_format"]) tmp: Target = Target.temp(file_extension=main_settings["audio_format"])
found_on_disc = False
song.target_collection.append(Target( song.target_collection.append(Target(
relative_to_music_dir=True, relative_to_music_dir=True,
@ -260,17 +250,39 @@ class Pages:
for target in song.target_collection: for target in song.target_collection:
if target.exists(): if target.exists():
output(f'- {target.file_path} {BColors.OKGREEN.value}[already exists]', color=BColors.GREY) output(f'- {target.file_path} {BColors.OKGREEN.value}[already exists]', color=BColors.GREY)
found_on_disc = True
r.found_on_disk += 1 r.found_on_disk += 1
target.copy_content(tmp)
if self.download_options.download_again_if_found:
target.copy_content(tmp)
else: else:
target.create_parent_directories() target.create_parent_directories()
output(f'- {target.file_path}', color=BColors.GREY) output(f'- {target.file_path}', color=BColors.GREY)
# actually download # this streams from every available source until something succeeds, setting the skip intervals to the values of the according source
for page in self._get_pages_with_source(song, sort_by_attribute="DOWNLOAD_PRIORITY"): used_source: Optional[Source] = None
r = page.download_song_to_target(song, tmp, r) skip_intervals: List[Tuple[float, float]] = []
for source in song.source_collection.get_sources(source_type_sorting={
"only_with_page": True,
"sort_key": lambda page: page.download_priority,
"reverse": True,
}):
if tmp.exists:
break
used_source = source
streaming_results = source.page.download_song_to_target(source=source, target=tmp, desc="download")
skip_intervals = source.page.get_skip_intervals(song=song, source=source)
# if something has been downloaded but it somehow failed, delete the file
if streaming_results.is_fatal_error and tmp.exists:
tmp.delete()
# if everything went right, the file should exist now
if not tmp.exists:
r.error_message = f"The song {song.option_string} couldn't be downloaded."
return r
# post process the audio
return r return r

View File

@ -2,7 +2,19 @@ from __future__ import annotations
from collections import defaultdict from collections import defaultdict
from enum import Enum from enum import Enum
from typing import List, Dict, Set, Tuple, Optional, Iterable, Generator, TypedDict, Callable, Any from typing import (
List,
Dict,
Set,
Tuple,
Optional,
Iterable,
Generator,
TypedDict,
Callable,
Any,
TYPE_CHECKING
)
from urllib.parse import urlparse, ParseResult from urllib.parse import urlparse, ParseResult
from dataclasses import dataclass, field from dataclasses import dataclass, field
from functools import cached_property from functools import cached_property
@ -15,6 +27,8 @@ from ..utils.string_processing import hash_url, shorten_display_url
from .metadata import Mapping, Metadata from .metadata import Mapping, Metadata
from .parents import OuterProxy from .parents import OuterProxy
from .collection import Collection from .collection import Collection
if TYPE_CHECKING:
from ..pages.abstract import Page
@ -78,7 +92,7 @@ class Source:
return self.source_type.page is not None return self.source_type.page is not None
@property @property
def page(self) -> OuterProxy: def page(self) -> Page:
return self.source_type.page return self.source_type.page
@property @property

View File

@ -51,7 +51,6 @@ class BandcampTypes(Enum):
class Bandcamp(Page): class Bandcamp(Page):
SOURCE_TYPE = ALL_SOURCE_TYPES.BANDCAMP SOURCE_TYPE = ALL_SOURCE_TYPES.BANDCAMP
LOGGER = logging_settings["bandcamp_logger"]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.connection: Connection = Connection( self.connection: Connection = Connection(