简介:这份 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 Spectrogram | Pitch / Intensity / Spectrogram |
| Pitch | Sound 转换 | Get value at time、To PointProcess | 数值 / PointProcess |
| TextGrid | 手动标注或脚本生成 | Get label of interval、Set interval text | 标注文本 |
| Formant | Sound 转换 | Get formant、Get bandwidth | 共振峰数值 |
| Table | 脚本创建或从文件读 | Append row、Save as CSV | CSV / 文本 |
这张表建议贴在编辑器旁边,写脚本时随时对照。
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, errors="ignore") df.to_csv("results_clean.csv", index=False)这样后续做混合效应模型或画图都不会因为格式问题翻车。
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 里用encoding="utf-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是静音阈值(dB),0.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 编辑器里看到的是否一致。确认无误再跑全量。这个习惯帮我省过很多次返工。
从那以后我每次写新脚本,都强制先跑小样本验证,再上全量。希望这份手册能帮你少走点弯路。
本文还有配套的精品资源,点击获取