GLM-ASR-Nano-2512代码实例:curl调用/gradio_api接口批量转写脚本

1. 为什么你需要这个脚本:从单次点击到批量处理的跨越

你可能已经试过在浏览器里打开 http://localhost:7860,把一段录音拖进去,点一下“转写”,几秒钟后就看到文字结果跳出来——很酷,但也很慢。

当你手头有37个会议录音、12段客户访谈、8条产品反馈语音,还有一堆没命名的 .wav 文件散落在文件夹里时,一个一个上传就成了最耗时间的环节。这时候,图形界面不再是助力,反而成了瓶颈。

GLM-ASR-Nano-2512 的真正价值,从来不只是那个漂亮的 Gradio 界面。它背后藏着一个稳定、轻量、可编程的 API 接口:/gradio_api/。这个接口不挑人,不卡顿,不依赖鼠标,只认标准 HTTP 请求和规范音频格式。而本文要带你写的,就是一个能自动扫文件夹、并发提交、统一整理结果的 Python 脚本——它不炫技,但每天能帮你省下两小时;它不复杂,但跑起来就像开了挂。

你不需要懂模型结构,不用调参,甚至不用改一行模型代码。你只需要知道:这段脚本能把你从“手动点点点”的循环里彻底解放出来。

2. 先搞清楚:API 是什么?它和网页界面有什么不一样?

很多人第一次看到 /gradio_api/ 这个路径会犹豫:“这是不是要写前端?”“是不是得配 token?”“会不会比网页还难用?”

其实完全相反。Gradio 的 gradio_api 是一套为开发者准备的“直连通道”——它绕过了所有 UI 渲染、状态管理、按钮逻辑,直接把你的音频文件送到模型推理层,再把识别结果原样返回。你可以把它理解成:把网页上那个“上传+提交”动作,拆解成两步:1)发个请求,2)收个回复。

举个最简单的例子:

  • 在网页里,你选中 meeting_01.mp3 → 点“转写” → 等进度条 → 看结果
  • 用 API,你执行一条命令:
    curl -X POST "http://localhost:7860/gradio_api/" \
      -F "data=[\"/path/to/meeting_01.mp3\", null, null, null]" \
      -F "fn_index=0"
    
    几秒后,终端就打印出 JSON 格式的识别文本。

关键区别就三点:

  • 无状态:每次请求都是独立的,不依赖登录、不保存历史
  • 可编程:你能用 Python、Shell、Node.js 甚至 Excel VBA 调它
  • 可批量:一次发1个,也能一次发100个(稍作改造)

fn_index=0 这个参数,就是告诉服务:“请调用第一个函数”,也就是模型的主转写函数。Gradio 把每个功能模块都编了号,0 是默认转写,1 可能是实时录音分析(如果镜像支持),我们只关心 0

3. 实战脚本:一个真正能跑起来的批量转写工具

下面这个脚本,你复制粘贴就能用。它做了三件关键事:扫描指定目录下的所有支持格式音频、按顺序或并发提交给 GLM-ASR-Nano-2512、把结果按原文件名保存为 .txt。没有多余依赖,只要 Python 3.8+ 和 requests 库。

3.1 安装依赖与准备环境

pip3 install requests tqdm

注意:如果你用的是 Docker 启动的服务(推荐方式),确保宿主机能访问容器的 7860 端口。默认 docker run 已映射 -p 7860:7860,所以 http://localhost:7860 在宿主机上完全可用。

3.2 批量转写脚本(Python 版)

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
GLM-ASR-Nano-2512 批量转写脚本
支持格式:WAV / MP3 / FLAC / OGG
输出:同名 .txt 文件,含识别文本 + 时间戳(可选)
"""
import os
import sys
import time
import json
import requests
from pathlib import Path
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor, as_completed

# ===== 配置区(只需改这里)=====
API_URL = "http://localhost:7860/gradio_api/"
INPUT_DIR = "./audio_samples"  # 替换为你自己的音频文件夹路径
OUTPUT_DIR = "./transcripts"   # 输出文本存放目录
MAX_WORKERS = 3                # 并发请求数(GPU 内存足可调高,如 RTX 4090 可设 5-6)
TIMEOUT = 300                  # 单次请求超时(秒),长音频建议留足
# ==============================

def get_supported_files(folder):
    """扫描支持的音频格式文件"""
    exts = {'.wav', '.mp3', '.flac', '.ogg'}
    files = []
    for p in Path(folder).rglob('*'):
        if p.is_file() and p.suffix.lower() in exts:
            files.append(p)
    return sorted(files)

def transcribe_one_file(filepath):
    """向 GLM-ASR-Nano-2512 提交单个文件并返回结果"""
    try:
        with open(filepath, "rb") as f:
            files = {"files": (filepath.name, f, "audio/x-wav" if filepath.suffix.lower() == ".wav" else "audio/mpeg")}
            data = {
                "data": json.dumps([
                    None,  # audio input(我们传文件,所以这里为 None)
                    None,  # language(自动检测,留空)
                    None,  # initial prompt(可选,留空)
                    None   # temperature(可选,留空)
                ]),
                "fn_index": 0,
                "session_hash": "batch_run"  # 固定 session,避免干扰
            }
            response = requests.post(
                API_URL,
                files=files,
                data=data,
                timeout=TIMEOUT
            )
            response.raise_for_status()
            result = response.json()
            # Gradio API 返回结构:{"data": ["识别文本"], ...}
            text = result.get("data", [""])[0] if result.get("data") else ""
            return str(filepath), text.strip()
    except Exception as e:
        return str(filepath), f"[ERROR] {str(e)}"

def main():
    input_path = Path(INPUT_DIR)
    output_path = Path(OUTPUT_DIR)
    output_path.mkdir(exist_ok=True)

    audio_files = get_supported_files(input_path)
    if not audio_files:
        print(f"  在 {input_path} 中未找到支持的音频文件(.wav/.mp3/.flac/.ogg)")
        return

    print(f" 发现 {len(audio_files)} 个待转写文件")
    print(f" 正在连接 {API_URL} ...")

    # 测试连通性
    try:
        test_resp = requests.get(f"{API_URL.replace('/gradio_api/', '')}", timeout=5)
        if test_resp.status_code != 200:
            raise ConnectionError("Web UI 未响应,请确认服务已启动")
    except Exception as e:
        print(f" 连接失败:{e}")
        print(" 检查项:1) docker ps 是否看到 glm-asr-nano 容器 2) 是否用了 --gpus all 3) 端口是否被占用")
        return

    results = []
    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        # 提交所有任务
        future_to_file = {
            executor.submit(transcribe_one_file, f): f for f in audio_files
        }
        # 收集结果(带进度条)
        for future in tqdm(as_completed(future_to_file), total=len(audio_files), desc="🔊 转写中"):
            filepath, text = future.result()
            results.append((filepath, text))
            # 立即写入文件,避免内存堆积
            stem = Path(filepath).stem
            out_file = output_path / f"{stem}.txt"
            with open(out_file, "w", encoding="utf-8") as fw:
                fw.write(text)
                if text and not text.endswith("\n"):
                    fw.write("\n")

    # 统计汇总
    success_count = sum(1 for _, t in results if not t.startswith("[ERROR]"))
    error_count = len(results) - success_count
    print(f"\n 完成!成功 {success_count} 个,失败 {error_count} 个")
    if error_count > 0:
        print(" 失败列表:")
        for f, t in results:
            if t.startswith("[ERROR]"):
                print(f"   {Path(f).name} → {t}")

if __name__ == "__main__":
    main()

3.3 脚本怎么用?三步走

  1. 准备音频:把 .wav.mp3 等文件放进 ./audio_samples(或你改过的 INPUT_DIR
  2. 确认服务运行:终端执行 docker ps,看到类似这行就对了:
    ... glm-asr-nano:latest ... 0.0.0.0:7860->7860/tcp
  3. 运行脚本
    python3 batch_transcribe.py
    

你会看到一个实时进度条,每完成一个文件,就在 ./transcripts/ 下生成一个同名 .txt。比如 interview_01.mp3interview_01.txt,内容就是识别出的文字。

小技巧:如果想看某次失败的具体原因,打开对应 .txt 文件,里面会写明错误类型(如“文件过大”、“格式不支持”、“超时”等),比终端滚动日志更清晰。

4. 进阶用法:定制化需求轻松加

上面的脚本是“开箱即用”版,但实际工作中,你很可能需要微调。以下三个高频需求,只需改几行代码就能实现:

4.1 指定语言,提升中文识别准确率

GLM-ASR-Nano-2512 支持自动检测中英文,但如果你的音频全是普通话,强制指定语言能减少误判。修改 transcribe_one_file 函数中 data 字典部分:

"data": json.dumps([
    None,
    "Chinese",  # ← 加这一行,固定为中文(也支持 "English", "Cantonese")
    None,
    None
]),

4.2 添加时间戳,生成带时间轴的字幕

当前脚本只返回纯文本。若需 SRT 或 VTT 字幕,需启用模型的时间戳输出(需镜像支持)。检查你的 app.py 是否启用了 return_timestamps=True。若已支持,只需改 data 中的第3个参数:

"data": json.dumps([
    None,
    "Chinese",
    True,  # ← 启用时间戳(注意:必须是布尔值 True,不是字符串 "true")
    None
]),

返回结果将变成类似 [{"text": "你好", "start": 0.23, "end": 1.45}, ...] 的结构,你可以在 main() 中解析并生成标准 SRT。

4.3 限制单次并发数,保护 GPU 显存

脚本默认 MAX_WORKERS = 3,适合大多数消费级显卡。如果你发现转写中途报错 CUDA out of memory,不要慌——这不是代码问题,是显存不够。直接把 MAX_WORKERS 改成 12,虽然慢一点,但稳如磐石。RTX 3090 用户可尝试 4,4090 用户放心 6

5. 常见问题与避坑指南

即使脚本再简单,第一次跑也可能遇到几个“意料之中”的小状况。以下是真实用户踩过的坑,附带一针见血的解法:

5.1 “Connection refused” 错误

  • 现象:脚本报错 ConnectionError: HTTPConnectionPool(host='localhost', port=7860): Max retries exceeded with url: /gradio_api/
  • 原因:服务根本没起来,或端口没映射对
  • 解法
    • 执行 docker ps,确认容器状态是 Up
    • 执行 curl http://localhost:7860,看能否返回 HTML(哪怕乱码也说明 Web 通了)
    • 如果 curl 通但 /gradio_api/ 不通,检查 app.py 中是否启用了 enable_queue=True(Gradio 6.x+ 默认开启,不影响 API)

5.2 上传后返回空字符串或乱码

  • 现象.txt 文件里是空的,或一堆 \u5f00\u59cb 这样的 Unicode
  • 原因:音频格式不被 PyTorch Audio 解码器支持,或采样率异常(如 96kHz)
  • 解法
    • ffprobe your_file.mp3 查看音频信息,重点关注 bit_rate, sample_rate, codec_name
    • 统一转为标准格式(推荐):
      ffmpeg -i input.mp3 -ar 16000 -ac 1 -c:a libmp3lame -q:a 2 output_16k.mp3
      
      (16kHz 单声道 MP3 是 GLM-ASR-Nano-2512 最兼容的输入)

5.3 转写结果明显漏字、断句奇怪

  • 现象:一句话被切成三段,或专有名词全错(如“张江”识别成“章江”)
  • 原因:模型对低信噪比、远场录音、重口音适应有限
  • 解法
    • 前置降噪:用 noisereduce 库预处理(加在脚本读文件后)
    • 加初始提示:在 data 第3项填入领域关键词,例如会议场景填 "会议纪要,发言人:张总,李经理,技术讨论"
    • 人工校对模板:脚本可额外生成 .review.md,把识别文本+原始音频路径+时间戳打包,方便后续用 Obsidian 或 Notion 批量审阅

6. 总结:让语音转写真正成为你的日常工具

GLM-ASR-Nano-2512 不是一个“玩具模型”。它用 1.5B 参数,在中文语音识别上跑赢 Whisper V3,同时体积更小、部署更轻、API 更干净——这些优势,只有当你把它从浏览器里“拽出来”,放进自动化流水线,才能真正释放。

本文给你的不是一个“一次性 demo”,而是一套可长期复用的工作流:

  • 用标准 curl/requests 调用,不绑定任何框架
  • 支持主流音频格式,失败有明确提示
  • 并发可控,适配不同硬件
  • 输出结构化,方便下一步 NLP 处理(如关键词提取、摘要生成)

你不需要成为语音专家,也能让这套系统每天安静地为你处理几十段语音。真正的技术价值,不在于参数多大、指标多高,而在于——它是否让你少点一次鼠标,少等一分钟,少写一行重复代码。

现在,就把那段积压的客户录音拖进 ./audio_samples,然后敲下 python3 batch_transcribe.py 吧。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐