| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- """使用本机 SAPI 语音合成生成 assets/voices/*.wav"""
- import os
- import sys
- OUTPUT_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "assets", "voices")
- VOICES = {
- "hooking.wav": "挂包中",
- "ready.wav": "挂包成功",
- "releasing.wav": "放包中",
- "arrive_1.wav": "到达1号工位",
- "arrive_2.wav": "到达2号工位",
- "arrive_3.wav": "到达3号工位",
- "arrive_4.wav": "到达4号工位",
- "arrive_5.wav": "到达5号工位",
- "offline_reader.wav": "读卡器离线",
- "offline_cam_left.wav": "左侧摄像头离线",
- "offline_cam_right.wav": "右侧摄像头离线",
- }
- def main():
- import struct
- os.makedirs(OUTPUT_DIR, exist_ok=True)
- import win32com.client
- speaker = win32com.client.Dispatch("SAPI.SpVoice")
- SSFMCreateForWrite = 3
- SAFT16kHz16BitMono = 4
- for filename, text in VOICES.items():
- path = os.path.join(OUTPUT_DIR, filename)
- stream = win32com.client.Dispatch("SAPI.SpFileStream")
- af = win32com.client.Dispatch("SAPI.SpAudioFormat")
- af.Type = SAFT16kHz16BitMono
- stream.Format = af
- stream.Open(path, SSFMCreateForWrite)
- speaker.AudioOutputStream = stream
- speaker.Speak(text)
- stream.Close()
- with open(path, 'rb+') as f:
- data = bytearray(f.read())
- fmt_chunk = b'fmt '
- fmt_pos = data.find(fmt_chunk)
- if fmt_pos == -1:
- print(f" 跳过音量放大(无 fmt chunk)")
- else:
- channels = struct.unpack_from('<H', data, fmt_pos + 10)[0]
- sample_rate = struct.unpack_from('<I', data, fmt_pos + 12)[0]
- bits_per_sample = struct.unpack_from('<H', data, fmt_pos + 22)[0]
- data_chunk = b'data'
- data_pos = data.find(data_chunk)
- if data_pos != -1:
- data_size = struct.unpack_from('<I', data, data_pos + 4)[0]
- sample_start = data_pos + 8
- sample_end = sample_start + data_size
- if bits_per_sample == 16:
- fmt = '<' + 'h' * (data_size // 2)
- samples = list(struct.unpack_from(fmt, bytes(data[sample_start:sample_end])))
- gain = 3.0
- samples = [max(-32768, min(32767, int(s * gain))) for s in samples]
- data[sample_start:sample_end] = struct.pack(fmt, *samples)
- elif bits_per_sample == 8:
- samples = list(data[sample_start:sample_end])
- gain = 3.0
- samples = [max(0, min(255, int((s - 128) * gain) + 128)) for s in samples]
- data[sample_start:sample_end] = bytes(samples)
- with open(path, 'wb') as f:
- f.write(data)
- print(f"生成: {path} (增益 {gain}x, {sample_rate}Hz, {bits_per_sample}bit, {channels}ch)")
- else:
- print(f"生成: {path} (无 data chunk)")
- if __name__ == "__main__":
- main()
|