示例#1
0
    def write_m3u(self, track_file, target_file=None):
        with open(track_file, "r") as fin:
            tracks = fin.read().splitlines()

        logger.info(
            "Checking and removing any duplicate tracks in {}.".format(track_file)
        )
        # Remove duplicates and empty elements
        # Also strip whitespaces from elements (if any)
        tracks = spotdl.util.remove_duplicates(
            tracks,
            condition=lambda x: x,
            operation=str.strip
        )

        if target_file is None:
            target_file = "{}.m3u".format(track_file.split(".")[0])

        total_tracks = len(tracks)
        logger.info("Generating {0} from {1} YouTube URLs.".format(target_file, total_tracks))
        write_to_stdout = target_file == "-"
        m3u_headers = "#EXTM3U\n\n"
        if write_to_stdout:
            sys.stdout.write(m3u_headers)
        else:
            with open(target_file, "w") as output_file:
                output_file.write(m3u_headers)

        videos = []
        for n, track in enumerate(tracks, 1):
            search_metadata = MetadataSearch(
                track,
                lyrics=not self.arguments["no_metadata"],
                yt_search_format=self.arguments["search_format"],
                yt_manual=self.arguments["manual"]
            )
            try:
                video = search_metadata.best_on_youtube_search()
            except (NoYouTubeVideoFoundError, NoYouTubeVideoMatchError) as e:
                logger.error(e.args[0])
            else:
                logger.info(
                    "Matched track {0}/{1} ({2})".format(
                        str(n).zfill(len(str(total_tracks))),
                        total_tracks,
                        video["url"],
                    )
                )
                m3u_key = "#EXTINF:{duration},{title}\n{youtube_url}\n".format(
                    duration=spotdl.util.get_sec(video["duration"]),
                    title=video["title"],
                    youtube_url=video["url"],
                )
                logger.debug(m3u_key.strip())
                if write_to_stdout:
                    sys.stdout.write(m3u_key)
                else:
                    with open(target_file, "a") as output_file:
                        output_file.write(m3u_key)
示例#2
0
    def download_tracks_from_file(self, path):
        logger.info(
            'Checking and removing any duplicate tracks in "{}".'.format(path)
        )
        tracks = spotdl.util.readlines_from_nonbinary_file(path)
        tracks = self.strip_and_filter_duplicates(tracks)

        if self.arguments["skip_file"]:
            len_tracks_before = len(tracks)
            tracks = self.filter_against_skip_file(tracks, self.arguments["skip_file"])
            logger.info("Skipping {} tracks due to matches in skip file.".format(
                len_tracks_before - len(tracks))
            )
        # Overwrite file
        spotdl.util.writelines_to_nonbinary_file(path, tracks)

        logger.info(
            "Downloading {n} tracks.\n".format(n=len(tracks))
        )

        for position, track in enumerate(tracks, 1):
            search_metadata = MetadataSearch(
                track,
                lyrics=True,
                yt_search_format=self.arguments["search_format"],
                yt_manual=self.arguments["manual"]
            )
            log_track_query = '{position}. Downloading "{track}"'.format(
                position=position,
                track=track
            )
            logger.info(log_track_query)
            try:
                metadata = search_metadata.on_youtube_and_spotify()
                self.download_track_from_metadata(metadata)
            except (urllib.request.URLError, TypeError, IOError) as e:
                logger.exception(e.args[0])
                logger.warning(
                    "Failed to download current track due to possible network issue. "
                    "Will retry after other songs."
                )
                tracks.append(track)
            except (NoYouTubeVideoFoundError, NoYouTubeVideoMatchError) as e:
                logger.error("{err}".format(err=e.args[0]))
            except KeyboardInterrupt:
                # The current track hasn't been downloaded completely.
                # Make sure we continue from here the next the program runs.
                tracks.insert(0, track)
                raise
            else:
                if self.arguments["write_successful_file"]:
                    with open(self.arguments["write_successful_file"], "a") as fout:
                        fout.write("{}\n".format(track))
            finally:
                spotdl.util.writelines_to_nonbinary_file(path, tracks[position:])
                print("", file=sys.stderr)
示例#3
0
    def download_track(self, track):
        subtracks = track.split("::")
        download_track = subtracks[0]
        custom_metadata_track = len(subtracks) > 1
        if custom_metadata_track:
            metadata_track = subtracks[1]
        else:
            metadata_track = download_track

        search_metadata = MetadataSearch(
            metadata_track,
            lyrics=not self.arguments["no_metadata"],
            yt_search_format=self.arguments["search_format"],
            yt_manual=self.arguments["manual"]
        )

        def threaded_metadata():
            try:
                if self.arguments["no_metadata"]:
                    metadata = search_metadata.on_youtube()
                else:
                    metadata = search_metadata.on_youtube_and_spotify()
            except (NoYouTubeVideoFoundError, NoYouTubeVideoMatchError) as e:
                logger.error(e.args[0])
            else:
                return metadata

        metadata = spotdl.util.ThreadWithReturnValue(target=threaded_metadata)
        metadata.start()
        if not custom_metadata_track:
            metadata = metadata.join()
            if not metadata:
                return
            return self.download_track_from_metadata(metadata)

        search_metadata = MetadataSearch(
            download_track,
            lyrics=False,
            yt_search_format=self.arguments["search_format"],
            yt_manual=self.arguments["manual"]
        )
        try:
            download_track_metadata = search_metadata.on_youtube()
        except (NoYouTubeVideoFoundError, NoYouTubeVideoMatchError) as e:
            logger.error(e.args[0])
            return

        metadata = metadata.join()
        if not metadata:
            return

        logger.info('Overriding metadata as per passed metadata-track'.format(metadata_track))
        metadata["streams"] = download_track_metadata["streams"]
        return self.download_track_from_metadata(metadata)
示例#4
0
 def download_track(self, track):
     logger.info('Downloading "{}"'.format(track))
     search_metadata = MetadataSearch(
         track,
         lyrics=not self.arguments["no_metadata"],
         yt_search_format=self.arguments["search_format"],
         yt_manual=self.arguments["manual"])
     try:
         if self.arguments["no_metadata"]:
             metadata = search_metadata.on_youtube()
         else:
             metadata = search_metadata.on_youtube_and_spotify()
     except (NoYouTubeVideoFoundError, NoYouTubeVideoMatchError) as e:
         logger.error(e.args[0])
     else:
         self.download_track_from_metadata(metadata)