示例#1
0
class ytmUploader:
    """class to use ytmusicapi (https://github.com/sigma67/ytmusicapi) to upload spotifyplaylists"""

    def __init__(self, yt_channel_id, auth_filepath='headers_auth.json'):
        self.ytmusic = YTMusic(auth_filepath)
        self.yt_channel_id = yt_channel_id

    def uploadSpotifyPlaylist(self, spotifyPL):

        plTitle = spotifyPL.get('playlistName')

        print(f"Retrieving songs for album {plTitle}")
        formerPlaylistID = self.getPlaylistID(plTitle)

        # convert Spotify songs to ytmusic video ids
        # Has to be done regardless, to update if exists
        videoIDs = self.ytVideoIDs(spotifyPL)

        if formerPlaylistID:
            # Delete first
            print(f"Deleting: {plTitle}")
            self.ytmusic.delete_playlist(formerPlaylistID)

        # Create playlist
        print(f"Creating: {plTitle}")
        plID = self.ytmusic.create_playlist(title=plTitle, description=f"{plTitle} from Spotify - magic from playmaker script", privacy_status="PUBLIC", video_ids=list(videoIDs))


    def ytVideoIDs(self, spotifyPL):

        ids = []
        """
        plTitle = spotifyPL.get('playlistName')
        if plTitle == 'RapCaviar':
            return rapCaviarIDs
        elif plTitle == 'Most Necessary':
            return mostNecessaryIDs
        elif plTitle == 'Get Turnt':
            return getTurntIDs
            """
        for song in spotifyPL.get('tracks'):
            songname = song[0]
            ytSongs = self.ytmusic.search(songname, "songs")
            if ytSongs:
                topMatchingSong = ytSongs[0]
                ids.append(topMatchingSong.get('videoId'))

        return ids


    def getPlaylistID(self, plTitle):

        userInfo = self.ytmusic.get_user(self.yt_channel_id)

        if 'playlists' in userInfo:
            for song in userInfo.get('playlists').get('results'):
                if song["title"] == plTitle:
                    return song["playlistId"]

        return ""
示例#2
0
文件: guess.py 项目: dlmhds/mu
 def get_playlist(self, genre, playlist_id):
     if playlist_id == None and genre == None:
         return None
     ytmusic = YTMusic()
     if playlist_id == None:
         with open("data/playlist_ids.json", 'r') as f:
             jsondump = json.load(f)
         playlist_id = jsondump[genre]
         playlist_data = ytmusic.get_playlist(playlist_id, 1000)['tracks']
     else:
         playlist_data = ytmusic.get_playlist(playlist_id, 1000)['tracks']
     playlist = Queue()
     for s in playlist_data:
         title = s['title']
         duration = s['duration']
         yt_id = s['videoId']
         artists = []
         for artist in s['artists']:
             artists.append(artist['name'])
         song = Song(title=title,
                     duration=duration,
                     artists=artists,
                     yt_id=yt_id)
         playlist.append(song)
     return playlist
def UpdateLikeSongsSorted(databaseConnectionString: str):
    ytmusic = YTMusic("headers_auth.json")
    mongoClient = MongoClient(databaseConnectionString)
    db = mongoClient['scrobble']
    playlistId = "PLJpUfuX6t6dScH3Ua2f2EsmRC4PolZp8I"
    likedSongs = db['scrobbleCount'].find(
        {
            "likeStatus": 1,
            "ytmusicPlayable": {
                "$ne": False
            }
        },
        sort=[("time", 1)],
        limit=100)
    videoIds = [song['ytmusicId'] for song in likedSongs]
    ClearPlaylist(ytmusic=ytmusic, playlistId=playlistId)
    results = [
        AddToPlaylist(ytmusic=ytmusic, playlistId=playlistId, videoId=videoId)
        for videoId in videoIds
    ]
    if results:
        nowFormatted = datetime.now().strftime("%Y-%m-%d at %H:%M")
        ytmusic.edit_playlist(playlistId=playlistId,
                              description=f"Updated on {nowFormatted}")
    return
示例#4
0
文件: rm_track.py 项目: AllenJB/plt
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-l", "--listId", help="Playlist ID", nargs=1, required=True)
    parser.add_argument("-v", "--videoId", help="Video ID", nargs=1, required=True)
    parser.add_argument("-s", "--setVideoId", help="Set Video ID", nargs=1, required=True)
    args = parser.parse_args()

    logger = logging.getLogger("app")
    logger.setLevel(logging.DEBUG)
    log_formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")

    log_hnd_screen = logging.StreamHandler(stream=sys.stdout)
    log_hnd_screen.setLevel(logging.DEBUG)
    log_hnd_screen.setFormatter(log_formatter)
    logger.addHandler(log_hnd_screen)

    ytmusic = YTMusic('ytm_auth.json')

    locale.setlocale(locale.LC_ALL, 'en_GB')

    list_id = args.listId[0]
    set_video_id = args.setVideoId[0]
    video_id = args.videoId[0]

    logger.info("Playlist: " + list_id)
    logger.info("SetVideoID: "+ set_video_id)
    logger.info("VideoID: "+ video_id)

    playlistItem = {
        "videoId": video_id,
        "setVideoId": set_video_id,
    }
    status = ytmusic.remove_playlist_items(playlistId=list_id, videos=[playlistItem])
    logger.info(pformat(status))
示例#5
0
def setup():
    global ytmusic
    if os.path.exists("headers_auth_raw.txt"):
        with open("headers_auth_raw.txt", "r") as headersRaw:
            YTMusic.setup(filepath="headers_auth.json",
                          headers_raw=headersRaw.read())
        os.remove("headers_auth_raw.txt")
    ytmusic = YTMusic('headers_auth.json')
示例#6
0
def setup_yt_music():
    headers = request.json.get('headers')
    try:
        os.remove('headers_auth.json')
    except FileNotFoundError:
        pass
    YTMusic.setup(filepath='headers_auth.json', headers_raw=headers)
    return {'result': 'New headers_auth.json set'}
示例#7
0
def ClearPlaylist(ytmusic: YTMusic, playlistId: str) -> str:
    trackCount = GetPlaylistTrackCount(ytmusic, playlistId=playlistId)
    if trackCount and trackCount > 0:
        currentPlaylist = ytmusic.get_playlist(playlistId, limit=trackCount)
        return ytmusic.remove_playlist_items(playlistId,
                                             currentPlaylist['tracks'])
    else:
        return
示例#8
0
def search_ytmusic(phrase: str) -> str:
    ytmusic = YTMusic()
    results = ytmusic.search(query=phrase)
    for result in results:
        if result['resultType'] == 'video' or result['resultType'] == 'song':
            return result['videoId']
    # TODO: Notify user if youtube did not find any music in the command channel
    logging.error('Youtube Music did not find any music.')
示例#9
0
 def __init__(self):
     """ Constructor."""
     self.__youtube_music_api = YTMusic(HEADERS_AUTH_FILE_PATH)
     if YoutubeMusicApiSingleton.__instance__ is None:
         YoutubeMusicApiSingleton.__instance__ = self
     else:
         raise Exception(
             "You cannot create another YoutubeMusicApiSingleton class, this class is a singleton"
         )
示例#10
0
def get_auth_obj():
    auth_obj = None
    try:
        auth_obj = YTMusic(const.HEADERS_FILE)
    except (KeyError, AttributeError):
        logging.info(f"Creating {const.HEADERS_FILE} file...")
        auth_obj = YTMusic(YTMusic.setup(filepath=const.HEADERS_FILE))

    return auth_obj
示例#11
0
async def async_check_data(hass, user_input):
    """Check validity of the provided date."""
    ret = {}
    if (CONF_COOKIE in user_input and CONF_HEADER_PATH in user_input):
        # sadly config flow will not allow to have a multiline text field
        # we get a looong string that we've to rearrange into multiline for ytmusic

        # the only thing we need is cookie + x-goog-authuser, lets try to cut this out
        # so the fields are written like 'identifier':'value', but some values actually have ':' inside, bummer.
        c = user_input[CONF_COOKIE]
        clean_cookie = ""
        clean_x_goog_authuser = ""
        ## lets try to find the cookie part
        cookie_pos = c.lower().find('cookie')
        if (cookie_pos >= 0):
            #_LOGGER.debug("found cookie in text")
            cookie_end = c[cookie_pos:]
            cookie_end_split = cookie_end.split(':')
            if (len(cookie_end_split) >= 3):
                #_LOGGER.debug("found three or more sections")
                cookie_length_last_field = cookie_end_split[2].rfind(' ')
                if (cookie_length_last_field >= 0):
                    #_LOGGER.debug("found a space")
                    cookie_length = len(cookie_end_split[0]) + 1 + len(
                        cookie_end_split[1]) + 1 + cookie_length_last_field
                    clean_cookie = c[cookie_pos:cookie_pos + cookie_length]
                    #_LOGGER.debug(clean_cookie)
        ## lets try to find x-auth-part
        xauth_pos = c.lower().find('x-goog-authuser: '******'x-goog-authuser: '******'x-goog-authuser: '******' ')
            #_LOGGER.debug(xauth_len)
            if (xauth_len >= 0):
                #_LOGGER.debug("found space in text")
                clean_x_goog_authuser = c[xauth_pos:(xauth_pos +
                                                     len('x-goog-authuser: '******'ve failed to find the cookie, the only thing we can do is at least to help with some breaks
            c = c.replace('cookie', '\ncookie')
            c = c.replace('Cookie', '\nCookie')
            c = c.replace('x-goog-authuser', '\nx-goog-authuser')
            c = c.replace('X-Goog-AuthUser', '\nX-Goog-AuthUser')
        #_LOGGER.debug("feeding with: ")
        #_LOGGER.debug(c)
        YTMusic.setup(filepath=user_input[CONF_HEADER_PATH], headers_raw=c)
        [ret, msg,
         api] = await async_try_login(hass, user_input[CONF_HEADER_PATH], "")
    return ret
示例#12
0
def authenticate(reset=False):
    global ytmusic

    if reset:
        os.remove(authFile)
    if authFile.exists():
        ytmusic = YTMusic(authFile)
    else:
        YTMusic.setup(filepath=authFile)
        exit(0)
示例#13
0
 def upload(self, mp3_files, dry_run=False, overwrite=False):
     for mp3_file in mp3_files:
         track = self.get_track(mp3_file=mp3_file)
         if track is not None and not overwrite:
             logging.info("Skipping %s", mp3_file)
         else:
             logging.info("Uploading %s", mp3_file)
             if not dry_run:
                 if track is not None:
                     self.delete(tracks=[track])
                 YTMusic.upload_song(mp3_file.file_path)
示例#14
0
def play_music(text):
    ytmusic = YTMusic()
    songs = ytmusic.search(f'{text}')
    pprint(songs)
    for material in songs:
        material_type = material['resultType']
        if material_type=='song':
            id = material['videoId']
            break

    webbrowser.open_new_tab(f'https://music.youtube.com/watch?v={id}')
示例#15
0
    def __init__(
        self,
        auth_file_path="/home/vvasuki/sysconf/kunchikA/google/vishvas/yt_music.json"
    ):
        YTMusic.setup(filepath=auth_file_path)
        # Returns a list of dictionaries, one for each audio track, each with the following keys: ('browseId', 'title', 'album', 'album_artist', 'artist', 'track_number', 'track_size', 'disc_number', 'total_disc_count').
        self.uploaded_tracks = YTMusic.get_library_upload_songs(limit=50000)

        self.albums = sorted(
            set(map(lambda track: track["album"], self.uploaded_tracks)))
        self.artists = sorted(
            set(map(lambda track: track["artist"], self.uploaded_tracks)))
示例#16
0
    def __init__(self):
        super(YoutubeMusicSkill, self).__init__()
        self.yt = YTMusic()
        self.idle_count = 0
        self.ducking = False
        self.mouth_text = None

        self._playlists = None
        self.saved_tracks = None
        self.regexes = {}
        self.last_played_type = None  # The last uri type that was started
        self.is_playing = False
示例#17
0
def youtube_lyrics(youtube_id: str) -> Tuple[str, str, Dict]:
    """Gets lyrics (if exists) given the youtube id.
    NOTE: get_lyrics operation is wasteful as it discards a watch playlist while getting lyrics."""
    ytmusic = YTMusic()
    # TODO: Make more efficent use of watch_playlist
    watch_playlist = ytmusic.get_watch_playlist(videoId=youtube_id)

    browse_id = watch_playlist["lyrics"]
    if browse_id:
        result = ytmusic.get_lyrics(browse_id)
        return result["lyrics"], result["source"], watch_playlist

    return None, None, watch_playlist
示例#18
0
def playlist(id, doubles=False, skipErrors=False):
    if id is None:
        if not os.path.exists(os.path.expanduser("~/.ymusic.json")):
            auth()
        list = YTMusic(
            os.path.expanduser("~/.ymusic.json")).get_liked_songs(limit)
    else:
        if re.match(r"^https://", id):
            id = id.split('list=')[1]
        try:
            list = YTMusic().get_playlist(id, limit)
        except:
            if not os.path.exists(os.path.expanduser("~/.ymusic.json")):
                auth()
            list = YTMusic(os.path.expanduser("~/.ymusic.json")).get_playlist(
                id, limit)
    if doubles is False:
        for song in list['tracks']:
            if song['videoId'] is not None:
                fname = re.sub('[^-а-яА-Яa-zA-Z0-9_.() ]+', '',
                               song['title']).strip()
                if song['album'] is not None:
                    fname = os.path.join(
                        re.sub('[^-а-яА-Яa-zA-Z0-9_.() ]+', '',
                               song['album']['name']).strip(), fname)
                if not os.path.exists(fname + '.mp3'):
                    if skipErrors is False:
                        foreach(song, fname)
                    else:
                        try:
                            foreach(song, fname)
                        except:
                            print('Error: vid: ' + song['videoId'])
                else:
                    print('[youtube-music] Skiping: ' + fname)
        print('Finish')
    else:
        titles = []
        ids = []
        for song in list['tracks']:
            if song['videoId'] is not None:
                id = song['videoId']
                title = song['title'].split(' [')[0].split(' (')[0]
                if title in titles:
                    print('\n' + title)
                    print('https://music.youtube.com/watch?v=' +
                          ids[titles.index(title)])
                    print('https://music.youtube.com/watch?v=' + id)
                else:
                    titles.append(title)
                    ids.append(id)
class Youtube:
    def __init__(self):
        self.ytmusic = YTMusic()
        self.thumburl = "https://i.ytimg.com/vi/{vid_id}/sddefault.jpg"
        self.vidurl = "https://www.youtube.com/watch?v={vid_id}"

    def _get_cleaned_track_data(self, result: dict) -> Song:
        try:
            vid_id = result['videoId']
            title = result['title']
            album = title
            artist = result['artists'][0][
                'name'] if 'artists' in result else result['author']
            imgurl = self.thumburl.format(vid_id=vid_id)

            return Song(vidurl=self.vidurl.format(vid_id=vid_id),
                        title=title,
                        artist=artist,
                        album=album,
                        imgurl=imgurl)

        except Exception as e:
            return None

    def get_playlist_tracks(self,
                            playlist_id: str,
                            limit: int = None) -> Union[Iterator[Song], None]:
        '''
        Get a genrator of Songs from the given playlist_id
        Works only for public playlists.
        '''
        if limit is None:
            limit = 10000

        try:
            tracks = self.ytmusic.get_playlist(playlist_id,
                                               limit=limit)['tracks']
        except KeyError:
            print('Invalid playlist or playlist is empty.')
            return None

        for track in tracks:
            yield self._get_cleaned_track_data(track)

    def get_song(self, song_name: str) -> Union[Song, None]:
        '''Get Song from a song name'''
        vidurl = get_yt_url(song_name)
        vid_id = re.search(r"watch\?v=(\S{11})", vidurl).group(1)
        return self._get_cleaned_track_data(self.ytmusic.get_song(vid_id))
示例#20
0
文件: web.py 项目: AllenJB/plt
def ytm_plsearch():
    cursor = db_connect()
    ytmusic = YTMusic('ytm_auth.json')

    term = request.form.get("term")

    recently_played = None
    results = None
    if term is None:
        try:
            recently_played = ytmusic.get_history()
            recently_played = ytm_attach_playlists(recently_played, cursor)
        except KeyError as ex:
            ex_type, ex_value, ex_trace = sys.exc_info()
            flash(
                "Failed to retrieve history: KeyError: " + str(ex) + "\n" +
                ("".join(
                    traceback.format_exception(ex_type, ex_value, ex_trace))),
                "error")
    else:
        sql = """
            SELECT DISTINCT ytm_playlist_entries.entry_name, ytm_playlist_entries.duration, 
                ytm_playlist_entries.artist_name, ytm_playlist_entries.album_name,
                ytm_playlist_entries.ytm_videoid AS videoId
            FROM ytm_playlist_entries
            LEFT JOIN ytm_playlists ON ytm_playlist_entries.ytm_playlistid = ytm_playlists.ytm_playlistid
            WHERE ytm_playlist_entries.deleted = 0
                AND ytm_playlists.deleted = 0
                AND (
                    ytm_playlist_entries.entry_name LIKE CONCAT('%%', %(term)s, '%%')
                    OR ytm_playlist_entries.artist_name LIKE CONCAT('%%', %(term)s, '%%')
                    OR ytm_playlist_entries.album_name LIKE CONCAT('%%', %(term)s, '%%')
                )
            ORDER BY ytm_playlist_entries.artist_name ASC, 
                ytm_playlist_entries.entry_name ASC, 
                ytm_playlist_entries.album_name ASC
        """
        params = {
            "term": term,
        }
        cursor.execute(sql, params)
        results = cursor.fetchall()
        results = ytm_attach_playlists(results, cursor)

    return render_template("ytm/plsearch.html",
                           history=recently_played,
                           results=results,
                           term=term,
                           ytm_list_artist_names=ytm_list_artist_names)
示例#21
0
文件: musicguesser.py 项目: dlmhds/mu
    def __init__(self,bot):
        self.bot = bot

        with open("data/score.json",'r') as f:
            jsondump = json.load(f)
        self.scores = jsondump #stores the cumulative score of a server
        with open("data/playlist_ids.json", 'r') as f:
            jsondump = json.load(f)
        self.playlist_ids = jsondump
        self.ytmusic = YTMusic()
        self.pop_playlist = self.ytmusic.get_playlist(self.playlist_ids['pop'],300)['tracks']
        self.local_scores = {} #stores the score for each game
        self.guess_data = {
            #"server": {"channelid":"","song playing":"","played":""}
        }
示例#22
0
def MixPlaylists(ytmusic: YTMusic, playlistId1: str, playlistId2: str,
                 finalPlaylistId: str) -> bool:
    playlist1 = ytmusic.get_playlist(playlistId1)
    playlist1Songs = playlist1['tracks']
    playlist2 = ytmusic.get_playlist(playlistId2)
    playlist2Songs = playlist2['tracks']
    songIds = [track['videoId'] for track in playlist1Songs + playlist2Songs]

    ClearPlaylist(ytmusic=ytmusic, playlistId=finalPlaylistId)
    random.shuffle(songIds)
    results = [
        AddToPlaylist(ytmusic=ytmusic,
                      playlistId=finalPlaylistId,
                      videoId=videoId) for videoId in songIds
    ]
    return sum(results) > 0
示例#23
0
def GetSongId(ytmusic: YTMusic, db: Database, videoId: str) -> ObjectId:
    try:
        songDocument = db['songs'].find_one({"ytmusicId": videoId},
                                            {"ytmusicId": 1})
        if songDocument is None:
            watchPlaylist = ytmusic.get_watch_playlist(videoId)
            browseId = None
            songInfo = watchPlaylist['tracks'][0]
            documentData = {
                "title": songInfo['title'],
                "artists": [artist['name'] for artist in songInfo['artists']],
                "ytmusicId": songInfo['videoId']
            }
            if "album" in songInfo:
                documentData['album'] = songInfo['album']['name']
                browseId = songInfo['album']['id']
            likeStatus = GetLikeStatus(ytmusic, videoId, browseId, db)
            if likeStatus:
                documentData['likeStatus'] = likeStatus.value
            result = db['songs'].insert_one(documentData)
            songId = result.inserted_id
        else:
            songId = songDocument['_id']
        return songId
    except Exception as e:
        print(f"GetSongId Error: {e}")
        return None
示例#24
0
文件: ls.py 项目: AllenJB/plt
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("-l", "--listId", help="Playlist ID", nargs=1)
    args = parser.parse_args()

    logger = logging.getLogger("app")
    logger.setLevel(logging.DEBUG)
    log_formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")

    log_hnd_screen = logging.StreamHandler(stream=sys.stdout)
    log_hnd_screen.setLevel(logging.ERROR)
    log_hnd_screen.setFormatter(log_formatter)
    logger.addHandler(log_hnd_screen)

    ytmusic = YTMusic('ytm_auth.json')

    # loc = locale.getlocale()
    locale.setlocale(locale.LC_ALL, 'en_GB')

    only_list_id = None
    if args.listId is None:
        logger.info("No list id given - listing all playlists")
        list_playlists(ytmusic)
    else:
        only_list_id = args.listId[0]
        logger.info("Listing tracks for playlist: " + only_list_id)
        list_tracks(ytmusic, only_list_id)
 def setUpClass(cls) -> None:
     cls._logger = logging.getLogger(__name__)
     cls._downloader = Downloader(cls._logger, Path(".", "..").resolve())
     cls._time_zone = pytz.timezone("Australia/Brisbane")
     cls._client = YouTubeMusic(cls._logger, cls._downloader,
                                cls._time_zone)
     cls._client._client = YTMusic()
示例#26
0
def main():
    path = sys.argv[1]
    if not os.path.exists(path):
        print("Invalid file path. %s" % path)
        return

    api = YTMusic('headers_auth.json')

    #if not api.is_authenticated():
    #    print("Login Error\n")
    #    return

    print("start upload...\n")
    upload_info = api.upload_song(path)
    print(upload_info)
    print("upload is completed.\n")
示例#27
0
def youtube_music(phrase: str) -> str:
    """Searches Youtube Music using the phase and returns the top video result's ID

    Args:
        phrase (str): phrase to search Youtube Music

    Returns:
        str: youtube video ID
    """
    ytmusic = YTMusic()
    results = ytmusic.search(query=phrase)
    for result in results:
        if result["resultType"] == "video" or result["resultType"] == "song":
            return result["videoId"]
    # TODO: Notify user if youtube did not find any music in the command channel
    logging.error("Youtube Music did not find any music.")
示例#28
0
def setup():
    try:
        return YTMusic(os.path.join(__package__, "headers_auth.json"))
    except KeyError:
        sys.exit("Cookie invalid. Did you paste your cookie into headers_auth.json?")
    except AttributeError:
        sys.exit("Headers not found. Most likely the headers_auth.json file could not be located.")
def upload(
    directory: str = '.',
    oauth: str = os.environ['HOME'] + '/oauth',
    remove: bool = False,
    oneshot: bool = False,
    listener_only: bool = False,
    deduplicate_api: str = None,
    log: str = None,
) -> None:
    global last_snapshot

    handler = logging.handlers.WatchedFileHandler(
        log) if log else logging.StreamHandler()
    handler.setLevel(logging.DEBUG)
    handler.setFormatter(
        logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    logger.addHandler(handler)
    logger.info("Init Daemon - Press Ctrl+C to quit")

    api = YTMusic(oauth)
    if not api:
        raise ValueError("Error with credentials")
    observer = None
    deduplicate = DeduplicateApi(deduplicate_api) if deduplicate_api else None
    if not oneshot:
        if os.path.isdir(directory):
            last_snapshot = DirectorySnapshot(directory)
        event_handler = MusicToUpload()
        event_handler.api = api
        event_handler.oauth = oauth
        event_handler.path = directory
        event_handler.remove = remove
        event_handler.logger = logger
        event_handler.deduplicate_api = deduplicate
        observer = Observer()
        observer.schedule(event_handler, directory, recursive=True)
        observer.start()
    if not listener_only:
        files = [
            file for file in glob.glob(glob.escape(directory) + '/**/*',
                                       recursive=True)
        ]
        for file_path in files:
            upload_file(api,
                        file_path,
                        logger,
                        remove=remove,
                        deduplicate_api=deduplicate)
    if oneshot:
        sys.exit(0)
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
示例#30
0
 def get_ytm_api(self):
     try:
         ytmusic = YTMusic()
         return ytmusic
     except Exception as e:
         self.logger.error("Something went wrong getting Youtube Music API")
         self.logger.error(e)
         return None