Search code examples
pythondiscord.pyyoutube-dlkeyerror

Youtube-dl KeyError: 'entries'


I tried to get some infos of a video with discord.py when "+dl https://youtube......" is executed, the program download in mp3 the youtube link and send it with : video name, duration and id but i get an error during execution :


    ydl_opts = {
    'outtmpl': './SomethingMore/dl.mp3',
    'format': 'bestaudio/best',
    'noplaylist': True,
    'default_search' : 'ytsearch',
    'postprocessors': [{
    'key': 'FFmpegExtractAudio',
    'preferredcodec': 'mp3',
    'preferredquality': '192',
    }]}

    Link = ctx.message.content
    Link = Link.strip('+dl ')

    with youtube_dl.YoutubeDL(ydl_opts) as ydl:

        playlist_dict = ydl.extract_info(Link, download=False)
        
        for video in playlist_dict['entries']:
                 
            if not video:
                print('ERROR: Unable to get info. Continuing...')
                continue
 
            video_title = video.get("title")
            video_duration = video.get("duration")
            video_id = video.get("id")
            

        await ctx.channel.send('Download of '+ video_title +' is starting, please wait a minute')

        try:
            ydl.download([Link])
            await ctx.channel.send('Download ended')

Here is the error :

Ignoring exception in command dl:
Traceback (most recent call last):
  File "C:\Users\Zarcross\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\discord\ext\commands\core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "h:\Users\Zarcross\Desktop\Discord\main.py", line 267, in dl
    for video in playlist_dict['entries']:
KeyError: 'entries'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Zarcross\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\discord\ext\commands\bot.py", line 903, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\Zarcross\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\discord\ext\commands\core.py", line 859, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:\Users\Zarcross\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\discord\ext\commands\core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: KeyError: 'entries'

Solution

  • Obviously your playlist_dict doesn't have key 'entries'.

    It is hard to say, why. Try checking what you still have in playlist_dict.

    Beside of that, it's a bad practice to mix blocking (youtube-dl) and asynchronous (ctx.channel.send()) code together.

    Consider scheduling blocking calls from a separate thread (asyncio.to_thread())


    UPD: As far as I can see, now YoutubeDL.extract_info() just returns list of dicts, so you can remove ['entries'] part and just iterate over the returned list.

    In [73]: import youtube_dl as ydl
    
    In [74]: with ydl.YoutubeDL() as ydl:
        ...:     ydl.extract_info??
        ...:
    Signature:
    ydl.extract_info(
        url,
        download=True,
        ie_key=None,
        extra_info={},
        process=True,
        force_generic_extractor=False,
    )
    Source:
        def extract_info(self, url, download=True, ie_key=None, extra_info={},
                         process=True, force_generic_extractor=False):
            '''
            Returns a list with a dictionary for each video we find.
            If 'download', also downloads the videos.
            extra_info is a dict containing the extra values to add to each result
            '''
    
            if not ie_key and force_generic_extractor:
                ie_key = 'Generic'
    
            if ie_key:
                ies = [self.get_info_extractor(ie_key)]
            else:
                ies = self._ies
    
            for ie in ies:
                if not ie.suitable(url):
                    continue
    
                ie = self.get_info_extractor(ie.ie_key())
                if not ie.working():
                    self.report_warning('The program functionality for this site has been marked as broken, '
                                        'and will probably not work.')
    
                return self.__extract_info(url, ie, download, extra_info, process)
            else:
                self.report_error('no suitable InfoExtractor for URL %s' % url)
    File:      ~/.local/lib/python3.9/site-packages/youtube_dl/YoutubeDL.py
    Type:      method