pi- 音频
语音约束 毕:语音相通,文字相通和实时语音相通,以pi自有风格. 用于 pi-coding- 代理插件和 塑料剂。 。 。 .
npm install @ai-ecoverse/pi-audio
一个用于节点24和较新的TypeScript ES模块库,以及浏览器.
| 端点 | 需求 | 用于 |
|---|---|---|
@earendil-works/pi-ai | 对 | 所有的东西 |
@earendil-works/pi-durable | 选项 | ./durable |
node-web-audio-api 或者说 web-audio-api | 选项 | 节点音频输出( N)openNodeAudio(中文(简体) ) |
@ai-ecoverse/wasm-webrtc-audio-processing | 选项 | ./webrtc-aec |
跟经纪人谈的三种方式
- 声入人心. 供养者为耳口;皮剂为脑. 语音变成
UserMessage,代理运行一个正常的转弯, 并且只有它的最后一个答案是说话。 使用任何语音对文本和TTS适配器。 见voiceTurns。 。 。 . - 实时. 一个语音对语音模型(OpenAI Realtime,xAI Voice,双子座活语)将对话作为 说话者派探员是 思想家 在一个工具后面,
ask_agent。见connectRealtime财务报告和审定财务报表bindThinker。 。 。 . - 主办级联. 11Labs代理商和Fish音频代理商在自己的服务器上运行语音对文本,一个LLM和TTS,并插入同一个实时会话和谈话者/思维者绑定. 他们的谈话者LLM可以是卖家模型或
CustomLlm: 任何OpenAI相容的端点,与pi自己的模型字段相描述(baseUrl, (中文(简体) ),id, (中文(简体) ),api, (中文(简体) ),headers) (中文(简体) ).
模型和适配器
翻译、演讲和实时模型都加入Pi-ai的 ModelTypeMap 通过声明合并。 他们不是聊天模式,所以Pi's Models.getAllModels() 没有列出他们。 pi-audio保留自己的目录: registerVoiceModel, (中文(简体) ), getVoiceModel(type, provider, id) 财务报告和审定财务报表 listVoiceModels。 。 。 . resolveVoiceAuth(models, voiceModel) 重新使用证书 pi 已经为供应商存储.
每个适配器都是它自己的子路径,在调用它之前什么也没有登记 register* 函数,该函数返回未注册的函数.
| 子路径 | 登记册 | 提供 |
|---|---|---|
./openai | registerOpenAI | OpenAI和OpenRouter 转录(批发和流传)和演讲 |
./xai | registerXAI, (中文(简体) ), registerXaiRealtime | xAI 语音对文本和 TTS( 批量和流线); xAI 语音实时 |
./elevenlabs | registerElevenLabs | 复制文本(批次和实时),字符对齐的 TTS |
./mistral | registerMistral | Voxtral 转录(批和实时),Voxtral TTS |
./fish | registerFish | 语音记录和TTS |
./google | registerGoogle | 双子座TTS |
./cloudflare | registerCloudflare | 工人 AI: Deepgram Flux, Nova-3和Aura, Whisper, MeloTTS |
./wavespeed | registerWaveSpeed | Batch Whisper和MiniMax的演讲(不是现场语音) |
./openai-realtime | registerOpenAIRealtime | gpt-realtime-2, (中文(简体) ), gpt-realtime-2.1 |
./gemini-live | registerGeminiLive | 双子座直播( E)gemini-3.8-live (a/conf.96/11,第5段) |
./elevenlabs-agents | registerElevenLabsAgents | 11Labs代理级, provisionAgent, (中文(简体) ), elevenLabsCustomLlm |
./fish-agents | registerFishAgents | 鱼类音频代理级联(通过LiveKit的WebRTC), provisionAgent, (中文(简体) ), fishCustomLlm |
./brain | —— 说 | chatCompletionsBrain后置 pi 代理服务器 CustomLlm 網址 |
./durable | —— 说 | appendVoiceTruncate 用于可持久主机 |
./webrtc-aec | —— 说 | WebRTC AEC3 回声取消器 echo.mode: "wasm" |
./worklet | registerAudioConvertWorklet | 音频工作文件夹中的格式转换 |
./faux | registerFaux* | 用于测试的脚本、语音和实时适配器 |
模型能力是模型上的字段: streaming, (中文(简体) ), turnDetection (单位:千美元)none, (中文(简体) ), vad 或者说 semantic, (中文(简体) ), textStreaming, (中文(简体) ), inputFormats 编号 : outputFormats 财务报告和审定财务报表 voices,用于实时模型 toolCalls (单位:千美元)blocking 或者说 async, (中文(简体) ), delivery, (中文(简体) ), truncation 财务报告和审定财务报表 transports。读取这些旗帜而不是检查提供者名称。 价格是每个模型的 audioCost。 。 。 .
语音对文本和 TTS
import { getVoiceModel, speak, transcribe } from '@ai-ecoverse/pi-audio';
import { registerOpenAI } from '@ai-ecoverse/pi-audio/openai';
registerOpenAI();
const ears = getVoiceModel('transcription', 'openai', 'gpt-4o-transcribe');
const mouth = getVoiceModel('speech', 'openai', 'gpt-4o-mini-tts');
const heard = await transcribe(ears, { data: wavBytes, mimeType: 'audio/wav' }, { apiKey });
for await (const event of speak(mouth, { text: heard.text, voice: 'alloy' }, { apiKey })) {
if (event.type === 'audio') play(event.chunk);
}
transcribe是批量的.listen(model, audio)溪流speech_start, (中文(简体) ),partial, (中文(简体) ),final财务报告和审定财务报表turn_end事件,一个turn_end每个用户转弯。 当一个模型没有 自己的转弯检测,listen结尾随局部语音活性检测而转向.speak取一个字符串或一个AsyncIterable<string>,所以语音可以从代理的第一句开始. 当一个模型无法接收流出文本时,speak每句发送一个请求.- 音频是二进制
AudioChunks (单位:千美元)Uint8Array加一个AudioFormat) (中文(简体) ).convertAudio财务报告和审定财务报表convertAudioSource转换为PCM16,浮32,G.711 μ-law和A-law,通道计数,样本率和PCM16 WAV. Opus,MP3和FLAC仅在不需要转换时通过.
声音转动
import { listen, speak, voiceTurns } from '@ai-ecoverse/pi-audio';
const options = { ears, mouth, voice: 'alloy', bargeIn: 'onWords' };
const session = voiceTurns({ listen, speak }, conversation, mic, out, options, signal);
for await (const caption of session.captions) render(caption);
主机执行 VoiceConversation数字 : prompt(message, meta, signal) 运行一个 pi 转弯并生成 pi-可持久形状的代理事件,以及 truncate(cut) 记录了一个驳船.
- 口语文字. 只讲最后的答案。 思考、评论和工具呼吁保持沉默,除非
announce(call)返回短行. - 贝吉入. 模式为
interrupt, (中文(简体) ),onWords(仅在转写后返回单词),ignore财务报告和审定财务报表auto(随回声校正. 中断会中止转弯和演讲,然后将回复切换到用户听到的. 和Pi -Duble, 一起,appendVoiceTruncate从./durable附录avoice.truncate条目,其上下文编辑以已听到的文本取代助理消息并保留其工具调用。 所储存的条目没有变化,因此UI仍然有完整的回复. - 说明.
session.captions溪流user_partial编号 :user_final, (中文(简体) ),agent_generated(声入人心),agent_spoken(按实际播放,TTS返回对齐时每个字符)和agent_cut。 。 。 .captionsFromHistory(entries)重新装入后重建它们. - 声景. 过
soundscape还有一个AudioOut(一出输出上被口音和床相混合)在思考和工具暂停时播放音乐,气氛或滴答.followBed等待时间graceMs在开始循环之前,保持它横跨有链条的工具呼叫,在语音和用户交谈时将其遮住.session.phases揭露了UI的相同听觉,思维,工具和发言状态.
实时
import {
askAgent,
bindThinker,
connectRealtime,
getVoiceModel,
mintRealtimeToken,
} from '@ai-ecoverse/pi-audio';
import { registerOpenAIRealtime } from '@ai-ecoverse/pi-audio/openai-realtime';
registerOpenAIRealtime();
const model = getVoiceModel('realtime', 'openai', 'gpt-realtime-2');
const context = { instructions, tools: [askAgent, readTool], voice: 'marin' };
const token = await mintRealtimeToken(model, context, { apiKey });
const session = await connectRealtime(model, context, { token });
await bindThinker(session, thinker, runDirectTool, {
progress: 'silent',
result: 'when_idle',
ack: 'On it.',
directTimeoutMs: 3000,
directMaxChars: 4000,
});
- 说客工具. 说话的人得到
ask_agent财务报告和审定财务报表read(单位:千美元)talkerTools) (中文(简体) ). 主机执行Thinker,则运行在后面ask_agent,直接read工具. - 送货. 将文字推入活语音使用一个词汇:
interrupt, (中文(简体) ),when_idle或者说silent双子座 Live 将它本土化地映射到其工具列表中. 关于封堵模型(OpenAI, xAI, 双子座 3.1 Flash Live),bindThinker承认ask_agent立即输入结果. - 断取. 登船时,
interrupt({ itemId, heardMs })将提供者的上下文切入所听到的内容:conversation.item.truncate在OpenAI和xAI上进行. 双子座没有短线呼叫. - 浏览器 auth.
mintRealtimeToken运行 API 密钥的住址并返回短寿命{ value, expiresAt, model, url? }覆盖 OpenAI 和 xAI 客户端秘密、 双子受限验证符、 11Labs 签名 URL 和 Fish LiveKit 会话. - Cloudflare AI Gateway. (原始内容存档于2018-09-29). 过
gateway改为connectRealtime通过网关运行同一协议. - 会议. 双子座直播重新连接
goAway并使用滑动窗口上下文压缩.RealtimeLedger每个会话的米数,和close()返回其定价使用.
回声取消
背景床,和说话者自己的声音,漏入麦克风并引起假驳船入内. EchoControl 决定取消地点 :
browser数字 :getUserMedia({ echoCancellation: true }),通过本地的WebRTC回放回放,所以Chrome使用回放作为回放参考.wasm: 已注射EchoCanceller由麦克风和AudioOut.reference。 。 。 ../webrtc-aec提供基于 WebRTC AEC3 的:createWebRtcEcho({ wasm, sampleRate })用于您编译的模块(在音频工作室工作),以及createNodeWebRtcEcho({ sampleRate })在节点上.none:用于耳机.
calibrateEcho(out, mic, probe, durationMs, signal, canceller?) 进行探测 测量延迟和剩余泄漏 interrupt, (中文(简体) ), onWords 或者说 headphones。给予它至少3秒:AEC3在一秒内去除出漏出,但其报告的取消只在大约3秒的音频后才解决.
节点
openNodeAudio({ sink: 'none' }) 打开一个 AudioContext 在节点上 node-web-audio-api,或纯JS web-audio-api 作为倒计时器,在没有音频设备的机器上工作. openMixer(context) 在您已有的上下文上建立同样的演讲和床位图 。 在节点上:
- 回声模式是
wasm或者说none,而回放是普通的Web Audio(没有WebRTC回放); - 主机提供麦克风作为
AudioSource· ; - pi -audio的活体释放出来
bindWorkletNode,因为返回false不停止处理器进入node-web-audio-api。 。 。 .
使用和定价
一个语音呼叫报告 Pi -ai Usage 带有可选 audio 字段 (inputSeconds, (中文(简体) ), outputSeconds, (中文(简体) ), characters, (中文(简体) ), textMessages) (中文(简体) ). 托肯计数器保持0,美元成本进入现有的 cost 字段,从模型中计价 audioCost 以 priceAudio。 。 。 .
长相 addUsage 合并一个固定的字段列表并减少 audio。一个主机通过 pi-可扩展补丁汇总语音使用量,也可以调用 addAudioCounters数字 :
if (usage.reasoning !== undefined) total.reasoning = (total.reasoning ?? 0) + usage.reasoning;
addAudioCounters(total, usage);
pi -adio不应用该补丁本身。 诸如斯莱克特工之类的主机在他们的 patches/patches.json。 。 。 .
测试
@ai-ecoverse/pi-audio/faux 注册脚本适配器 : registerFauxTranscription, (中文(简体) ), registerFauxSpeech 财务报告和审定财务报表 registerFauxRealtime每个返回 { model, unregister, calls, … },因此测试可以脚本事件并检查发送的内容. 使用一个独特的 api 每个测试和呼叫 unregister()。导入 ./faux 没有注册,根包不会导入它.
发展
npm ci
npm run lint
npm test
npm run lint运行 斯克林特语name: Biome,类型检查,无评论规则,没有单位测试用git,以及AGENTS.md限制. 左勾拳在每次犯案前都会进行同样的检查.npm test正在建设dist/并运行整合测试test/integration/。测试从不调用真实的语音或 LLM 提供者;适配器使用记录的固定装置进行测试.- 单位测试现场直播
test/unit/运行npm run test:unit。 。 。 .
释放
CI是一个工作流程, .github/workflows/ci.yml,该调用 塑料-共享网络管道: 在每一个事件上都涂入了集成测试和Claude,以及在拉出请求时进行Codex审查,合并队列中再次进行集成测试. 每一次推动 main 然后运行语义发布,读取常规承诺消息,标记版本,通过信任的出版(OIDC)发布到npm ci.yml写着GitHub版 没有从分支或膝上型电脑上发布任何信息.
许可证
阿帕奇 - 2.0