资讯动态

Label Studio 动态文本跨度插件:用 TextArea 实时绑定 Text 字段实现转录后 NER 标注

发布时间:2026/9/13 7:21:10 来源:尧图企业网站定制
Label Studio 动态文本跨度插件用 TextArea 实时绑定 Text 字段实现转录后 NER 标注【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio本指南讲解 Label Studio 企业版插件库中的Dynamic Text Spans插件它通过 JavaScript 将TextArea与Text字段绑定使转录/听写内容实时镜像到可标注的文本控件中从而实现对与导入数据不同的文本如人工修正后的转录结果进行跨度标注。读完本文你将掌握该插件的完整脚本、标签配置与示例数据并能基于 Label Studio 前端 APILSI理解其轮询同步的底层原理进而按需改造出自己的自定义插件。本文对应的插件文档位于 docs/source/plugins/dynamic_text_spans.md关于如何修改该插件或编写全新插件参见 Customize and Build Your Own Plugins插件通用说明见 Plugins for projects 与 Plugin FAQ。插件解决了什么问题在音频/视频转写标注场景中一个常见痛点是导入任务的文本原始 ASR 结果或占位文本与标注者实际要标注的文本并不一致。标注者往往需要先听写/转录再对转录结果做命名实体识别NER等跨度标注。而 Label Studio 的TextArea文本输入控件本身并不支持在其内部选择文本跨度并打标签——跨度标注依赖Text/HyperText等对象标签。Dynamic Text Spans 插件的核心思路是定义一个用于转录输入的TextArea名字固定为transcription定义一个用于跨度标注的Text名字固定为extraction_text通过轮询监听TextArea的实时 DOM 值一旦变化就调用前端 API 把新值同步写入Text控件。最终效果是标注者在TextArea中输入或粘贴的任何内容都会实时出现在Text字段中且Text字段中被标注的文本会随标注结果一起导出。插件工作原理分步拆解原文档将插件执行逻辑归纳为以下几个关键步骤定义两个标签名TextArea命名为transcriptionText命名为extraction_text捕获当前标注 ID插件启动时记录LSI.annotation.id用于在切换区域/标注时停止运行init()轮询查找控件每 300 ms 轮询一次 DOM直到找到name以transcription开头的textareaLabel Studio 会为结果追加随机后缀因此使用^前缀匹配找到后启动tick()循环同样每 300 ms 执行一次若 DOM 节点被替换例如重新加载或切换了标注重新查询该节点若已切换到不同的标注 ID立即停止循环读取 DOM 实时值$ta.value若为空则回退到标注中最后一次保存的结果将该字符串与extraction_text控件的当前_value比较若不一致调用text.setRemoteValue(val)通过 Label Studio 前端 API 更新另一字段的值。从源码看setRemoteValue是前端编辑器中对象标签Object Tag模型的标准方法例如 web/libs/editor/src/tags/object/RichText/model.js 中的实现它会将传入值解码支持base64/base64unicode编码、对非纯文本类型做 HTML 清理sanitizeHtml移除 script 与 iframe然后更新_value并重建文本跨度区域。这意味着插件写入的值会经过与任务数据同样的加载管线保证跨度标注机制正常工作。插件完整脚本以下为 Dynamic Text Spans 插件的完整 JavaScript 代码来自 docs/source/plugins/dynamic_text_spans.mdconst TEXTAREA_NAME transcription; const TEXT_NAME extraction_text; const current_annotation LSI.annotation.id; (function init() { // textarea results have names like tag_name:h4$h, so we use ^ let $ta document.querySelector(textarea[name^${TEXTAREA_NAME}]); if (!$ta) return setTimeout(init, 300); if ($ta._already_loaded) return; $ta._already_loaded true; (function tick() { // it can be another textarea with submitted result if (!$ta?.isConnected) { $ta document.querySelector(textarea[name^${TEXTAREA_NAME}]); } // if we lost textarea/moved out of current annotation — break the cycle if (!$ta?.isConnected || LSI.annotation?.id ! current_annotation) return; setTimeout(tick, 300); const textarea LSI.annotation.names.get(TEXTAREA_NAME); const text LSI.annotation.names.get(TEXT_NAME); const val String($ta.value ?? textarea.result?.value.text ?? ); if (text._value ! val) { text.setRemoteValue(val); } })(); })();脚本关键细节解读LSI.annotation.namesnames是当前标注控件实例的映射表以标签name为键其 getter 定义于 web/libs/editor/src/stores/Annotation/Annotation.js。插件通过LSI.annotation.names.get(TEXTAREA_NAME)获取TextArea控件模型、通过names.get(TEXT_NAME)获取Text控件模型。_already_loaded标志插件会在每次标注显示时执行用 DOM 属性标记避免重复初始化与重复订阅轮询——这正是 custom.md 中强调的每次脚本运行需清理上一次运行的实践。$ta.value ?? textarea.result?.value.text ?? 优先取 DOM 实时值若节点刚被替换或值缺失回退到TextArea已提交结果textarea.result中的value.text再退为空字符串保证比较基准始终是字符串。text._value ! val比较仅当值真正变化时才调用setRemoteValue避免无谓的渲染与跨度重建。标注 ID 守卫LSI.annotation?.id ! current_annotation时直接return不重新调度setTimeout从而在切换标注/任务时优雅退出轮询循环。关联的 LSI 实例方法LSI.annotation——当前选中标注的 getter返回当前标注对象是访问names、id等成员的人口。标注界面Labeling Config插件的生效依赖特定的标签配置一个供转录输入的TextArea与一个供跨度标注的Text对象标签。完整 XML 如下View Header value1. Transcribe the audio below:/ Audio nameaudio value$audio zoomtrue hotkeyctrlenter/ TextArea nametranscription toNameaudio rows4 editabletrue maxSubmissions1 showSubmitButtonfalse value$text / Header value2. Extract spans from the transcript:/ !-- force HyperText into the DOM via non-breaking space -- View idAttrextractionBlock Text nameextraction_text idAttrextractionText value$transcription inlinefalse / /View Labels namespan_labels toNameextraction_text choicemultiple showInlinetrue Label valueEntityType1 background#8cc6ff/ Label valueEntityType2 background#ffa39e/ /Labels /View配置要点TextArea绑定音频nametranscription、toNameaudioeditabletrue允许自由编辑rows4控制文本域高度maxSubmissions1限制最多提交一条转录showSubmitButtonfalse隐藏提交按钮配合轮询实时同步无需手动提交value$text用任务数据中的text字段作为初始占位文本。各参数说明参见 TextArea 标签文档。Text作为标注载体nameextraction_textvalue$transcription引用任务数据中的transcription字段inlinefalse让文本独占一行便于跨度框选外层View idAttrextractionBlock与idAttrextractionText用于强制把HyperText渲染进 DOM注释中说明了通过非断空格占位的手法。Labels提供标签集toNameextraction_text指向待标注文本choicemultiple允许多标签showInlinetrue内联展示标签按钮两个示例实体EntityType1、EntityType2附有区分色背景可按需增删替换。相关标签文档View、Header、TextArea、Audio、Text、Labels。标签如何触发跨度标注在 web/libs/editor/src/tags/control/TextArea/TextArea.jsx 中可以看到TextArea控件的每次输入都会触发item.setValue(value)更新内部_value但其本质是纯文本输入控件不承载区域选择。而Text对象标签继承自 RichText 模型通过_value驱动文本渲染与跨度区域region.setText、annotation.addRegion重建——这正是本插件把转录文本搬运到Text字段后即可标注的根本原因。示例数据Sample Data以下 JSON 为该项目音频转写 跨度提取的示例任务数据{ data: { audio: https://data.heartex.net/librispeech/dev-clean/3536/8226/3536-8226-0024.flac.wav, transcription: , text: this is a test } }字段说明audio音频文件 URL由Audio value$audio引用transcription初始为空字符串插件启动后将TextArea的实时内容同步到这里即Text控件的value$transcription所引用的字段textTextArea的初始占位内容value$text标注者可在此基础上编辑成真实转录结果。使用与调试建议新建测试项目先在测试项目中导入上述示例数据与标注配置将插件脚本粘贴到项目的 Plugins 编辑器中避免影响线上项目参见 custom.md 中的排障建议。验证实时同步在TextArea中逐字输入或粘贴大段文本观察Text字段是否即时更新随后用Labels在Text中框选实体并确认导出结果中包含相应跨度。调试手段添加插件后编辑面板下方会出现Testing面板可配合示例数据手动触发事件同时可在浏览器开发者工具的 Console 中检查LSI对象、用 Network 面板查看/project/:id接口返回的插件信息必要时在脚本中插入debugger语句设置断点。注意执行时机插件在每次标注显示时执行打开任务、切换任务、新建/切换标注、查看旧版本标注都会触发脚本中依赖 DOM 轮询与_already_loaded防重入改造时应遵循每次运行清理上一次运行的规范优先使用LSI.on()订阅事件以自动退订。结语Dynamic Text Spans 插件是 Label Studio 插件机制的典型范例用极简的轮询逻辑 前端 APILSI.annotation.names、setRemoteValue打通了转录输入与跨度标注两类控件之间的数据鸿沟让标注工作流从先转录、再另起任务标注合并为单任务一站式完成。理解它的 DOM 轮询、标注 ID 守卫与值比对模式后你可以轻松复刻该思路实现任意一个控件驱动另一个控件的自定义标注体验。【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价