tts_voice_send.sh
2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/bin/bash
# tts_voice_send.sh — generate TTS audio and send as WeChat voice message
#
# Usage:
# ./tts_voice_send.sh <wxid> <text> [voice]
#
# Args:
# <wxid> — talker id (use 'filehelper' for safe testing)
# <text> — 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 <wxid> <text> [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."