FunASR FunTextProcessing 实战指南:多语言文本归一化(ITN/TN)与数字转读的完整方案

发布时间:2026/9/13 12:02:36

FunASR FunTextProcessing 实战指南:多语言文本归一化(ITN/TN)与数字转读的完整方案 FunASR FunTextProcessing 实战指南多语言文本归一化ITN/TN与数字转读的完整方案【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASRFunTextProcessingFundamental Text Processing是 FunASR 仓库内随附的一套基础文本处理 Python 工具包围绕 ASR语音识别与 TTS语音合成场景提供逆向文本归一化ITN, Inverse Text Normalization、**正向文本归一化TN, Text Normalization与数字转读num2words**三类核心能力。本文以 fun_text_processing/README.md 为骨架结合仓库源码深入讲解其工作原理、CLI 与 Python API 用法、多语言支持矩阵、语法图WFST缓存机制、评估与导出工具帮助你在 ASR 结果后处理与 TTS 前端文本预处理两条链路上直接落地这套方案。1. FunTextProcessing 是什么定位与能力全景在完整语音链路中文本形态存在两个方向的转换需求ASR 侧识别模型输出的是口语化文本例如twelve kilograms、dua ribu dua puluh dua需要还原成便于展示、检索和二次消费的书面形式12 kg、2022这一过程称为逆向文本归一化ITNTTS 侧合成系统通常要求输入朗读形态的文本例如把12 kg展开成twelve kilograms这一过程称为正向文本归一化TN数字转读num2words在部分语言中直接把数字转换为单词形式是 TN 内部能力的重要组成。依据 fun_text_processing/README.md 的官方声明FunTextProcessing 同时支持上述三种能力且具备多语言覆盖能力官方声明支持规模仓库内实际语言实现按源码核实逆向文本归一化ITN10 种语言en、id、ja、es、pt、ru、de、fr、vi、ko、zh、tl共12 种正向文本归一化TN5 种语言en、de、es、ru、zh共5 种ru仅支持非确定性模式数字转读num2words50 种语言借由第三方num2words库提供语言清单来自 inverse_normalize.pyITN 的--language可选值与 normalize.pyTN 的--language可选值中的参数定义其中 ITN 额外支持tl菲律宾语与vi越南语其规则目录分别位于 inverse_text_normalization/tl 与 inverse_text_normalization/vi。从源码结构看每种语言都遵循统一的taggers/分类器与verbalizers/言语化器两段式目录组织。2. 核心原理基于 WFST 的 Tagger Verbalizer 两段式管线FunTextProcessing 的归一化实现并非简单的规则表查替换而是基于**加权有限状态转换器WFST**构建的语法图grammar底层依赖 OpenFst 的 Python 绑定Pynini。整条管线可以拆成四个环节Tagging打标将输入文本送入ClassifyFst分类语法图识别出数字、日期、货币、度量衡、电话等半符号类semiotic classes并打上标签Parsing解析用 TokenParser 把带标签的文本解析成嵌套字典例如tokens { money { integer: 20 currency: $ } }Permutation排列对嵌套标签生成可能的重排序列见 normalize.py 中的_permute与generate_permutations以覆盖复合标签内部成分的多种语序Verbalization言语化将标签序列送入VerbalizeFinalFst言语化语法图输出最终目标形态文本。以 ITN 为例InverseNormalizer 在初始化时按语言动态导入对应的ClassifyFst与VerbalizeFinalFst并组合出self.tagger、self.verbalizer、self.parser三个组件其转换方向为口语 → 书面例如twelve kilograms - 12 kg。而正向的 Normalizer 方向相反例如12 kg - twelve kilograms。值得一提的实现细节在正向归一化的normalize()方法中normalize.py输入文本会先经pynini.escape转义再与self.tagger.fst做组合text self.tagger.fst得到标签格lattice随后用pynini.shortestpath取最短路径作为标签结果言语化阶段同样取最短路径。为了控制组合爆炸_split_tokens_to_reduce_number_of_permutationsnormalize.py会把令牌序列切分为若干段使每段产生的排列数不超过max_number_of_permutations_per_split默认 729这是大规模语料归一化时保持性能的关键机制。3. 环境准备Pynini 安装与语法图缓存FunTextProcessing 的核心运行时依赖是pynini以及regex、joblib、tqdm。仓库提供了开箱即用的安装脚本 install_pynini.sh#!/bin/bash if [[ $OSTYPE darwin* ]]; then conda install -c conda-forge -y pynini2.1.5 else pip install pynini2.1.5 fi即macOS 下通过 conda-forge 安装pynini2.1.5其他平台通过 pip 安装同一版本。安装完成并确认import pynini成功后即可使用。关于.far语法图缓存每次构造ClassifyFst/VerbalizeFinalFst时程序会尝试在cache_dir目录中查找或生成.farfinite-state archive语法文件。cache_dir设为None时每次都会重新构建语法图首次构建耗时较长设置有效目录后语法图只编译一次后续推理直接复用显著加快加载速度。overwrite_cacheTrue则强制重新生成缓存。这一行为在 inverse_normalize.py 与 normalize.py 的构造函数文档中均有明确说明。4. 逆向文本归一化ITN把 ASR 口语结果还原为书面文本ITN 是 FunTextProcessing 中与 ASR 结合最紧密的能力README 给出的示例脚本即针对此功能。4.1 命令行用法test_filefun_text_processing/inverse_text_normalization/id/id_itn_test_input.txt python fun_text_processing/inverse_text_normalization/inverse_normalize.py --input_file $test_file --cache_dir ./itn_model/ --output_file output.txt --languageid其中fun_text_processing/inverse_text_normalization/id/id_itn_test_input.txt是仓库自带的印尼语 ITN 测试输入内容为一行一句的口语化数字文本例如dua ribu dua puluh dua sembilan ribu sembilan ratus sembilan puluh sembilan dua puluh empat maret seribu tujuh puluh enam rupiah经过 ITN 后会输出2022、9999、24 maret、1076 rupiah这类书面形式。仓库同样提供了日语测试输入 ja_itn_test_input.txt其内容涵盖汉字数字、序数词第一、第二…、分数五分の一、日期零六年四月、金额十億円等复杂日语书面/口语混合场景。4.2 CLI 参数完整说明依据 inverse_normalize.py 的参数定义inverse_normalize.py支持以下参数参数类型默认值说明--textstr无直接输入单条待转换文本与--input_file互斥--input_filestr无输入文件路径每行一条文本--output_filestr无输出文件路径不指定时结果打印到控制台--languagestren语言可选en/id/ja/de/es/pt/ru/fr/vi/ko/zh/tl--verbose布尔False打印中间标签信息用于调试--overwrite_cache布尔False置为 True 时重新生成.far语法文件--cache_dirstrNone.far语法文件目录None时不使用缓存--enable_standalone_numberstrTrue是否启用独立数字转换仅日语生效通过str2bool解析--enable_0_to_9strTrue是否启用 0~9 单独数字转换仅日语生效其中--enable_standalone_number与--enable_0_to_9两个开关仅对ja日语生效从 inverse_normalize.py 的入口逻辑可见只有language ja时这两个参数才会被传入InverseNormalizer其他语言一律使用默认行为。这两个开关主要控制日语中独立数字如三→3与个位数0~9是否进行书面化转换日语场景中大量存在的人名、专有名词如安倍晋三、山本五十六依赖其关闭来避免误转。4.3 Python API 用法除命令行外InverseNormalizer可直接在 Python 代码中调用例如嵌入 ASR 后处理服务from fun_text_processing.inverse_text_normalization.inverse_normalize import InverseNormalizer normalizer InverseNormalizer( langid, cache_dir./itn_model/, # 语法图缓存目录 overwrite_cacheFalse, ) # 单条转换口语 - 书面 text normalizer.inverse_normalize(dua ribu dua puluh dua, verboseFalse) # 批量转换 texts normalizer.inverse_normalize_list([tiga ribu, empat belas], verboseFalse)inverse_normalize()接受单条字符串并返回书面形式inverse_normalize_list()接受字符串列表并返回列表inverse_normalize.py。注意ITN 的输入默认期望是小写且除撇号与连字符-外无标点的口语文本见类文档字符串这正是 ASR 解码结果的典型形态。5. 正向文本归一化TN为 TTS 准备朗读文本5.1 命令行用法与参数正向归一化入口为 normalize.pyCLI 参数定义在 normalize.py参数类型默认值说明--text/--input_filestr无单条文本或文件输入互斥必须二选一--output_filestr无输出文件路径--languagestren语言可选en/de/es/zhru需使用normalize_with_audio.py--input_casestrcased输入大小写可选lower_cased/cased--verbose布尔False打印中间标签信息--punct_post_process布尔False归一化后对标点做后处理以匹配输入--punct_pre_process布尔False归一化前对标点做预处理例如[25]→[ 25 ]--overwrite_cache布尔False重新生成.far语法文件--whiteliststrNone白名单替换文件路径--cache_dirstrNone语法图缓存目录典型用法python fun_text_processing/text_normalization/normalize.py --language en --text I bought 12 kg of apples --input_case cased输出应为I bought twelve kilograms of apples一类的朗读形态。Normalizer构造时要求input_case必须为lower_cased或cased之一normalize.py。5.2 白名单whitelist机制--whitelist允许用户提供自定义的精确字符串映射文件用于处理语法图覆盖不到的领域词或专有缩写。该文件路径会被os.path.abspath规范化后传入ClassifyFstnormalize.py在分类阶段做硬性替换。英文 TN 的白名单数据文件位于 text_normalization/en/data/whitelist 对应目录下可参照其格式自定义。5.3 中文 TN 管线三段式处理详解对于中文text_normalization/zh/README.md 明确将 TN 管线拆为三部分可作为理解所有语言 TN 实现的参照① 预处理Pre-Processing全角转半角苹果宣布发布新→苹果CEO宣布发布新IPHONE完整映射表见 text_normalization/zh/data/char/fullwidth_to_halfwidth.tsv去除列表Denylist可自定义删除啊、呃等语气填充词列表见data/denylist/denylist.tsv。② 非标准词NSW归一化覆盖以下类别并给出真实样例摘自该 README数字共465篇约315万字→共四百六十五篇约三百一十五万字分数总量的1/5以上→总量的五分之一以上百分比同比增长6.3%→同比增长百分之六点三日期2002/01/28→二零零二年一月二十八日时间8月16号12:00之前→八月十六号十二点之前数学比分定格在78:96→比分定格在七十八比九十六货币价格是13.5→价格是十三点五元度量衡重达25kg→二十五千克、最高气温38°C→三十八摄氏度号码串可以打我手机13501234567→可以打我手机一三五零一二三四五六七儿化音去除这儿有只鸟儿→这有只鸟白名单见data/erhua/whitelist.tsv白名单替换C E O→CEO、O2O→O to O文件见data/whitelist/default.tsv。③ 后处理Post-Processing可选启用标点去除英文大小写转换OOV 标记将字符集外的字用oov标签包裹例如我们안녕→我们oov안/oovoov녕/oov字符集可经data/char/charset_extension.tsv扩展。这套预处理 NSW 分类 后处理的架构在 data_loader_utils.py 中也有对应实现pre_process()data_loader_utils.py负责给[]等符号两侧加空格post_process_punct()data_loader_utils.py则根据原始输入把归一化结果中的标点空格还原到与输入一致的位置——这对 TTS 前端至关重要避免引号、逗号位置漂移导致朗读断句错误。5.4 非确定性归一化normalize_with_audio.py当一条文本存在多种合理归一化方式例如金额既可读作ten dollars也可读作$10时normalize_with_audio.py 提供先生成多种候选再用 ASR 转录结果按 CER 择优的高级方案它继承Normalizer并以deterministicFalse构造normalize_with_audio.py从而输出多个归一化候选输入可以是单条--text、音频 文本、或包含audio_data/text/pred_text字段的 JSON manifestselect_best_match()normalize_with_audio.py对每个候选计算与 ASR 预测文本的CER选择最低者作为最终归一化结果若 CER 超过--cer_threshold默认 100则放弃归一化语言支持en/ru/de/es其中英文还支持--lm模式WFSTLM 融合仅英文可用俄语注释明确仅支持非确定性模式请使用本脚本normalize.py。6. 效果评估run_evaluate.py 与 15 类半符号类别两个run_evaluate.pyITN 版 与 TN 版提供了标准的离线评测入口。评测数据采用 Kaggle Google 文本归一化数据格式每行三列semiotic class\tunnormalized text\tnormalized text。评测支持两个粒度句子级Sentence level对整句做归一化/逆归一化后计算准确率Token 级Token level按类别分别统计准确率并输出按 token 数加权的总准确率及汇总表。脚本默认输出包含所有类别的对照表类别即known_typesdata_loader_utils.pyPLAIN DATE CARDINAL LETTERS VERBATIM MEASURE DECIMAL ORDINAL DIGIT MONEY TELEPHONE ELECTRONIC FRACTION TIME ADDRESS共 15 个半符号类别。ITN 评测还支持--cat参数只评测单个类别如--cat CARDINAL--filter参数则调用对应语言的clean_eval_data.py清洗数据仅英文实现。评测的准确率计算逻辑见 data_loader_utils.py 的evaluate()对预测与标签统一做clean_generic去空白、转小写后逐条比较。7. 部署加速把语法图导出为 .far 文件在生产环境中重复构建 WFST 语法图的开销不可忽略。两个export_models.py用于把语法图一次性编译并导出为.far归档文件供运行时通过cache_dir直接加载# ITN导出 en_itn_tagger.far 与 en_itn_verbalizer.far python fun_text_processing/inverse_text_normalization/export_models.py --language en --export_dir ./itn_grammars/ # TN导出 en_tn_tagger.far 与 en_tn_verbalizer.far含 input_case 参数 python fun_text_processing/text_normalization/export_models.py --language en --input_case cased --export_dir ./tn_grammars/ITN 版支持de/en/es/fr/id/ja/ko/pt/ru/vi/zh共 11 种语言inverse_text_normalization/export_models.pyTN 版支持de/en/es/ru/zhtext_normalization/export_models.py。导出文件名遵循lang_itn_tagger.far、lang_itn_verbalizer.far、lang_tn_tagger.far、lang_tn_verbalizer.far的命名规范。之后在InverseNormalizer/Normalizer中传入cache_dir./itn_grammars/即可跳过首次编译直接复用离线导出的语法图。8. 在 FunASR 语音链路中的典型集成场景作为随 FunASR 仓库分发的文本处理工具FunTextProcessing 主要服务于两类下游场景ASR 结果后处理FunASR 的 SenseVoice 系列模型在解码时通过|withitn|/|woitn|特殊 token 控制是否输出 ITN 后的文本相关 token 映射见 funasr/utils/postprocess_utils.py。对于未内置 ITN 的识别结果可直接调用InverseNormalizer完成口语到书面的还原再进入标点、热词等下游模块TTS 前端文本预处理合成前用Normalizer含 whitelist、punct 前后处理把含数字、符号、单位的书面文本展开为朗读形态保障合成读音正确。从实现上看InverseNormalizer直接复用了Normalizer的normalize_list()/normalize()骨架inverse_normalize.py两者共享同一套 tagger→parser→permutation→verbalizer 执行链因此无论集成到 FunASR 的 Python 推理脚本还是独立微服务调用范式保持一致。9. 致谢与许可说明依据 fun_text_processing/README.md 的声明大量代码借鉴自 NVIDIANeMoITN/TN 的 WFST 架构中文逆向文本归一化参考了WeTextProcessingwenet-e2e的实现数字转单词num2words功能在部分语言中借用了第三方num2words库的代码。许可证方面本项目以MIT License发布同时包含部分来自其他仓库、遵循其他开源许可证的第三方组件与修改代码。FunTextProcessing 目录下的核心实现、测试输入如 id_itn_test_input.txt与中文 TN 的完整管线文档text_normalization/zh/README.md均可直接在仓库中查阅作为扩展自定义语言规则与业务集成的起点。10. 快速上手速查表需求命令/代码安装依赖bash fun_text_processing/install_pynini.sh命令行 ITNpython fun_text_processing/inverse_text_normalization/inverse_normalize.py --input_file file --cache_dir ./itn_model/ --output_file out.txt --languageidPython ITNInverseNormalizer(langid, cache_dir./itn_model/).inverse_normalize(text)命令行 TNpython fun_text_processing/text_normalization/normalize.py --language zh --text 共465篇约315万字非确定性 TNpython fun_text_processing/text_normalization/normalize_with_audio.py --text RAW TEXT --language en评估 ITN/TNpython fun_text_processing/inverse_text_normalization/run_evaluate.py --input data --lang en导出语法图python fun_text_processing/inverse_text_normalization/export_models.py --language en --export_dir ./itn_grammars/使用提示大批量处理时务必指定--cache_dir以复用.far语法文件输入超过约 500 词时Normalizer会输出告警normalize.py建议先经split_text_into_sentences()切句后再批量归一化以规避排列组合导致的耗时增长。【免费下载链接】FunASROpen-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving.项目地址: https://gitcode.com/GitHub_Trending/fun/FunASR创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/13 11:57:36

三步把小爱音箱接上大模型:MiGPT 新手实操手册

三步把小爱音箱接上大模型:MiGPT 新手实操手册 【免费下载链接】mi-gpt 🏠 将小爱音箱接入 ChatGPT 和豆包,改造成你的专属语音助手。 项目地址: https://gitcode.com/GitHub_Trending/mi/mi-gpt MiGPT 是一个把小爱音箱接入 ChatGPT、…

2026/9/13 13:02:39

AI降重工具原理与论文查重优化实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 13:02:39

ASP.NET Core Web API契约设计:序列化、路由与错误语义化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 13:02:39

SEO关键词优化实战:从挖掘到布局的全流程指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 13:02:39

红黑树旋转操作详解:原理、类型与工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 13:02:39

如何把应用后端从 Convex 迁移到 SpacetimeDB

如何把应用后端从 Convex 迁移到 SpacetimeDB 【免费下载链接】SpacetimeDB Development at the speed of light 项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB 这篇文章面向正在把应用后端从 Convex 迁到 SpacetimeDB 的开发者。两个系统都包含数据库…

2026/9/13 12:57:38

桌面Agent容器化:Crayfish+WorkBuddy轻量沙箱架构解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码