Skip to content

fix: 修复 NapCat 语音消息的 Record 文件路径解析问题#7687

Open
AmeiMiao wants to merge 2 commits intoAstrBotDevs:masterfrom
AmeiMiao:fix-napcat-record-file-resolution
Open

fix: 修复 NapCat 语音消息的 Record 文件路径解析问题#7687
AmeiMiao wants to merge 2 commits intoAstrBotDevs:masterfrom
AmeiMiao:fix-napcat-record-file-resolution

Conversation

@AmeiMiao
Copy link
Copy Markdown

@AmeiMiao AmeiMiao commented Apr 20, 2026

变更说明

修复 Docker + NapCat 场景下语音消息 Record 组件的文件路径解析问题。

当前 Record.convert_to_file_pathRecord.convert_to_base64 主要只使用 self.file,在 NapCat 场景下,这个值可能只是文件名,或者是 AstrBot 容器内不可直接访问的路径,导致语音预处理时报错:

Voice processing failed: not a valid file: xxx.amr

本次修改让 RecordImage 的处理逻辑保持一致,优先使用:

self.url or self.file

问题原因

在 Docker + NapCat 部署下,语音文件虽然已经在协议端成功下载,但 AstrBot 收到的 Record.file 可能只是文件名或不可直接访问的路径。

由于 Record 组件没有像 Image 一样优先使用 url,因此会把本来有效的语音消息误判为无效文件。

修改内容

修改文件:

  • astrbot/core/message/components.py

调整内容:

  • Record.convert_to_file_path 改为优先使用 self.url or self.file
  • Record.convert_to_base64 改为优先使用 self.url or self.file
  • 顺手将语音 base64 落地临时文件扩展名从 .jpg 调整为更合理的 .amr

验证结果

已在本地 Docker + NapCat 环境中验证:

  • 修改前:接收语音消息会报 not a valid file: xxx.amr
  • 修改后:该报错不再出现
  • 语音消息可以继续进入后续 STT 流程

Closes #7686

Summary by Sourcery

Fix voice Record message path resolution to correctly handle NapCat and Docker deployments by aligning its source selection with Image handling.

Bug Fixes:

  • Resolve failures when processing NapCat voice messages by falling back to the component URL when the file path is not directly accessible.

Enhancements:

  • Change temporary voice file extension from .jpg to .amr when decoding base64 voice data for more accurate file typing.

@auto-assign auto-assign Bot requested review from advent259141 and anka-afk April 20, 2026 06:10
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. area:core The bug / feature is about astrbot's core, backend labels Apr 20, 2026
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the convert_to_file_path and convert_to_base64 methods in astrbot/core/message/components.py to support both url and file attributes and corrects the temporary file extension for base64-encoded audio to .amr. Feedback suggests using ValueError for invalid inputs to maintain consistency with other components, refactoring the download logic into a shared helper function to prevent code duplication, and ensuring correct file extensions for audio downloads. Additionally, it was noted that new functionality should be accompanied by unit tests.

Comment thread astrbot/core/message/components.py Outdated
file_path = await download_image_by_url(self.file)
url = self.url or self.file
if not url:
raise Exception(f"not a valid file: {url}")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

为了与 Image 组件保持一致,建议在未提供文件或 URL 时抛出 ValueError。此外,新增的语音处理功能属于新功能,根据项目规则,应附带相应的单元测试。

Suggested change
raise Exception(f"not a valid file: {url}")
raise ValueError("No valid file or URL provided")
References
  1. New functionality, such as handling attachments, should be accompanied by corresponding unit tests.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改,这里现在改为抛出 ValueError("No valid file or URL provided"),与 Image 组件保持一致。

Comment thread astrbot/core/message/components.py Outdated
Comment on lines 155 to 156
file_path = await download_image_by_url(url)
return os.path.abspath(file_path)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

此处使用 download_image_by_url(url) 会导致语音文件被保存为 .jpg 后缀。建议将此处的下载逻辑重构为一个共享的助手函数,以便在处理不同来源的语音附件时复用,避免代码重复并确保后缀名正确。

Suggested change
file_path = await download_image_by_url(url)
return os.path.abspath(file_path)
file_path = os.path.join(get_astrbot_temp_path(), f"recordseg_{uuid.uuid4()}.amr")
await download_file(url, file_path)
return os.path.abspath(file_path)
References
  1. When implementing similar functionality for different cases (e.g., direct vs. quoted attachments), refactor the logic into a shared helper function to avoid code duplication.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改。现在 Record 在处理 HTTP URL 时不再复用 download_image_by_url,而是使用 download_file 并显式保存为 .amr 临时文件,避免语音下载后缀和处理方式不准确。

Comment thread astrbot/core/message/components.py Outdated
file_path = await download_image_by_url(self.file)
url = self.url or self.file
if not url:
raise Exception(f"not a valid file: {url}")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

建议在此处也使用 ValueError 以保持与 Image 组件的一致性。

Suggested change
raise Exception(f"not a valid file: {url}")
raise ValueError("No valid file or URL provided")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修改,这里现在改为抛出 ValueError("No valid file or URL provided"),与 Image 组件保持一致。

Comment thread astrbot/core/message/components.py Outdated
Comment on lines 183 to 184
file_path = await download_image_by_url(url)
bs64_data = file_to_base64(file_path)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

此处逻辑与上方重复。建议按照规则将下载和保存语音的逻辑重构为共享的助手函数,以提高代码的可维护性并确保后缀名正确。

Suggested change
file_path = await download_image_by_url(url)
bs64_data = file_to_base64(file_path)
file_path = os.path.join(get_astrbot_temp_path(), f"recordseg_{uuid.uuid4()}.amr")
await download_file(url, file_path)
bs64_data = file_to_base64(file_path)
References
  1. When implementing similar functionality for different cases (e.g., direct vs. quoted attachments), refactor the logic into a shared helper function to avoid code duplication.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这次我先尽量保持修复范围最小,优先解决 NapCat + Docker 场景下语音消息 Record 无法继续进入后续 STT 的问题,因此暂时没有继续做额外重构。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Docker + NapCat 接收语音消息时报错:Voice processing failed: not a valid file: xxx.amr

1 participant