#!/bin/bash # tts_voice_send.sh — generate TTS audio and send as WeChat voice message # # Usage: # ./tts_voice_send.sh [voice] # # Args: # — talker id (use 'filehelper' for safe testing) # — Chinese text to synthesize # [voice] — edge-tts voice name (default: zh-CN-XiaoxiaoNeural) # # Examples: # ./tts_voice_send.sh filehelper "你好,今天天气不错。" # ./tts_voice_send.sh filehelper "下午三点开会" zh-CN-YunxiNeural # # IMPORTANT: test only with 'filehelper' to avoid account risk. # # Dependencies (Mac): # pip3 install edge-tts # brew install ffmpeg # npm install -g silk-wasm (or use openclaw's bundled one) # adb in PATH or set ADB env var set -e WXID="${1:?Usage: $0 [voice]}" TEXT="${2:?Missing text argument}" VOICE="${3:-zh-CN-XiaoxiaoNeural}" ADB="${ADB:-/opt/homebrew/share/android-commandlinetools/platform-tools/adb}" SILK_WASM="${SILK_WASM:-/opt/homebrew/lib/node_modules/openclaw/node_modules/silk-wasm}" TMPDIR="$(mktemp -d /tmp/tts_send_XXXXXX)" trap "rm -rf $TMPDIR" EXIT echo "[1/4] TTS: \"$TEXT\" (voice=$VOICE)" python3 -c " import asyncio, edge_tts async def go(): tts = edge_tts.Communicate('''$TEXT''', '$VOICE') await tts.save('$TMPDIR/out.mp3') asyncio.run(go()) " echo "[2/4] Convert MP3 → PCM 16kHz mono" ffmpeg -y -i "$TMPDIR/out.mp3" -ar 16000 -ac 1 -f s16le "$TMPDIR/out.pcm" -loglevel error echo "[3/4] Encode PCM → SILK V3" DURATION=$(node -e " const silk = require('$SILK_WASM'); const fs = require('fs'); silk.encode(fs.readFileSync('$TMPDIR/out.pcm'), 16000).then(r => { fs.writeFileSync('$TMPDIR/out.amr', r.data); process.stdout.write(String(r.duration)); }); ") echo " → SILK $(wc -c < "$TMPDIR/out.amr" | tr -d ' ') bytes, duration=${DURATION}ms" echo "[4/4] Push + send to WeChat ($WXID)" $ADB push "$TMPDIR/out.amr" /sdcard/hook_voice_tmp.amr -q $ADB shell "su -c 'cp /sdcard/hook_voice_tmp.amr /data/data/com.tencent.mm/cache/hook_voice_src.amr \ && chmod 644 /data/data/com.tencent.mm/cache/hook_voice_src.amr \ && chown u0_a330:u0_a330 /data/data/com.tencent.mm/cache/hook_voice_src.amr \ && rm /sdcard/hook_voice_tmp.amr'" $ADB shell "su -c 'am broadcast -a com.hermes.wechat.SEND_VOICE_INTERNAL \ --es to $WXID \ --es src_path /data/data/com.tencent.mm/cache/hook_voice_src.amr \ --ei duration $DURATION'" echo "Done."