SoundWise 的批量转录通常要解决两件事:一是确认 SoundWise 自带命令行接口还是只暴露 HTTP API,二是确定输入音频的目录结构和命名规则。如果 SoundWise 提供可执行命令,直接写循环调用即可;如果只有 API,就需要用 curl 或 Python 请求包装。下面给出两种通用脚本骨架,先在本机小范围试跑,再推广到全量目录。
批量转录脚本的核心是“文件清单 + 逐条调用 + 失败重试 + 输出落盘”。先确认 SoundWise 的调用方式(命令行或 API 端点),再把音频路径逐一传给转录命令,结果写入对应文本文件。脚本要保留日志和重试机制,因为长音频或高并发下服务端可能超时。适用场景是本地已有成批音频文件、需要一次性生成文字记录;操作前先准备一个包含 3~5 个文件的测试集,跑通后再放开。
准备输入文件和输出目录
建议先把音频集中到一个目录,统一格式,例如只保留 .wav、.mp3、.m4a。如果原始文件分散在多个子目录,可以先用 find 生成清单,避免脚本进入深层目录时路径拼接出错。输出目录建议单独建,比如 transcripts,每个文件命名与源文件一致,但扩展名改为 .txt。
mkdir -p audio_files transcripts
# 把要处理的音频放到 audio_files 下
方式一:SoundWise 提供命令行工具
如果 SoundWise 的 CLI 可以单文件调用,比如 soundwise transcribe input.mp3 -o output.txt,那么用 bash 循环即可。要注意命令名和参数需要根据实际安装的版本调整,下例中的 soundwise 只是一个占位。
#!/bin/bash
INPUT_DIR="audio_files"
OUTPUT_DIR="transcripts"
LOG="transcribe.log"
for f in "$INPUT_DIR"/*.{wav,mp3,m4a}; do
[ -e "$f" ] || continue
base=$(basename "$f")
name="${base%.*}"
out="$OUTPUT_DIR/$name.txt"
# 已存在的输出文件可跳过,便于断点续跑
if [ -f "$out" ]; then
echo "skip $f -> $out" | tee -a "$LOG"
continue
fi
echo "transcribing $f" | tee -a "$LOG"
soundwise transcribe "$f" -o "$out" 2>>"$LOG"
if [ $? -ne 0 ]; then
echo "FAILED $f" | tee -a "$LOG"
else
echo "OK $f" | tee -a "$LOG"
fi
done
脚本会跳过已生成的文本文件,避免重复处理。如果某个文件失败,日志里有 FAILED 记录,可以单独重跑。
方式二:SoundWise 只提供 HTTP API
如果 SoundWise 只有 API,通常需要先上传音频再获取转录结果。这种场景下用 Python 脚本处理更灵活,因为要处理 HTTP 状态码和轮询。下面是一个通用骨架,你需要替换成实际服务的端点、密钥和请求字段。
import os
import time
import requests
import glob
INPUT_DIR = "audio_files"
OUTPUT_DIR = "transcripts"
API_URL = "https://api.example.com/transcribe" # 替换成 SoundWise 实际地址
API_KEY = "your-key" # 替换成你的密钥
os.makedirs(OUTPUT_DIR, exist_ok=True)
def transcribe(audio_path):
with open(audio_path, "rb") as f:
resp = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
files={"audio": f},
timeout=300,
)
if resp.status_code != 200:
raise RuntimeError(f"HTTP {resp.status_code}: {resp.text}")
task_id = resp.json().get("task_id")
# 轮询获取结果,每 10 秒查一次,最多等 10 分钟
for _ in range(60):
result = requests.get(
f"{API_URL}/{task_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
)
if result.status_code == 200 and result.json().get("status") == "done":
return result.json()["text"]
time.sleep(10)
raise TimeoutError("polling timeout")
for audio_path in glob.glob(os.path.join(INPUT_DIR, "*.mp3")):
base = os.path.basename(audio_path)
out_path = os.path.join(OUTPUT_DIR, ".".join(base.split(".")[:-1]) + ".txt")
if os.path.exists(out_path):
continue
try:
text = transcribe(audio_path)
with open(out_path, "w", encoding="utf-8") as f:
f.write(text)
print(f"OK {audio_path}")
except Exception as e:
print(f"FAILED {audio_path}: {e}")
这个骨架假设 API 返回 JSON,且包含 task_id 和 status 字段。如果 SoundWise 是同步返回文本,可以去掉轮询部分,直接读取响应内容。
验证结果和常见坑
跑完脚本后,先检查输出文件数量是否和输入一致:
ls transcripts/*.txt | wc -l
ls audio_files/*.mp3 | wc -l
数量一致不代表内容正确,建议随机挑两个音频,打开对应文本文件,听一段核对。如果音频很长,而转录文本明显短于音频时长,可能是 API 只处理了前几分钟,需要看 SoundWise 是否对单个音频有时长限制。另外,脚本里的 glob.glob("*.mp3") 只匹配该格式,如果目录里有 mp4 或 wav,要扩展扩展名列表,或者直接用 glob.glob(os.path.join(INPUT_DIR, "*")) 再用后缀过滤。
批量转录通常比较耗时间。如果文件数量大,先小批次跑,确认没有超时和配额问题。对于需要稳定产出的场景,建议给脚本加上断点续跑,也就是已经生成输出的文件跳过,这样中途失败后重跑不会从头再来。
常见问题
转录中途失败,如何断点续跑?
脚本里已经用“检查输出文件是否存在”作为跳过条件。如果失败发生在写入之前,再次运行脚本会重新处理该文件;如果文件写了但内容不完整,需要手动删除该输出文件,或者改进脚本,写入成功后才生成输出。
音频文件很多,能否并行处理?
可以,但要控制并发量。参考 bash 方式,可以用 xargs -P 4 限制 4 个进程并行;Python 方式可以用 concurrent.futures 的 ThreadPoolExecutor 或 ProcessPoolExecutor。并发数不宜过高,避免触发服务端限流。建议先从 2 并发开始测试。