Omi Swift SDK 接入实战:iOS/macOS 端设备连接与本地 Whisper / 流式 Deepgram 实时转写 📅 发布时间:2026/9/17 8:23:06 👁 浏览次数: Omi Swift SDK 接入实战iOS/macOS 端设备连接与本地 Whisper / 流式 Deepgram 实时转写【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend本文围绕开源仓库 FriendOmi中 Swift SDK 官方文档 展开系统讲解如何在 iOS/macOS 应用中通过 Swift Package 连接 Omi 智能穿戴设备从零配置的本地 Whisper 转写快速上手到OmiManager全部公开方法逐项剖析再到基于 WebSocket 的 Deepgram / Parakeet 流式语音识别接入。读完本文你将掌握该 SDK 的完整调用链、BLE 数据流底层原理与可复用的 Swift 代码模板能够直接在 Xcode 工程中落地设备连接 实时转写功能。一、SDK 概览包定位与适用场景Swift SDK 是一个开箱即用的 Swift Packageswift-tools-version支持 SPM 集成专为 iOS/macOS 客户端连接 Omi 系列设备而设计。其核心卖点有三原生 iOS/macOS 支持基于CoreBluetooth实现 BLE 通信无跨平台桥接层本地转写默认使用随包捆绑的 Whisper 模型ggml-tiny.en在设备端完成语音转写无需任何云 API 和网络请求简洁 API对外仅暴露一个OmiManager门面类几分钟即可完成连接与转写。从仓库目录结构看包内主要分为两大部分模块目录职责设备通信sdks/swift/Sources/omi-lib/helpersBLE 扫描/连接、Friend 设备协议、录音与编解码、数据包处理语音识别sdks/swift/Sources/omi-lib/STTWhisper本地离线、Deepgram云端流式、Parakeet自托管流式三种引擎另外包内还随附了ggml-tiny.en.bin模型文件Resources 目录与 Deepgram 转写器的单元测试DeepgramTranscriberTests.swift便于开发者验证和二次开发。二、快速开始2 分钟跑通设备连接与本地转写1. 替换 ViewController 完整代码按官方文档指引将你工程中的ViewController.swift整体替换为如下代码该示例无 UI转写结果直接打印到 Xcode 控制台import UIKit import omi_lib class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.lookForDevice() } func lookForDevice() { OmiManager.startScan { device, error in print(starting scan) if let device device { print(got device , device) self.connectToOmiDevice(device: device) OmiManager.endScan() } } } func connectToOmiDevice(device: Device) { OmiManager.connectToDevice(device: device) self.listenToLiveTranscript(device: device) self.reconnectIfDisconnects() } func reconnectIfDisconnects() { OmiManager.connectionUpdated { connected in if connected false { self.lookForDevice() } } } func listenToLiveTranscript(device: Device) { OmiManager.getLiveTranscription(device: device) { transcription in print(transcription:, transcription ?? no transcription) } } }这段代码覆盖了 SDK 使用的四个关键步骤扫描发现设备startScan→建立连接connectToDevice→订阅实时转写getLiveTranscription→监听断线并自动重连connectionUpdated。其中connectionUpdated返回false时重新发起扫描是实际部署中保证连接稳健性的推荐模式。2. 构建运行前置条件运行前必须满足以下三点缺一不可选择你的开发团队Signing Capabilities 中设置 Team真机运行必须有开发者签名使用真机连接 iPhone官方文档明确说明模拟器不支持蓝牙simulators dont support Bluetooth因此 BLE 扫描、连接、音频传输都必须在物理设备上验证Run 工程将 App 安装到手机。3. 验证开机、自动连接、说话看日志打开你的 Omi 设备电源启动 App程序会自动扫描并连接设备对着设备说话转写文本会实时出现在 Xcode 控制台print(transcription:, ...)的输出。注意本示例没有任何 UI转写结果只出现在 Xcode 日志中如需界面展示可在getLiveTranscription回调中自行刷新 UILabel 或 SwiftUI 视图。三、OmiManager 公共 API 一览与方法逐项说明官方文档给出了OmiManager的六个核心方法全部为static方法可在任意位置直接调用方法说明startScan(callback)开始扫描 Omi 设备endScan()停止扫描connectToDevice(device)连接已发现的设备connectionUpdated(callback)监听连接状态变化getLiveTranscription(device, callback)接收实时转写文本getLiveAudio(device, callback)接收音频文件 URL结合门面实现源码omi_lib.swift可以进一步看清每个方法的底层行为startScan(completion:)内部将回调透传给单例FriendManager并在seen_devices数组中按设备 UUID 去重避免重复回调同一个设备Device结构体仅暴露id: String字段给上层connectToDevice(device:)会先在上层seen_devices中按id找回内部Friend对象再调用FriendManager.connectToDevice因此连接前必须先完成扫描getLiveAudio(device:)实际映射到内部getRawAudio与转写共用同一条 BLE 音频链路只是输出为音频文件 URL 而非文本。底层实现8 秒轮询、临时文件与 44 字节 WAV 头从 FriendManager.swift 的实现看实时转写实际是定时器驱动的准实时轮询getLiveTranscription用Timer.scheduledTimer(withTimeInterval: 8.0, repeats: true)每8 秒取出当前录音文件调用resetRecording()重置录音再交给本地 Whisper 转写getRawAudio同样以 8 秒为周期产出音频块但有一个关键细节录音文件会先被复制到临时目录然后才调用resetRecording()因为resetRecording()会删除原文件。复制得到的 WAV 文件头可能显示 0 字节音频数据文件仍在写入中但 44 字节头部之后实际存在完整的 PCM 数据——代码中正是通过fileSize 44来判断音频块是否有效见 FriendManager.swift。这意味着如果你的应用对延迟有更高要求可以自行缩短轮询间隔或改用下面的流式 STT 方案。四、设备发现与 BLE 链路解析源码级扫描过滤三种设备名扫描器在centralManager(_:didDiscover:...)回调中按广播名过滤外设仅接受以下名称见 BLEManager 相关扩展Friend Friend DevKit 2 Omi DevKit 2也就是说Omi 正式版与 DevKit 开发板都能被 SDK 识别。扫描使用CBCentralManagerScanOptionAllowDuplicatesKey: false避免重复回调并在centralManagerDidUpdateState中等待蓝牙poweredOn后才开始扫描。BLE 服务与特征 UUIDFriend设备的通信协议定义在 helpers/Friend.swift核心 UUID 如下用途UUID音频服务19B10000-E8F2-537E-4F6C-D104768A1214音频数据特征19B10001-E8F2-537E-4F6C-D104768A1214音频编解码器特征19B10002-E8F2-537E-4F6C-D104768A1214灯效编解码器特征19B10003-E8F2-537E-4F6C-D104768A1214音频数据包的解析逻辑为前 2 字节是小端UInt16包序号配合PacketCounter做丢包检测第 3 字节是分片索引其后才是音频负载只有index 0的包才触发录音缓冲刷新避免分片内容被拆散。编解码与连接状态机设备通过编解码器特征上报音频格式FriendCodec枚举支持pcm1616 kHz PCM/pcm88 kHz PCMµLaw16/µLaw816 kHz / 8 kHz μ-Lawopus1616 kHz Opus见 Friend.swiftBLEManager维护了完整的连接状态机off / on / scanning / connecting / connected / linked / disconnected并在didDisconnectPeripheral时回调lostConnection()——这正是上层connectionUpdated(false)触发重连的链路来源见 BLEManager.swift。从源码结构看connected → linked的转变发生在按服务 UUID 匹配到已注册的可穿戴设备类型之后SDK 通过WearableDeviceRegistry实现设备类型注册与实例化。五、流式 STTDeepgram 实时转写当需要真正的低延迟流式转写而不是 8 秒轮询时SDK 提供了基于 WebSocket 的 Deepgram 引擎。方式一通过工厂方法 OmiSttFactoryimport omi_lib // Via OmiSttFactory let transcriber try OmiSttFactory.makeStreaming( engine: .deepgram, deepgramAPIKey: YOUR_DEEPGRAM_API_KEY, deepgramModel: nova-2, deepgramLanguage: es, // e.g. en-US, es, fr, ja onTranscript: { text in print(Transcript: \(text)) } )方式二直接实例化 OmiDeepgramTranscriber// Or directly with OmiDeepgramTranscriber let deepgram OmiDeepgramTranscriber( apiKey: YOUR_DEEPGRAM_API_KEY, sampleRate: 16000, model: nova-2, language: es, onTranscript: { text in print(Transcript: \(text)) } ) // Send PCM audio data deepgram.appendPcm(pcmData) // Disconnect when done deepgram.stop()工厂方法的默认参数为deepgramModel nova、deepgramLanguage en-US、sampleRate 16000见 SttFactory.swift。OmiStreamingTranscriber协议只要求两个方法——appendPcm(_ data: Data)推送 PCM16 LE 单声道 16 kHz 数据与stop()统一了各引擎的调用方式见 SttEngine.swift。WebSocket 协议细节与测试验证从 DeepgramTranscriber.swift 的实现看客户端会向wss://api.deepgram.com/v1/listen发起 WebSocket 连接并携带以下查询参数参数值说明punctuatetrue自动加标点model可配置默认novaDeepgram 模型版本language可配置默认en-US识别语言encodinglinear16线性 PCM 编码sample_rate默认16000采样率channels1单声道认证方式为 HTTP 头Authorization: Token API_KEY。接收循环持续解析服务端返回的 JSON从channel.alternatives[0].transcript中提取文本并回调onTranscriptappendPcm在私有串行队列中执行以保证数据顺序stop()以goingAway关闭码断开连接。这些行为均有单元测试背书DeepgramTranscriberTests.swift 验证了默认参数nova/en-US/16000/linear16/channels1、自定义参数nova-2/de/ 8000 Hz以及多语言场景nova-2-general/ja并断言了工厂方法在 API Key 缺失或为空时抛出omi.stt域、code 为 2 的错误。六、其他转写引擎Parakeet 与本地 WhisperParakeet自托管 NVIDIA 引擎OmiParakeetTranscriber面向自托管的 Parakeet 推理服务。其内部会把传入的 HTTP(S) base URL 自动转换为 WebSocket 地址https://→wss://http://→ws://并拼接/v3/stream?sample_rate16000端点。握手阶段服务端返回{type:ready}后客户端才开始推送音频stop()时先发送finalize字符串再断开以保证最终结果落盘见 ParakeetTranscriber.swift。其 API URL 可通过工厂方法的parakeetAPIURL参数传入默认读取环境变量HOSTED_PARAKEET_API_URL若该值为空工厂会抛出omi.stt域、code 为 3 的错误。Whisper设备端离线除FriendManager内置的 8 秒轮询转写外SDK 还提供了独立的OmiWhisperTranscriber见 WhisperTranscriber.swift它默认从包内加载ggml-tiny.en模型接受[Float]PCM 帧数组await异步返回拼接后的识别文本。注意工厂方法对engine: .whisper会直接抛错code 4提示流式 Whisper 请走getLiveTranscription路径——即Whisper 是离线、面向文件/帧的引擎Deepgram / Parakeet 才是流式引擎。引擎选择建议场景推荐引擎理由最快上手、零云成本、离线可用WhispergetLiveTranscription模型内置无需网络与密钥低延迟流式转写、多语言、可调模型DeepgramWebSocket 流式nova-2等模型可选数据不出内网、自建推理服务Parakeet对接自托管/v3/stream服务七、常见错误与排查现象可能原因处理方式收不到转写文本使用模拟器运行改用真机模拟器不支持蓝牙startScan无回调设备未开机或蓝牙未授权打开 Omi 设备电源检查系统蓝牙权限Info.plist中NSBluetoothAlwaysUsageDescriptionmakeStreaming(.deepgram)抛错 code 2未传或传空deepgramAPIKey配置有效密钥makeStreaming(.parakeet)抛错 code 3HOSTED_PARAKEET_API_URL为空设置环境变量或显式传parakeetAPIURLmakeStreaming(.whisper)抛错 code 4误用工厂创建流式 Whisper改用getLiveTranscription或OmiWhisperTranscriber转写中断、自动重连BLE 意外断开确认已实现connectionUpdated回调中的重扫逻辑音频文件异常文件仍在写入、WAV 头为 0 字节参考getRawAudio的 44 字节头部判断与临时文件复制策略八、相关资源Swift SDK 官方文档sdks/swift/README.md公共 API 门面实现sdks/swift/Sources/omi-lib/omi_lib.swift内部连接与转写核心sdks/swift/Sources/omi-lib/FriendManager.swiftSTT 引擎工厂与协议sdks/swift/Sources/omi-lib/STT/SttFactory.swift、sdks/swift/Sources/omi-lib/STT/SttEngine.swiftDeepgram / Parakeet / Whisper 转写器DeepgramTranscriber.swift、ParakeetTranscriber.swift、WhisperTranscriber.swiftBLE 协议与设备模型helpers/Friend.swift、helpers/BLEManager.swift单元测试示例sdks/swift/Tests/omi-libTests/DeepgramTranscriberTests.swift需要说明的是本指南基于当前仓库中 Swift SDK 的既有实现整理而成具体参数如默认模型nova、轮询间隔 8 秒以仓库源码为准接入时若 SDK 版本更新请以最新源码与文档为准。【免费下载链接】FriendAI that sees your screen, listens to your conversations and tells you what to do项目地址: https://gitcode.com/GitHub_Trending/fr/Friend创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考