-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix(qqofficial): convert non-WAV audio to PCM WAV before Tencent Silk encoding #6867
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,10 @@ | |
| from astrbot.api.platform import AstrBotMessage, PlatformMetadata | ||
| from astrbot.core.utils.astrbot_path import get_astrbot_temp_path | ||
| from astrbot.core.utils.io import download_image_by_url, file_to_base64 | ||
| from astrbot.core.utils.tencent_record_helper import wav_to_tencent_silk | ||
| from astrbot.core.utils.tencent_record_helper import ( | ||
| convert_to_pcm_wav, | ||
| wav_to_tencent_silk, | ||
| ) | ||
|
|
||
|
|
||
| def _patch_qq_botpy_formdata() -> None: | ||
|
|
@@ -602,22 +605,41 @@ async def _parse_to_qqofficial(message: MessageChain): | |
| image_base64 = image_base64.removeprefix("base64://") | ||
| elif isinstance(i, Record): | ||
| if i.file: | ||
| record_wav_path = await i.convert_to_file_path() # wav 路径 | ||
| record_wav_path = await i.convert_to_file_path() # 可能不是wav | ||
| temp_dir = get_astrbot_temp_path() | ||
| record_tecent_silk_path = os.path.join( | ||
| temp_dir, | ||
| f"qqofficial_{uuid.uuid4()}.silk", | ||
| ) | ||
| try: | ||
| duration = await wav_to_tencent_silk( | ||
| record_wav_path, | ||
| record_tecent_silk_path, | ||
| # 检查是否为 WAV 文件,非 WAV 需要先转换 | ||
| ext = os.path.splitext(record_wav_path)[1].lower() | ||
| if ext != ".wav": | ||
| temp_wav_path = os.path.join( | ||
| temp_dir, | ||
| f"qqofficial_{uuid.uuid4()}.wav", | ||
|
Comment on lines
+617
to
+619
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (performance): Consider cleaning up the intermediate WAV file after conversion to avoid temp-file buildup. Since Suggested implementation: temp_dir,
f"qqofficial_{uuid.uuid4()}.silk",
)
# 检查是否为 WAV 文件,非 WAV 需要先转换
temp_wav_path: str | None = None
ext = os.path.splitext(record_wav_path)[1].lower()
if ext != ".wav":
temp_wav_path = os.path.join(
temp_dir,
f"qqofficial_{uuid.uuid4()}.wav",
)
try:
record_wav_path = await convert_to_pcm_wav(
record_wav_path,
temp_wav_path,
)
except Exception as e:
logger.error(f"转换音频为WAV格式时出错: {e}")
# 转换失败时清理中间 WAV 文件,避免临时文件堆积
if temp_wav_path and os.path.exists(temp_wav_path):
try:
os.remove(temp_wav_path)
except Exception as cleanup_err:
logger.warning(
f"清理临时 WAV 文件失败 {temp_wav_path}: {cleanup_err}"
)
record_file_path = None
record_wav_path = NoneTo fully implement your suggestion ("once
This will guarantee the temporary WAV file is removed both on success and failure of the Silk conversion step. |
||
| ) | ||
|
Comment on lines
611
to
620
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (performance): Silk temp file might remain on disk when conversion fails, which could accumulate over time. If Suggested implementation: try:
await wav_to_tencent_silk(record_wav_path, record_tecent_silk_path)
except Exception as e:
# Cleanup partially written silk file to avoid temp file buildup
if os.path.exists(record_tecent_silk_path):
try:
os.remove(record_tecent_silk_path)
except OSError:
# Best-effort cleanup; log and continue raising original error
logger.warning(
"Failed to remove temporary silk file %s after conversion error",
record_tecent_silk_path,
)
logger.exception("Failed to convert wav to tencent silk: %s", e)
raise
|
||
| if duration > 0: | ||
| record_file_path = record_tecent_silk_path | ||
| try: | ||
| record_wav_path = await convert_to_pcm_wav( | ||
| record_wav_path, | ||
| temp_wav_path, | ||
| ) | ||
| except Exception as e: | ||
| logger.error(f"转换音频为WAV格式时出错: {e}") | ||
| record_file_path = None | ||
| record_wav_path = None | ||
| try: | ||
| if record_wav_path: | ||
| duration = await wav_to_tencent_silk( | ||
| record_wav_path, | ||
| record_tecent_silk_path, | ||
| ) | ||
| if duration > 0: | ||
| record_file_path = record_tecent_silk_path | ||
| else: | ||
| record_file_path = None | ||
| logger.error("转换音频格式时出错:音频时长不大于0") | ||
| else: | ||
| record_file_path = None | ||
| logger.error("转换音频格式时出错:音频时长不大于0") | ||
| except Exception as e: | ||
| logger.error(f"处理语音时出错: {e}") | ||
| record_file_path = None | ||
|
Comment on lines
+614
to
645
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The temporary WAV file created during audio conversion is not being cleaned up, which can lead to an accumulation of files in the temporary directory. This is a resource leak. I suggest refactoring this block to use a converted_wav_path = None
try:
# 检查是否为 WAV 文件,非 WAV 需要先转换
ext = os.path.splitext(record_wav_path)[1].lower()
if ext != ".wav":
temp_wav_path = os.path.join(
temp_dir,
f"qqofficial_{uuid.uuid4()}.wav",
)
converted_wav_path = temp_wav_path
try:
record_wav_path = await convert_to_pcm_wav(
record_wav_path,
temp_wav_path,
)
except Exception as e:
logger.error(f"转换音频为WAV格式时出错: {e}")
record_wav_path = None
if record_wav_path:
duration = await wav_to_tencent_silk(
record_wav_path,
record_tecent_silk_path,
)
if duration > 0:
record_file_path = record_tecent_silk_path
else:
record_file_path = None
logger.error("转换音频格式时出错:音频时长不大于0")
else:
record_file_path = None
except Exception as e:
logger.error(f"处理语音时出错: {e}")
record_file_path = None
finally:
if converted_wav_path and os.path.exists(converted_wav_path):
os.remove(converted_wav_path) |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider extracting the audio conversion and WAV-normalization logic into focused helper functions so this block becomes a simple, linear call that just assigns the final
record_file_path.You can reduce the branching and state juggling here by pushing the conversion logic into a small helper and using linear flow instead of mutating
record_wav_path/record_file_pathin multiple branches.For example, extract the audio handling into a dedicated helper:
with a focused WAV normalizer:
Then the calling site becomes much simpler and only handles the final state:
This keeps all existing behavior (non-WAV support, duration check, logging) but:
record_wav_path/record_file_pathas control-flow flags.if/tryblocks into a linear flow.record_file_path = None.