Praat中文手册:语音信号处理脚本编写与批量声学分析实战
简介这份 praat 中文学习手册面向语音学研究者、语言学与心理学专业学生及对语音科学感兴趣的初学者帮助读者系统掌握 praat 在语音信号分析、处理与展示方面的操作。手册围绕软件基本界面、语音文件导入导出、波形与频谱分析、声调韵律研究、元音辅音测量、语音合成、脚本编程及教学演示等模块展开通过实例与步骤降低上手门槛。资源包为 rar 格式共 214 个文件全部为 html 网页文档整体约 281KB内容涵盖对象类型、脚本编辑器、公式函数、查询操作等主题页面便于按目录逐节查阅。目前已有 920 人学习下载适合希望从零建立语音分析流程、并在实践中查阅具体功能用法的读者参考。1. 一份被语音实验室翻烂的 Praat 中文手册到底解决了什么痛点做语音信号处理的人几乎绕不开 Praat。它免费、跨平台、脚本能力强从基频提取到共振峰分析、从标注对齐到批量声学参数导出都能扛。但真正上手时很多人卡在同一个地方官方文档全英文术语密度高函数说明写得像天书遇到一个报错翻半天论坛也找不到中文解释。这份 Praat 中文学习手册就是冲着这个缺口来的。它把 Praat 的核心操作、脚本语法、常用声学分析流程整理成中文覆盖从打开音频到批量导出数据的完整链路。适合谁语音学方向的研究生、做声纹特征的算法工程师、需要批量处理录音数据的社科研究者以及任何被英文手册劝退过的从业者。它不是简单的界面翻译而是把「怎么用 Praat 做出一份能写进论文或喂给模型的声学数据」这件事讲透了。2. Praat 脚本核心语法与对象模型先搞懂它怎么想问题2.1 Praat 的对象-命令范式Praat 的脚本逻辑跟 Python 那种「变量函数」的写法不太一样。它的核心是「对象Object」和「命令Command」你先创建或读取一个对象比如 Sound、TextGrid、Pitch然后对这个对象施加命令。每个对象有类型每个命令只对特定类型生效。理解这一点后面写脚本才不会出现「为什么这行报错说对象类型不对」的困惑。常见做法是打开音频 → 创建 Sound 对象 → 对它做 To Pitch、To Spectrogram 等操作 → 把结果存成 Pitch 对象或 Matrix → 再导出数据。整个过程像流水线对象在流水线上被不断转换。手册里把常用对象类型和对应命令列成表我整理成下面这个速查版对象类型典型来源常用命令输出形式Sound读取 wav / 录音To Pitch、To Intensity、To SpectrogramPitch / Intensity / SpectrogramPitchSound 转换Get value at time、To PointProcess数值 / PointProcessTextGrid手动标注或脚本生成Get label of interval、Set interval text标注文本FormantSound 转换Get formant、Get bandwidth共振峰数值Table脚本创建或从文件读Append row、Save as CSVCSV / 文本这张表建议贴在编辑器旁边写脚本时随时对照。2.2 脚本变量、循环与条件判断Praat 脚本的变量命名不区分类型但赋值方式有讲究。数值变量直接写x 1字符串变量要加$后缀比如name$ test。数组用[]索引从 1 开始而不是 0这一点跟大多数编程语言不同新手极易踩坑。下面是一个批量读取文件夹内所有 wav 文件、提取基频并保存为文本的脚本骨架# 定义输入输出目录 input_dir$ /path/to/wavs/ output_dir$ /path/to/results/ # 创建文件列表 Create Strings as file list: fileList, input_dir$ *.wav n_files Get number of strings # 循环处理每个文件 for i from 1 to n_files selectObject: Strings fileList filename$ Get string: i base$ filename$ - .wav # 读取音频 Read from file: input_dir$ filename$ sound selected(Sound) # 提取基频 selectObject: sound To Pitch: 0, 75, 600 pitch selected(Pitch) # 获取基频值并写入文件 selectObject: pitch mean_f0 Get mean: 0, 0, Hertz writeFileLine: output_dir$ base$ _f0.txt, mean_f0 # 清理对象避免内存堆积 selectObject: sound, pitch Remove endfor逻辑说明先创建文件列表对象拿到文件数量然后逐个读取。To Pitch的三个参数分别是时间步长0 表示自动、最低基频、最高基频。Get mean取整个音段的平均基频。最后用Remove清理对象否则处理几百个文件后 Praat 会卡死。参数怎么改最低和最高基频要根据说话人调整。成年男性常用 75–300 Hz成年女性常用 100–500 Hz儿童可能到 600 Hz。设窄了会丢基频设宽了会引入噪声这个区间得根据你的数据来。2.3 标注文件 TextGrid 的读写TextGrid 是 Praat 标注的核心格式。脚本里读取 TextGrid 并提取标注内容是批量分析前的必经步骤。下面这段代码演示如何遍历 TextGrid 的每个区间并输出标注文本和对应时间Read from file: /path/to/annotation.TextGrid tg selected(TextGrid) # 获取层数和区间数 n_tiers Get number of tiers for t from 1 to n_tiers tier_name$ Get tier name: t n_intervals Get number of intervals: t for i from 1 to n_intervals label$ Get label of interval: t, i if label$ start Get start time of interval: t, i end Get end time of interval: t, i appendInfoLine: tier_name$, , label$, , start, , end endif endfor endfor这里的关键是Get label of interval返回空字符串时表示该区间无标注用if label$ 过滤掉。appendInfoLine把结果输出到 Info 窗口也可以改成writeFileLine直接写文件。3. 用 Praat 做批量声学分析从脚本到 CSV 的完整链路3.1 批量提取基频、强度和共振峰单独提取一个文件的基频很简单但研究或工程场景往往需要处理几十上百个文件并且要把多个声学参数合并到一张表里。手册里给了一个完整的批量处理模板我把它拆成可复用的步骤。第一步准备一个文件夹里面放所有 wav 文件命名统一比如speaker01_001.wav。第二步确定你要提取的参数基频均值、基频标准差、强度均值、第一共振峰、第二共振峰。第三步用脚本遍历所有文件每处理一个就往 Table 对象里追加一行。# 创建结果表 Create Table with column names: results, 0, ... file f0_mean f0_sd intensity_mean f1_mean f2_mean input_dir$ /path/to/wavs/ output_file$ /path/to/results.csv Create Strings as file list: list, input_dir$ *.wav n Get number of strings for i from 1 to n selectObject: Strings list fname$ Get string: i base$ fname$ - .wav Read from file: input_dir$ fname$ snd selected(Sound) # 基频 selectObject: snd To Pitch: 0, 75, 500 pit selected(Pitch) f0_mean Get mean: 0, 0, Hertz f0_sd Get standard deviation: 0, 0, Hertz # 强度 selectObject: snd To Intensity: 100, 0 int selected(Intensity) int_mean Get mean: 0, 0, energy # 共振峰 selectObject: snd To Formant (burg): 0, 5, 5500, 0.025, 50 fmt selected(Formant) f1 Get mean: 1, 0, 0, Hertz f2 Get mean: 2, 0, 0, Hertz # 写入表格 selectObject: Table results Append row row Get number of rows Set string value: row, file, base$ Set numeric value: row, f0_mean, f0_mean Set numeric value: row, f0_sd, f0_sd Set numeric value: row, intensity_mean, int_mean Set numeric value: row, f1_mean, f1 Set numeric value: row, f2_mean, f2 # 清理 selectObject: snd, pit, int, fmt Remove endfor selectObject: Table results Save as comma-separated file: output_file$逻辑说明Create Table with column names先建一张空表列名自己定。每处理完一个文件Append row加一行然后用Set string value和Set numeric value填数据。最后Save as comma-separated file导出 CSV。参数注意To Formant (burg)的五个参数分别是时间步长、最大共振峰数量、最大频率、窗口长度、预加重。最大频率根据采样率来16 kHz 采样设 5500 Hz 左右44.1 kHz 采样可以设到 8000 Hz 以上。窗口长度一般 0.025 秒预加重 50 Hz 是默认值通常不用改。3.2 把结果整理成可分析的 CSV导出的 CSV 可以直接拖进 Excel、R 或 Python 做后续统计。但有几个细节要注意Praat 导出的 CSV 默认用逗号分隔如果文件路径里有逗号会出问题所以命名时避开逗号。另外基频和共振峰的缺失值在 Praat 里可能显示为--undefined--导入 Python 后要处理成 NaN。我一般会在 Python 里做一步清洗import pandas as pd df pd.read_csv(results.csv) df df.replace(--undefined--, pd.NA) df df.apply(pd.to_numeric, errorsignore) df.to_csv(results_clean.csv, indexFalse)这样后续做混合效应模型或画图都不会因为格式问题翻车。3.3 脚本调试与错误定位Praat 脚本报错信息往往很模糊比如「Command not available for current selection」这种本质是你选错了对象。调试时我习惯在关键步骤后加appendInfoLine打印当前对象类型和数量确认流水线没跑偏。另一个常见问题是对象泄漏。循环里创建了对象但没 Remove跑几十个文件后内存暴涨Praat 直接无响应。所以每个循环末尾一定要清理临时对象。手册里专门用一节讲这个算是血泪经验。4. 避坑与常见问题那些手册没写但一定会遇到的坑4.1 基频提取结果全是 0 或 undefined现象脚本跑完CSV 里 f0_mean 一列全是 0 或者--undefined--。原因最常见的是基频范围设错了。比如男声录音你设了 200–500 Hz实际基频在 100 Hz 左右Praat 直接判定为无声段。另一个原因是音频本身信噪比太低或者有直流偏移。解决先用一个文件手动跑To Pitch在编辑器里看基频曲线是否合理。范围从 75–500 Hz 开始试再根据说话人调整。如果音频质量差先做降噪或归一化。4.2 TextGrid 区间标注读取为空现象遍历 TextGrid 时明明在编辑器里看到有标注脚本读出来全是空字符串。原因TextGrid 可能有多层你读的那一层是空的标注在另一层。或者区间边界没对齐Get label of interval取的是区间索引不是时间点。解决先用Get number of tiers和Get tier name确认层名再定位到有标注的那一层。如果标注是点标注PointTier而不是区间标注IntervalTier要用Get label of point而不是Get label of interval。4.3 批量处理时 Praat 卡死或崩溃现象跑几十个文件后 Praat 无响应或者直接闪退。原因对象没清理内存堆积。Praat 不像 Python 有自动垃圾回收每个Read from file和To Pitch都会创建新对象不 Remove 就一直在。解决每个循环末尾加selectObject: 所有临时对象然后Remove。另外处理超大批量时可以分批跑每 50 个文件重启一次 Praat。4.4 导出的 CSV 中文乱码现象标注文本是中文时导出的 CSV 用 Excel 打开乱码。原因Praat 默认用 UTF-8 编码写文件Excel 在中文系统下默认用 GBK 打开。解决用记事本打开 CSV 再另存为 ANSI 编码或者在 Python 里用encodingutf-8-sig读取后再导出。更彻底的办法是标注时就用英文或拼音避免编码问题。4.5 脚本里的路径分隔符在 Windows 和 Mac 下不通用现象在 Mac 上写好的脚本拿到 Windows 上跑报「文件不存在」。原因Mac 用/Windows 用\虽然 Praat 在 Windows 下也支持/但如果你从资源管理器复制路径默认是\。解决统一用/Praat 跨平台都认。或者用homeDirectory$和preferencesDirectory$这类内置变量拼接路径减少硬编码。5. 进阶技巧用 Praat 做脚本化标注与批量修改5.1 自动生成 TextGrid 并预标注有时候你不需要手动标注而是想根据静音段自动切分生成初始 TextGrid再人工修正。Praat 可以结合To TextGrid (silences)实现Read from file: /path/to/audio.wav snd selected(Sound) # 自动检测静音段生成 TextGrid selectObject: snd To TextGrid (silences): 100, 0, -25, 0.1, 0.05, silent, voiced tg selected(TextGrid) # 保存 Save as text file: /path/to/auto.TextGrid参数说明100是分析步长0是起始时间-25是静音阈值dB0.1是最短静音间隔0.05是最短有声段。生成的 TextGrid 有两层silent 和 voiced。这个结果可以直接导入标注工具做修正省掉大量手动切分时间。5.2 批量修改 TextGrid 标注内容如果发现标注文件里某个标签写错了比如把所有「a」改成「aa」可以用脚本批量替换input_dir$ /path/to/textgrids/ Create Strings as file list: list, input_dir$ *.TextGrid n Get number of strings for i from 1 to n selectObject: Strings list fname$ Get string: i Read from file: input_dir$ fname$ tg selected(TextGrid) n_tiers Get number of tiers for t from 1 to n_tiers n_int Get number of intervals: t for j from 1 to n_int label$ Get label of interval: t, j if label$ a Set interval text: t, j, aa endif endfor endfor Save as text file: input_dir$ fname$ selectObject: tg Remove endfor这个模板可以扩展成任意标签替换只要改if条件里的字符串就行。5.3 验证脚本正确性的笨办法写完一个批量脚本别急着跑全量数据。先拿 3 个文件跑一遍手动核对第一个文件的基频均值、共振峰数值跟 Praat 编辑器里看到的是否一致。确认无误再跑全量。这个习惯帮我省过很多次返工。从那以后我每次写新脚本都强制先跑小样本验证再上全量。希望这份手册能帮你少走点弯路。本文还有配套的精品资源点击获取