feat(wechat): add WeChat voice reco API fallback for service account
Memind CI / Test, build, and release guards (push) Successful in 3m27s

When passive Recognition is empty, convert AMR to mp3 and call WeChat
addvoicetorecofortext before the existing asr.tkmind.cn fallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-05 18:01:50 +08:00
parent d9db72fd90
commit 26846a0274
7 changed files with 529 additions and 3 deletions
+31 -2
View File
@@ -12,6 +12,10 @@ import {
persistWechatImage,
uploadWechatGeneratedImage,
} from './wechat-media.mjs';
import {
buildWechatVoiceRecoVoiceId,
transcribeWechatVoiceViaRecoApi,
} from './wechat-voice-reco.mjs';
import { normalizeWechatName, resolveWechatAddressName } from './wechat/user/display-name.mjs';
import { buildAckText } from './wechat/ack/ack-provider.mjs';
import {
@@ -1624,6 +1628,9 @@ export function createWechatMpService({
requireFreshPageThumbnail,
repairFreshPageThumbnail,
asrTarget: config.asrTarget || DEFAULT_ASR_TARGET,
wechatVoiceRecoApiEnabled: config.wechatVoiceRecoApiEnabled !== false,
wechatVoiceRecoLang: config.wechatVoiceRecoLang || 'zh_CN',
wechatVoiceRecoApiBase: config.wechatVoiceRecoApiBase || 'https://api.weixin.qq.com',
};
const deferredStore = createWechatCustomerServiceDeferredStore({ mysqlPool, logger });
@@ -2091,12 +2098,30 @@ export function createWechatMpService({
}
};
const transcribeWechatVoiceMedia = async (mediaId, format) => {
const transcribeWechatVoiceMedia = async (mediaId, format, { msgId } = {}) => {
if (!mediaId) return '';
const accessToken = await getStableAccessToken();
const downloaded = await downloadTemporaryMedia(accessToken, mediaId, { wechatFetch });
if (!downloaded.buffer?.length) return '';
if (config.wechatVoiceRecoApiEnabled) {
try {
const recoText = await transcribeWechatVoiceViaRecoApi({
accessToken,
voiceBuffer: downloaded.buffer,
format,
voiceId: buildWechatVoiceRecoVoiceId({ msgId, mediaId }),
lang: config.wechatVoiceRecoLang,
apiBase: config.wechatVoiceRecoApiBase,
wechatFetch,
convertToMp3: config.wechatVoiceRecoConvertToMp3,
});
if (recoText) return recoText;
} catch (err) {
logger.warn?.('WeChat MP voice reco API failed:', err);
}
}
const extension = String(format ?? '').trim().toLowerCase() || 'amr';
const form = new FormData();
form.append(
@@ -3577,7 +3602,11 @@ export function createWechatMpService({
if (intent.msgType === 'voice' && !intent.agentText.trim() && intent.media?.mediaId) {
try {
const fallbackText = await transcribeWechatVoiceMedia(intent.media.mediaId, intent.media.format);
const fallbackText = await transcribeWechatVoiceMedia(
intent.media.mediaId,
intent.media.format,
{ msgId: intent.msgId },
);
if (fallbackText) {
intent.agentText = fallbackText;
intent.displayText = `语音:${fallbackText}`;