searchForTrack method

  1. @override
Stream<LazyYouTubeResult> searchForTrack(
  1. String query, [
  2. int itemCount = 7
])
override

Searches YouTube for the given query.

Implementation

@override
Stream<LazyYouTubeResult> searchForTrack(
  String query, [
  itemCount = 7,
]) async* {
  var searchResults = await _youtubeEngine.search.search(query);

  // We use this to track the number of results we've processed proactively
  // as result processing is kinda slow ~1s per result.
  var resultCount = 0;

  while (resultCount < itemCount) {
    resultCount++;
    var cResult = searchResults.removeAt(0);

    var mainArtist = cResult.author.split('- Topic').first;

    // We extract the album name from the description if it starts with 'Provided to YouTube by '.
    // NOTE: auto-generated youtube description goes like this:

    // -------------------------------------------------------------------------------------------
    // Example #01
    // -------------------------------------------------------------------------------------------
    //
    // Provided to YouTube by DistroKid                                       (Provider)
    // Ira · Ivory Rasmus                                                     (Title) · (Artist)
    // Ira                                                                    (Album)
    // ℗ And Friends                                                          (Label)

    // -------------------------------------------------------------------------------------------
    // Example #02
    // -------------------------------------------------------------------------------------------
    // Provided to YouTube by Universal Music Group                           (Provider)
    // Abracadabra · Lady Gaga                                                (Title) · (Artist)
    // Abracadabra                                                            (Album)
    // ℗ 2024 Interscope Records                                              (Label)
    //
    // -------------------------------------------------------------------------------------------

    // We're using a convoluted split because the scraped description doesn't always come with
    // "\n\n" even if youtube has the newlines in it's rendering.
    String? album;

    if (cResult.description.startsWith('Provided to YouTube by ')) {
      try {
        album = cResult.description.split(mainArtist)[1].split('℗').first.trim();
      } catch (_) {
        album = null;
      }
    }

    // Add the search result to the list.
    yield LazyYouTubeResult(
      artists: () async* {
        yield mainArtist;
      },
      title: () async => cResult.title,
      album: () async => album ?? '',
      sDuration: () async => cResult.duration?.inSeconds ?? 0,
      srcUrl: () async => cResult.url,
      source: () async => Source.youtube,
      dlUrl: () async {
        final streamManifest = await _youtubeEngine.videos.streams.getManifest(cResult.id);

        return streamManifest.audioOnly.withHighestBitrate().url.toString();
      },
      artUrl: () async => '',
    );

    // If the search results are empty, fetch the next page.
    if (searchResults.isEmpty) {
      var nextResultSet = await searchResults.nextPage();

      if (nextResultSet == null || nextResultSet.isEmpty) {
        break;
      } else {
        searchResults = nextResultSet;
      }
    }
  }
}