树莓派上用ytdlp下载YouTube音频遇类型错误的排查与解决
问题:树莓派上Discord机器人用ytdlp提取YouTube音频时报错
a bytes-like object is required, not 'str' 问题背景
将Discord机器人从Replit迁移到树莓派后,原本正常通过ytdlp提取YouTube音频的功能失效,执行下载命令时触发类型错误。
错误触发场景
错误出现在以下命令处理代码的extract_info调用行:
@app_commands.command( name="downloadyoutubeaudio", description="Download youtube audio as an mp3 (Takes a few seconds)") @app_commands.describe(youtubevideo="The youtube url or search terms") async def youtubedownload(self, interaction: discord.Interaction, youtubevideo: str): await interaction.response.defer(ephemeral=False) loop2 = asyncio.get_event_loop() try: # 错误触发行 audiodata = await loop2.run_in_executor( None, lambda: ytdl.extract_info(youtubevideo, download=True)) audiofilename = audiodata['title'] + '.mp3' await interaction.followup.send( file=discord.File('youtubemp3.mp3', filename=audiofilename)) os.remove('youtubemp3.mp3')
具体报错指向:
audiodata = await loop2.run_in_executor( None, lambda: ytdl.extract_info(youtubevideo, download=True))
尝试修复与矛盾错误
尝试对输入参数调用.encode()转换为字节对象,反而触发新错误:
cannot use a string pattern on a bytes-like object
打印确认youtubevideo参数类型为字符串,推测与树莓派字节编码方式有关,但无法定位具体问题。
完整错误栈
Command 'downloadyoutubeaudio' raised an exception: TypeError: a bytes-like object is required, not 'str' Task exception was never retrieved future: <Task finished name='CommandTree-invoker' coro=<CommandTree._from_interaction.<locals>.wrapper() done, defined at /home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/tree.py:1087> exception=CommandInvokeError("Command 'downloadyoutubeaudio' raised an exception: TypeError: a bytes-like object is required, not 'str'")> Traceback (most recent call last): File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/commands.py", line 827, in _do_call return await self._callback(self.binding, interaction, **params) # type: ignore ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/Desktop/code/musiccommands.py", line 319, in youtubedownload raise e File "/home/SamuelDorfman/Desktop/code/musiccommands.py", line 302, in youtubedownload audiodata = await loop2.run_in_executor( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.11/concurrent/futures/thread.py", line 58, in run result = self.fn(*self.args, **self.kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/Desktop/code/musiccommands.py", line 303, in <lambda> None, lambda: ytdl.extract_info(video, download=True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1594, in extract_info return self.__extract_info(url, self.get_info_extractor(key), download, extra_info, process) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1605, in wrapper return func(self, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1761, in __extract_info return self.process_ie_result(ie_result, download, extra_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1840, in process_ie_result return self.extract_info( ^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1594, in extract_info return self.__extract_info(url, self.get_info_extractor(key), download, extra_info, process) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1605, in wrapper return func(self, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1761, in __extract_info return self.process_ie_result(ie_result, download, extra_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1890, in process_ie_result return self.__process_playlist(ie_result, download) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1981, in __process_playlist 'playlist', ie_result, self.prepare_filename(ie_copy, 'pl_infojson')) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1437, in prepare_filename filename = self._prepare_filename(info_dict, tmpl_type=dir_type, outtmpl=outtmpl) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1407, in _prepare_filename outtmpl = self._outtmpl_expandpath(outtmpl) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/yt_dlp/YoutubeDL.py", line 1139, in _outtmpl_expandpath outtmpl = outtmpl.replace('%%', f'%{sep}%').replace('$$', f'${sep}$') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: a bytes-like object is required, not 'str' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/tree.py", line 1091, in wrapper await self._dispatch_error(interaction, e) File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/tree.py", line 1084, in _dispatch_error await self.on_error(interaction, error) File "/home/SamuelDorfman/Desktop/code/main.py", line 551, in on_app_command_error raise error File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/tree.py", line 1089, in wrapper await self._call(interaction) File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/tree.py", line 1252, in _call await self.on_error(interaction, e) File "/home/SamuelDorfman/Desktop/code/main.py", line 551, in on_app_command_error raise error File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/tree.py", line 1248, in _call await command._invoke_with_namespace(interaction, namespace) File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/commands.py", line 853, in _invoke_with_namespace return await self._do_call(interaction, transformed_values) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/SamuelDorfman/.local/lib/python3.11/site-packages/discord/app_commands/commands.py", line 842, in _do_call raise CommandInvokeError(self, e) from e discord.app_commands.errors.CommandInvokeError: Command 'downloadyoutubeaudio' raised an exception: TypeError: a bytes-like object is required, not 'str'
解决方案
问题根源在于ytdlp的outtmpl配置项,将其显式设置为字符串格式即可修复:
ytdl_opts = { 'format': 'bestaudio/best', 'outtmpl': 'youtubemp3.%(ext)s', # 关键配置 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '192', }], } ytdl = yt_dlp.YoutubeDL(ytdl_opts)
设置后,树莓派上的下载功能恢复正常。
内容的提问来源于stack exchange,提问作者person
相关产品推荐
相关产品推荐

