| 7 | |
| 8 | |
| 9 | class CustomAudioTrack(DeferredAudioTrack): |
| 10 | # A DeferredAudioTrack allows us to load metadata now, and a playback URL later. |
| 11 | # This makes the DeferredAudioTrack highly efficient, particularly in cases |
| 12 | # where large playlists are loaded. |
| 13 | |
| 14 | async def load(self, client): # Load our 'actual' playback track using the metadata from this one. |
| 15 | result: LoadResult = await client.get_tracks('ytsearch:{0.title} {0.author}'.format(self)) # Search for our track on YouTube. |
| 16 | |
| 17 | if result.load_type != LoadType.SEARCH or not result.tracks: # We're expecting a 'SEARCH' due to our 'ytsearch' prefix above. |
| 18 | raise LoadError |
| 19 | |
| 20 | first_track = result.tracks[0] # Grab the first track from the results. |
| 21 | base64 = first_track.track # Extract the base64 string from the track. |
| 22 | self.track = base64 # We'll store this for later, as it allows us to save making network requests |
| 23 | # if this track is re-used (e.g. repeat). |
| 24 | |
| 25 | return base64 |
| 26 | |
| 27 | |
| 28 | class CustomSource(Source): |