【实战教程】基于Python实现英雄联盟语音输入方案(附完整开源代码)

在英雄联盟对局中,快速和队友沟通是取胜的关键!但手动打字不仅慢,还容易错过操作时机;原生语音聊天又可能遇到队友静音、环境嘈杂等问题。今天就给大家分享一个轻量级英雄联盟语音输入方案——按住按键录音,松开自动转文字,直接复制到游戏聊天框,解放双手,沟通效率拉满!

一、方案核心优势

  1. 极简操作:按住指定按键录音,松开自动识别成文字,无需复杂操作;

  2. 轻量化:基于Python实现,无冗余依赖,运行内存占用极低;

  3. 可定制:支持自定义录音按键、退出按键,适配不同玩家操作习惯;

  4. 跨平台:兼容Windows/macOS(核心逻辑通用,仅音频驱动细节需微调);

  5. 开源可扩展:可根据自己需求对接不同语音识别API,适配更多场景。

二、环境准备

1. 基础环境

  • Python 3.7+(推荐3.8~3.10版本,兼容性最佳)

  • 操作系统:Windows(实测Win10/11)/macOS/Linux

2. 依赖安装

核心依赖包括音频录制(pyaudio)、网络请求(requests)、按键监听(keyboard)等,执行以下命令安装:


# 基础依赖
pip install requests keyboard json uuid wave tempfile threading

# 重点:安装pyaudio(音频录制核心库)
# Windows推荐方式(避免编译失败)
pip install pipwin
pipwin install pyaudio

# macOS/Linux
# macOS: brew install portaudio && pip install pyaudio
# Linux: sudo apt-get install portaudio19-dev && pip install pyaudio

三、核心实现原理

整个方案的核心逻辑分为4步,流程清晰易懂:

按键监听 → 音频录制 → 语音识别API调用 → 输出文字结果

  1. 按键监听:通过keyboard库监听指定按键(默认V键),按住时启动录音,松开时停止;

  2. 音频录制:通过pyaudio录制16000Hz采样率、单声道的PCM音频,保存为临时WAV文件;

  3. 语音识别:将WAV文件转Base64编码,调用通用语音识别API(支持自定义对接讯飞、百度、阿里等平台);

  4. 结果输出:识别完成后打印文字结果,直接复制到英雄联盟聊天框即可发送。

四、核心代码解析

下面拆解关键模块,帮大家理解核心逻辑(完整代码见文末开源地址)。

1. 配置文件加载(load_config)

通过config.json管理API密钥、按键配置等敏感/可配置信息,避免硬编码:


def load_config():
    config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.json")
    if not os.path.exists(config_path):
        print(f"[ERROR] config.json not found at {config_path}")
        print("Please copy config.json and fill in your API credentials.")
        sys.exit(1)
    with open(config_path, encoding="utf-8") as f:
        return json.load(f)

config.json示例(需替换为自己的API信息):


{
    "api_key": "YOUR_API_KEY_HERE",
    "resource_id": "YOUR_RESOURCE_ID_HERE",
    "recognize_url": "https://api.example.com/speech/recognize",
    "record_key": "v",
    "exit_key": "esc"
}

2. 音频录制与保存(save_wav)

录制的音频数据暂存到内存,停止录音后保存为临时WAV文件(避免磁盘冗余):


def save_wav(audio, frames_data):
    tmp = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
    wf = wave.open(tmp.name, "wb")
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(audio.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b"".join(frames_data))
    wf.close()
    return tmp.name

3. 语音识别核心逻辑(recognize)

将WAV文件转Base64后调用API,解析返回结果并输出:


def recognize(cfg, wav_path):
    with open(wav_path, "rb") as f:
        base64_data = base64.b64encode(f.read()).decode("utf-8")

    headers = {
        "X-Api-Key": cfg.get("api_key", ""),
        "X-Api-Resource-Id": cfg.get("resource_id", ""),
        "X-Api-Request-Id": str(uuid.uuid4()),
        "X-Api-Sequence": "-1",
    }

    body = {
        "user": {"uid": "demo_user"},
        "audio": {"data": base64_data},
        "request": {
            "model_name": "bigmodel",
            "enable_itn": True,  # 开启数字转换(比如"123"转"一百二十三")
            "enable_punc": True, # 开启标点符号
        },
    }

    try:
        resp = requests.post(
            cfg.get("recognize_url", ""), json=body, headers=headers, timeout=120
        )
        # 解析API返回码和结果
        code = resp.headers.get("X-Api-Status-Code", "")
        if code == "20000000":
            result = resp.json()
            utterances = result.get("result", {}).get("utterances", [])
            text = "".join(u["text"] for u in utterances)
            if text:
                print(f"\n[RESULT] {text}")  # 识别结果打印,直接复制即可
            else:
                print("\n[INFO] No speech detected.")
        else:
            msg = resp.headers.get("X-Api-Message", "Unknown error")
            print(f"\n[ERROR] API error ({code}): {msg}")
    except requests.RequestException as e:
        print(f"\n[ERROR] Request failed: {e}")

4. 按键监听与主线程(main)

通过多线程实现“录音不阻塞主线程”,监听按键事件控制录音启停:


def main():
    cfg = load_config()
    # 校验API密钥
    if not cfg.get("api_key") or cfg["api_key"] == "YOUR_API_KEY_HERE":
        print("[ERROR] Please fill in api_key in config.json")
        sys.exit(1)

    record_key = cfg.get("record_key", "v")
    exit_key = cfg.get("exit_key", "esc")

    audio = pyaudio.PyPyAudio() if hasattr(pyaudio, "PyPyAudio") else pyaudio.PyAudio()
    frames = []
    recording = False
    stream = None
    exit_flag = threading.Event()

    # 录音循环(子线程执行)
    def record_loop():
        nonlocal frames, stream, recording
        while recording:
            try:
                data = stream.read(CHUNK, exception_on_overflow=False)
                frames.append(data)
            except Exception:
                break

    # 按键事件回调
    def on_key(event):
        nonlocal frames, stream, recording
        # 录音按键逻辑(按住V录音,松开停止)
        if event.name == record_key:
            if event.event_type == keyboard.KEY_DOWN and not recording:
                recording = True
                frames = []
                stream = audio.open(
                    format=FORMAT, channels=CHANNELS, rate=RATE,
                    input=True, frames_per_buffer=CHUNK,
                )
                threading.Thread(target=record_loop, daemon=True).start()
                print(f"\r[REC] Recording... (release '{record_key}' to stop)", end="", flush=True)
            elif event.event_type == keyboard.KEY_UP and recording:
                recording = False
                time.sleep(0.1)
                if stream:
                    stream.stop_stream()
                    stream.close()
                if frames:
                    print(f"\r[INFO] Recognizing...                    ", end="", flush=True)
                    wav_path = save_wav(audio, frames)
                    # 异步识别,避免阻塞
                    threading.Thread(target=recognize, args=(cfg, wav_path), daemon=True).start()
            return False

        # 退出按键(ESC)
        if event.name == exit_key and event.event_type == keyboard.KEY_DOWN:
            exit_flag.set()
            return False
        return True

    # 注册按键钩子
    keyboard.hook(on_key)
    print("=" * 40)
    print("  SpellVoice - 英雄联盟语音输入方案")
    print("=" * 40)
    print(f"  录音按键 : 按住 '{record_key}' 开始录音")
    print(f"  退出按键   : {exit_key}")
    print("=" * 40)
    print("监听按键事件中...")

    try:
        exit_flag.wait()
    except KeyboardInterrupt:
        pass

    keyboard.unhook_all()
    audio.terminate()
    print("\nBye!")

五、使用教程(英雄联盟适配版)

1. 下载源码

在线体验 https://voice.magetech.com.cn/
魔法语音输入助手,SpellVoice

2. 配置API信息

  1. 复制项目中的config.json.example为config.json;

  2. 填写api_key、resource_id、recognize_url(需对接自己的语音识别API,比如讯飞开放平台、百度智能云等);

  3. 可选:修改record_key(录音按键)、exit_key(退出按键)。

3. 运行程序


python demo.py

4. 游戏内使用

  1. 运行程序后,切回英雄联盟游戏界面;

  2. 按住配置的录音按键(默认V)开始说话(比如“中路来人了”“大龙团战”);

  3. 松开按键,程序自动识别并打印文字结果;

  4. 复制识别结果,按Enter打开游戏聊天框,粘贴后发送即可。

六、注意事项

  1. 音频权限:Windows需允许程序访问麦克风,macOS需在“系统设置-隐私与安全性-麦克风”中授权;

  2. API对接:不同语音识别平台的接口参数不同,需根据平台文档调整recognize函数中的headers和body;

  3. 游戏兼容性:英雄联盟聊天框支持粘贴,识别结果可直接复制,无需额外适配;

  4. 按键冲突:若录音按键(默认V)和游戏技能键冲突,可在config.json中修改为其他按键(比如z/x);

  5. 低延迟优化:可减小CHUNK值(默认1024)降低录音延迟,但可能增加CPU占用。

七、总结

这个方案以极简的逻辑实现了英雄联盟语音输入的核心需求,既解决了手动打字慢的问题,又避免了语音聊天的噪音干扰。代码完全开源,大家可以根据自己的需求扩展功能(比如自动发送到游戏聊天框、自定义话术模板、多语言识别等)。

如果觉得这个教程有用,欢迎给项目点个Star!有任何问题,也可以在仓库Issues中交流~

开源地址

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐