ZCode ai-elements 实战指南:用 Transcription 组件构建可点击跳转的同步音频转写界面
ZCode ai-elements 实战指南用 Transcription 组件构建可点击跳转的同步音频转写界面【免费下载链接】ZCodeZ.ais coding agent harness. Powerful, intelligent, extensible.项目地址: https://gitcode.com/gh_mirrors/zco/ZCodeTranscription 是 ZCode 仓库内 ai-elements 技能包提供的一个可组合 React 组件用于将 AI SDKtranscribe()产出的分段转写结果segments渲染为与播放进度实时同步、支持点击跳转click-to-seek的交互式字幕界面。本文以 transcription.md 为核心结合仓库内的完整示例 transcription.tsx 与技能总览 SKILL.md带你掌握其 Props 语义、渲染模式、状态管理、样式定制与无障碍设计并能在自己的 AI 应用中直接落地一套音频播放器 同步字幕方案。组件定位为 AI 转写结果而生的展示组件Transcription 组件解决的是 AI 语音转写场景中最常见的展示需求模型输出的转写文本不是一段平铺的文字而是一系列带有时间戳的片段segment。组件以当前播放时间为基准自动高亮正在朗读的片段、弱化已读与未读片段并允许用户点击任意片段让播放器跳转到对应时间点。在 ZCode 仓库中该组件属于.agents/skills/ai-elements/技能包整套技能派生自 vercel/ai-elements经本地化集成与适配后引入仓库其许可证与来源信息记录在仓库根目录 THIRD-PARTY-NOTICES.md。组件本身构建于 shadcn/ui 之上代码在安装后直接落入你的项目源码默认位于/components/ai-elements/因此可以像自己写的组件一样自由阅读、修改与扩展。安装与前置条件与 ai-elements 的其他组件一致Transcription 通过 CLI 安装命令如下npx ai-elementslatest add transcription若项目使用 pnpm 或 bun 作为包管理器则相应替换为pnpm dlx ai-elementslatest add transcription或bunx --bun ai-elementslatest add transcription详见 SKILL.md 中的说明。安装前建议确认以下前置条件Node.js 18 及以上版本Next.js 项目并已安装AI SDK组件的数据类型直接依赖 AI SDK 的转写类型shadcn/ui已配置若尚未安装执行安装命令时会自动补齐项目tsconfig.json需配置/*路径别名例如{ compilerOptions: { baseUrl: ., paths: { /*: [./*] } } }安装完成后组件代码含 Tailwind 样式类会写入/components/ai-elements/目录无需额外配置即可导入使用。核心 API两个组件的 Props 全解Transcription 由一对组件构成根组件Transcription /负责上下文与状态管理子组件TranscriptionSegment /负责渲染单个片段。Transcription /根组件通过 render props 模式渲染片段并统一管理转写状态Prop类型默认值说明segmentsTranscriptionSegment[]-来自 AI SDKtranscribe()的转写片段数组currentTimenumber0当前播放时间秒受控模式下由外部传入onSeek(time: number) void-点击片段或受控currentTime变化时触发的回调children(segment: TranscriptionSegment, index: number) ReactNode-接收每个片段及其索引的渲染函数...propsOmitReact.ComponentPropsdiv, ...-其余属性透传到根div元素TranscriptionSegment /片段子组件单个片段渲染为按钮自带状态样式与点击跳转能力Prop类型默认值说明segmentTranscriptionSegment-转写片段数据indexnumber-片段在数组中的索引...propsReact.ComponentPropsbutton-其余属性透传到button元素两个组件均遵循 ai-elements 尽可能透传原始属性的扩展理念见 SKILL.md 的 Extensibility 一节根组件扩展div的 HTML 属性片段组件扩展button的 HTML 属性因此可以无缝叠加className、onClick、aria-*等原生能力。数据格式AI SDK 转写结果的分段结构组件期望的数据来自 AI SDKtranscribe()函数每个片段包含三个字段type TranscriptionSegment { text: string; startSecond: number; endSecond: number; };其中startSecond/endSecond以秒为单位标记该片段在音频中的起止时间text为该时间窗口内的转写文本。仓库示例 transcription.tsx 中直接以Experimental_TranscriptionResult[segments]类型构造数据展示了真实的片段粒度——例如单词级转写中会出现{ startSecond: 0.119, endSecond: 0.219, text: You }这样的极短片段以及大量仅含空格的间隙片段这正好对应组件内置的空片段自动过滤能力。完整实战示例音频播放器 同步转写仓库示例脚本 transcription.tsx 给出了完整的接线方式用useRef持有audio元素、用useState维护当前播放时间并把转写组件与播放器通过onSeek/onTimeUpdate双向联动use client; import { Transcription, TranscriptionSegment } from /components/ai-elements/transcription; import type { Experimental_TranscriptionResult as TranscriptionResult } from ai; import { useCallback, useRef, useState } from react; const segments: TranscriptionResult[segments] [ { endSecond: 0.219, startSecond: 0.119, text: You }, // ...更多带时间戳的片段 ]; const Example () { const audioRef useRefHTMLAudioElement(null); const [currentTime, setCurrentTime] useState(0); const handleSeek useCallback((time: number) { if (audioRef.current) { audioRef.current.currentTime time; // 点击字幕 - 播放器跳转 } }, []); const handleTimeUpdate useCallback(() { if (audioRef.current) { setCurrentTime(audioRef.current.currentTime); // 播放进度 - 字幕高亮 } }, []); return ( div classNamespace-y-6 p-6 audio controls onTimeUpdate{handleTimeUpdate} ref{audioRef} source src你的音频文件地址.mp3 / /audio Transcription currentTime{currentTime} onSeek{handleSeek} segments{segments} {(segment, index) ( TranscriptionSegment classNametext-lg index{index} key{${segment.startSecond}-${segment.endSecond}} segment{segment} / )} /Transcription /div ); }; export default Example;关键点解读onTimeUpdate在播放过程中持续把audio.currentTime写入currentTime状态驱动字幕高亮handleSeek把片段点击转换为播放器currentTime赋值实现点击跳转示例还展示了片段级自定义样式如classNametext-lg印证了 render props 模式样式完全由调用方掌控的灵活性示例同时标注了biome与oxlint的无障碍豁免注释media-has-caption提示真实项目中应补充音频字幕描述。行为机制详解Render Props 模式组件将children定义为函数而非节点(segment, index) ReactNode。这样每个片段的渲染方式完全由使用者决定——可以逐词渲染、可以包裹富文本、可以注入自定义交互而高亮、跳转、状态管理等机制仍由组件内部统一提供。片段高亮Active / Past / Future 三态组件依据当前播放时间与片段时间窗的关系自动计算视觉状态Active当前播放中currentTime落在片段的[startSecond, endSecond]区间内使用主色primary强调Past已播放currentTime已越过片段结束时间使用 muted foreground 弱化Future未播放currentTime早于片段开始时间使用进一步压暗的 muted foreground60% 透明度。Click-to-Seek 点击跳转当传入onSeek时片段会渲染为可交互的button点击任意片段即以该片段的startSecond调用onSeek由外部播放器执行跳转。特别值得注意的是onSeek的触发时机有两类用户点击片段以及受控currentTime发生变化——这意味着你可以在外部驱动进度变化的同时获得统一的跳转通知。空片段自动过滤转写结果中常混入纯空格或空白片段如示例中大量text: 的间隔片段组件会自动过滤这些空文本避免渲染无意义的空白按钮保持字幕流整洁。受控与非受控状态管理组件基于 Radix UI 的useControllableStateHook 实现双模式状态受控模式传入currentTime时高亮状态完全由外部驱动适合与播放器进度绑定的场景如上面的示例非受控模式未传入currentTime时组件自行维护内部时间状态。这种设计让组件既能被播放器精确驱动也能在纯展示场景中开箱即用。样式定制data 属性与默认外观组件为样式定制提供了一组稳定的数据属性钩子data-slottranscription根容器标识data-slottranscription-segment单个片段按钮标识data-active标记当前正在播放的片段同时服务于无障碍辅助技术data-index片段在数组中的索引。默认外观通过 Tailwind 语义色实现可无缝融入 shadcn/ui 主题体系Active 片段text-primaryPast 片段text-muted-foregroundFuture 片段text-muted-foreground/60可交互片段cursor-pointer hover:text-foreground非交互片段未传onSeekcursor-default。无障碍设计组件在无障碍方面内置了完整支持交互片段使用语义化button元素支持完整的键盘导航Tab 聚焦、Enter/Space 触发为屏幕阅读器提供正确的按钮语义通过data-active属性向辅助技术暴露当前播放位置提供 hover 与 focus 视觉反馈方便键盘用户定位。使用要点与最佳实践综合文档 transcription.md 的 Notes 与示例脚本实践中的要点如下空文本片段会被自动过滤无需手工清洗转写结果字幕流采用flex-wrap响应式换行片段之间以gap-1保持内联间距默认字号text-sm、行高leading-relaxed保证长文本的可读性片段按钮自带的onClick与跳转逻辑不冲突——点击事件在触发onSeek的同时仍会正常触发外部传入的onClick处理器onSeek既在片段点击时触发也会在受控currentTime变化时触发设计跳转副作用时需注意这一双重触发语义若项目出现组件未安装成功、/别名解析失败或主题切换不生效等问题可对照 SKILL.md 的 Troubleshooting 一节排查确认在项目根目录执行 CLI、检查components.json、核对tsconfig.json的 paths 配置并确保全局样式文件引入 shadcn/ui 的 Tailwind 基础样式。小结Transcription 组件把AI 转写结果与音频播放交互这两件事解耦得相当干净数据侧只需提供 AI SDK 标准的分段时间戳结构交互侧通过 render props 与onSeek/currentTime两个通道即可与任意播放器双向同步。无论你是在构建会议纪要、播客字幕、课程回放还是语音助手界面都可以直接复用 transcription.tsx 的联动模式在几分钟内交付一套专业、可访问、可深度定制的同步转写体验。【免费下载链接】ZCodeZ.ais coding agent harness. Powerful, intelligent, extensible.项目地址: https://gitcode.com/gh_mirrors/zco/ZCode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考