Documentation Index
Fetch the complete documentation index at: https://sdk.sleepcycle.com/llms.txt
Use this file to discover all available pages before exploring further.
Sleep Cycle SDK - iOS 文档
Sleep Cycle SDK for iOS 让开发者能够将先进的睡眠分析能力集成到他们的应用中。SDK 通过音频和运动传感器提供实时睡眠追踪,并在整夜过程中生成详细的睡眠洞察、睡眠阶段转换以及检测到的事件。
系统要求
最低 iOS 版本:
Swift:
- Swift 版本:5.9+
- SDK 使用 Swift 编写,并提供原生的 Swift API,支持 async/await
Swift Package Manager
使用 Swift Package Manager 将 Sleep Cycle SDK 添加到您的项目:
- 在 Xcode 中选择 File → Add Package Dependencies
- 输入 package URL:
https://github.com/MDLabs/sleepcycle-sdk-swift
- 选择您要使用的版本(语义化版本号)
- 将该 package 添加到您的目标
也可以将其添加到 Package.swift 中:
dependencies: [
.package(url: "https://github.com/MDLabs/sleepcycle-sdk-swift", from: "1.1.0")
]
SDK 需要 API 密钥用于授权。请联系 Sleep Cycle 获取凭证。
前置条件
SDK 需要麦克风权限以进行基于音频的睡眠分析。请将以下内容添加到您的 Info.plist:
<key>NSMicrophoneUsageDescription</key>
<string>We need access to the microphone to analyze your sleep patterns and detect snoring.</string>
如需基于运动的分析,您可能还需要:
<key>NSMotionUsageDescription</key>
<string>We use motion data to track your sleep movements.</string>
后台模式
要确保整夜持续进行睡眠分析,请在应用的 capabilities 中启用相应的后台模式:
- 在 Xcode 中打开您的项目
- 选择应用的 target
- 进入 “Signing & Capabilities”
- 添加 “Background Modes” 能力
- 启用 “Audio”
也可以将以下内容添加到 Info.plist:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
SDK 在睡眠分析期间使用音频后台模式来维持持续的音频处理。您的应用还应实现合适的会话管理,以防止 iOS 挂起分析进程。
通用说明
SDK 是线程安全的,所有异步操作均使用 Swift 并发(async/await)。
初始化 SDK
SDK 在使用前需要进行身份验证。初始化过程会校验您的凭证并确定可用的功能。
import SleepCycleSDK
Task {
do {
let features = try await SleepCycleSdk.initialize(
apiKey: "your-api-key-here"
)
print("Authorized with features: \(features)")
} catch {
print("Initialization error: \(error)")
}
}
返回的 SleepAnalysisFeatures 表示您的 API 密钥可用的能力:
sleepStaging Bool - 睡眠分期分析
smartAlarm Bool - 智能闹钟功能
audioEvents Bool - 音频事件检测
snoringDetection Bool - 鼾声检测
realTimeSleepStaging Bool - 实时睡眠分期
multiChannelAnalysis Bool - 多声道分析(立体声,两个声道)
在运行时访问功能开关:
if SleepCycleSdk.isFeatureEnabled(\.audioEvents) {
// Present snore/talk event UI
}
获取 SDK 状态
通过 AsyncStream 监听 SDK 状态的变化:
import SleepCycleSDK
Task {
for await state in SleepCycleSdk.stateStream {
switch state {
case .uninitialized:
print("SDK not initialized")
case .initialized:
print("SDK ready")
case .running:
print("Analysis in progress")
}
}
}
同步获取当前状态:
let currentState = SleepCycleSdk.currentState
启动睡眠分析会话
初始化完成后,即可启动一次睡眠分析会话。该方法返回标识本次会话的 UUID。
import SleepCycleSDK
Task {
do {
let sessionId: UUID = try await SleepCycleSdk.startAnalysis(
config: SleepAnalysisConfig(
useAudio: true,
useAccelerometer: true
)
)
print("Analysis started with session ID: \(sessionId)")
} catch {
print("Failed to start analysis: \(error)")
}
}
参数:
config SleepAnalysisConfig - 用于指定使用哪些传感器的配置对象
at Date - 分析的起始时间(默认为当前时间)
using DataSource? - 可选的数据源(例如实时或文件回放)
eventListeners [AudioEventListener] - 可选的监听器数组,在音频分析过程中接收回调。可用于实时捕获音频样本和事件
恢复会话
SDK 支持恢复先前启动的分析会话。当应用重启或后台任务被系统终止时,这一功能很有用。
if SleepCycleSdk.isResumePossible() {
try await SleepCycleSdk.resumeAnalysis()
}
停止会话
要停止当前的分析会话并获取结果:
Task {
do {
let result = try await SleepCycleSdk.stopAnalysis()
print("Session ID: \(result.sessionId)")
if let statistics = result.statistics {
print("Total sleep duration: \(statistics.totalSleepDuration ?? 0)")
print("Sleep efficiency: \(statistics.sleepEfficiency ?? 0)")
if let snoreSessions = statistics.snoreSessions {
for session in snoreSessions {
print("Snoring session: \(session.interval)")
}
}
}
for event in result.events {
print("\(event.type) detected: \(event.interval), p=\(event.probability)")
}
for breathingRate in result.breathingRates {
print("Breathing rate: \(breathingRate.bpm) bpm at \(breathingRate.timestamp)")
}
for stageInterval in result.sleepStageIntervals {
print("\(stageInterval.stage): \(stageInterval.interval)")
}
if let audioStats = result.audioStatistics {
for interval in audioStats.healthIntervals {
print("Audio \(interval.status): \(interval.interval)")
}
}
} catch {
print("Failed to stop analysis: \(error)")
}
}
分析结果
AnalysisResult 包含一次睡眠分析会话的完整输出:
sessionId UUID - 唯一会话标识符
startTime Date - 会话起始时间
endTime Date - 会话结束时间
events [Event] - 检测到的睡眠事件
breathingRates [BreathingRate] - 呼吸频率测量值
sleepStageIntervals [SleepStageInterval] - 睡眠阶段数据
statistics SleepStatistics? - 聚合的睡眠统计(可选)
audioStatistics AudioStatistics? - 音频运行状况统计(可选)
SleepStatistics
当存在时,statistics 包含本次睡眠会话的聚合指标:
totalSleepDuration Double? - 总睡眠时长
sleepOnsetLatency Double? - 入睡所用时间
sleepEfficiency Double? - 睡眠时长与在床时长的比值(0.0 到 1.0)
finalWakeTime Date? - 最终醒来时间
numberOfAwakenings Int? - 整夜的醒来次数
snoreTime Double? - 鼾声总时长
snoreSessions [SnoreSession]? - 单次鼾声会话
sleepStageDurations [SleepStage: Double]? - 每个睡眠阶段的时长
AudioStatistics
当存在时,audioStatistics 包含整个会话期间音频输入运行状况的相关信息。
实时事件
SDK 在分析过程中通过 AsyncStream API 提供实时事件更新:
Task {
for await events in SleepCycleSdk.eventStream {
for event in events {
switch event.type {
case .movement:
handleMovement(event)
case .snoring:
handleSnoring(event)
case .talking:
handleTalking(event)
case .coughing:
handleCoughing(event)
}
}
}
}
每个 Event 包含:
type EventType - 事件类型
interval DateInterval - 事件的时间区间
probability Double - 置信度分数(0.0 到 1.0)
source EventSource - 检测来源
sessionId UUID - 该事件所属的会话
signature [Float]? - 可选特征向量(用于鼾声事件)
实时呼吸频率
SDK 在分析过程中提供实时呼吸频率测量:
Task {
for await breathingRate in SleepCycleSdk.breathingRateStream {
print("Breathing rate: \(breathingRate.bpm) bpm (confidence: \(breathingRate.confidence))")
}
}
每个 BreathingRate 包含:
timestamp Date - 测量记录的时间
bpm Double - 呼吸频率(每分钟呼吸次数)
confidence Double - 测量的置信度(0.0 到 1.0)
sessionId UUID - 该测量所属的会话
实时睡眠分期(实验性)
此功能为实验性功能,未来版本中可能会发生变更。API 和行为可能在未通知的情况下被修改。
SDK 可在分析过程中提供实时睡眠阶段预测。此功能要求您的 API 密钥启用了 realTimeSleepStaging 功能。
Task {
for await stageInterval in SleepCycleSdk.sleepStageStream {
switch stageInterval.stage {
case .awake:
print("Awake: \(stageInterval.interval)")
case .light:
print("Light sleep: \(stageInterval.interval)")
case .deep:
print("Deep sleep: \(stageInterval.interval)")
case .rem:
print("REM sleep: \(stageInterval.interval)")
}
}
}
该流在分析过程中大约每 30 秒发出一个 SleepStageInterval 对象,从而以接近实时的方式反馈睡眠状态的转换。
实时音频运行状况
SDK 在分析期间监测音频输入的运行状况,并在状态变化时发出更新:
Task {
for await update in SleepCycleSdk.audioHealthStream {
switch update.status {
case .healthy:
print("Audio input healthy")
case .flatline:
print("Audio flatline detected")
case .missingInput:
print("Audio input missing")
}
}
}
AudioHealthStatus 取值:
.healthy - 音频输入包含有变化的信号
.flatline - 检测到恒定值(麦克风失效或输入静音)
.missingInput - 较长时间内未收到任何音频输入
事件签名
对于鼾声事件,Event.signature 属性包含一个 16 维特征向量,表示所检测到鼾声的独特特征。来自同一人的鼾声事件在签名空间中彼此聚集,因此可以按人对事件进行聚类。
音频事件监听器
AudioEventListener 协议允许您在会话过程中接收实时的音频分析更新。实现该协议可在分析进行时访问原始音频样本、事件检测以及音量信息。
class MyAudioListener: AudioEventListener {
func onAudioAnalysisBatchCompleted(
sessionId: UUID,
audioSamples: [Float],
audioSampleRate: Int,
audioStartTime: Date,
audioEndTime: Date,
eventsStarted: [EventStartedInfo],
eventsEnded: [EventEndedInfo],
rms: [Float]
) {
// Process audio samples and events
}
}
let listener = MyAudioListener()
try await SleepCycleSdk.startAnalysis(
config: SleepAnalysisConfig(useAudio: true),
eventListeners: [listener]
)
audioSamples 参数顺序包含所有已处理的音频数据,批次之间没有间隙或重叠。每个批次都从前一个批次结束的位置精确接续,从而对所有分析过的音频实现完整覆盖。
音频片段
当检测到特定的睡眠事件(例如鼾声、梦话或咳嗽)时,SDK 可以捕获短音频录音。
使用 AudioClipsConfig 和 AudioClipsReceiver 创建一个 AudioEventListener:
import SleepCycleSDK
let listener = SleepCycleSdk.createAudioClipsProducer(
audioClipsConfig: AudioClipsConfig(
activeTypes: [
.snoring: EventTypeConfig(minDuration: 0.5),
.talking: EventTypeConfig(minDuration: 0.5)
],
clipLength: 5.0
),
receiver: MyAudioHandler()
)
try await SleepCycleSdk.startAnalysis(
config: SleepAnalysisConfig(useAudio: true),
eventListeners: [listener]
)
每个 AudioClip 包含:
startTime Date - 起始时间戳
type EventType - 触发本次捕获的事件类型
samples [Float] - 原始音频样本
sampleRate Int - 采样率(Hz)
sessionId UUID - 该片段所属的会话
多声道分析
SDK 支持使用立体声音频源同时分析两个声道。多声道分析将数据源生命周期与各个会话生命周期分离,使您可以独立启动和停止每个声道上的会话。
立体声流应来自两个独立的单声道麦克风,每个麦克风占用一个声道,再合并为单个立体声流。
此功能要求您的 API 密钥启用了 multiChannelAnalysis 功能。
声道分离
使用立体声输入时,ChannelSeparationConfig 控制如何将音频事件分配到各个声道。内置预设:
.bedSideMics — 分离放置的床头麦克风(默认值)
.centeredMicArray — 间距很近的麦克风阵列
.detectionStrengthOnly() — 不进行空间过滤,仅依据检测置信度
所有参数(麦克风间距、模糊区、置信度阈值、各事件类型设置)都可以单独调节,以适配您的具体硬件配置和使用场景。
数据源生命周期
在启动各个会话之前,使用立体声音频配置启动数据源:
import SleepCycleSDK
let dataSource = SleepCycleSdk.createLiveDataSource()
try await SleepCycleSdk.startDataSource(
using: dataSource,
channelSeparationConfig: .bedSideMics
)
在每个声道上启动会话
数据源运行后,在每个声道上启动一个会话:
let primarySessionId: UUID = try await SleepCycleSdk.startAnalysis(
channel: .primary,
config: SleepAnalysisConfig(useAudio: true, useAccelerometer: true)
)
let secondarySessionId: UUID = try await SleepCycleSdk.startAnalysis(
channel: .secondary,
config: SleepAnalysisConfig(useAudio: true, useAccelerometer: false)
)
AnalysisChannel 取值:
.primary - 第一个音频声道(或单声道)
.secondary - 立体声中的第二个音频声道
独立停止各个会话
每个会话都可以独立停止以获取其结果:
let primaryResult = try await SleepCycleSdk.stopAnalysis(channel: .primary)
let secondaryResult = try await SleepCycleSdk.stopAnalysis(channel: .secondary)
停止数据源
所有会话都已停止后,再停止数据源:
await SleepCycleSdk.stopDataSource()
如果在仍有会话处于活动状态时调用 stopDataSource(),会强制停止这些会话并丢弃其结果。要保留结果,请先停止每个会话。