def dump_json(songs):
    """
    Outputs the JSON response of ydl.extract_info to stdout
    :param songs: the songs for which the JSON should be output
    """
    for song in songs:
        query = f"{song.get('artist')} - {song.get('name')}".replace(
            ":", ""
        ).replace('"', "")

        ydl_opts = {"quiet": True}

        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
            try:
                ytJson = {}
                with ytmusicapi.YTMusic() as ym:
                    # Reduce results to array of titles and video IDs
                    search_results = ym.search(query, filter="songs")
                    if len(search_results) == 0:
                        log.warning("No song results found for %s, retrying.", query)
                        search_results = ym.search(query, filter="videos")
                        if len(search_results) == 0:
                            log.error("No search results found for %s, skipping.", query)
                            continue
                    result_titles, result_ids = zip(*map(
                        lambda d: (f"{d['artists'][0]['name']} - {d['title']}".replace(":", "").replace('"', ""), d["videoId"]),
                        search_results
                    ))
                    # Get ID of closest matching result by finding index in titles list
                    videoId = result_ids[result_titles.index(get_closest_match(result_titles, query))]

                    ytJson = ydl.extract_info(f"https://music.youtube.com/watch?v={videoId}", False)
                print(json.dumps([ytJson]))  # insert into array so that the format stays the same
            except Exception as e:  # skipcq: PYL-W0703
                log.debug(e)
                print(
                    f"Failed to download {song.get('name')}, make sure yt_dlp is up to date"
                )
                continue

    Outputs the JSON response of ydl.extract_info to stdout
    :param songs: the songs for which the JSON should be output
    
spotify_dl/youtube.py