Skip to content

Ti 云存 iOS API 参考

本文列出 iOS 与 macOS 中 Ti 云存和通用 Media 的公开 API、返回结果和行为约定。第一次接入时,建议先阅读 Ti 云存 API 总览

同步方法返回 Int32 错误码,TiCloudStorageErrorCode.ok 表示当前调用成功。Swift 的一次性异步操作使用 async,Objective-C 使用 completion;两者都只返回一个终局。需要业务分支处理的错误通过 TiCloudStorageErrorCode 提供公开常量;完整含义和处理建议见错误码TiCloudStorage.errorToString(_:) 只用于展示或诊断。

基础类型

swift
@objcMembers public final class TiCloudStorageRecordingRange: NSObject {
    public let startTimeMs: Int64
    public let endTimeMs: Int64

    public init(
        startTimeMs: Int64,
        endTimeMs: Int64
    )
}

@objcMembers public final class TiCloudStorageRecordingRangesResult: NSObject {
    public let code: Int32
    public let recordings: [TiCloudStorageRecordingRange]
}

@objc public enum TiCloudStorageReplaySpeed: Int {
    case x0_125 = 6
    case x0_25 = 5
    case x0_5 = 4
    case x1 = 0
    case x2 = 1
    case x4 = 2
    case x8 = 3
}

TiCloudStorageRecordingRange

字段说明
startTimeMs录像可用时间段的开始时间,UTC Unix 毫秒
endTimeMs录像可用时间段的结束时间,UTC Unix 毫秒;必须晚于 startTimeMs

TiCloudStorageRecordingRangesResult

字段说明
codeList 的最终错误码
recordings查询得到的录像可用时间段;成功但没有录像时为空数组

TiCloudStorageRecordingDayTiCloudStorageRecordingDaysResult

类型或字段说明
TiCloudStorageRecordingDay.date严格 YYYY-MM-DD 日期
TiCloudStorageRecordingDay.hasRecording该自然日至少有一个当前可见录像时点时为 true
TiCloudStorageRecordingDaysResult.code日期查询的最终错误码
TiCloudStorageRecordingDaysResult.days完整、按日期升序的逐日结果

TiCloudStorageReplaySpeed

枚举值说明
.x0_1251/8 倍速,视频慢放,音频静音
.x0_251/4 倍速,视频慢放,音频静音
.x0_51/2 倍速,视频慢放,音频静音
.x11 倍速,播放音频和视频
.x22 倍速,视频播放,音频静音
.x44 倍速,视频播放,音频静音
.x88 倍速,视频播放,音频静音

NSNumber? 用于向 Objective-C 表达可空整数。

使用可用时间段开始回放

selectedRecording 是从 listRecordings 返回结果中选择的一段录像。下面只展示正常调用顺序;回放期间保持 replayvideoOutputaudioOutput 有效。

swift
guard TiCloudStorage.initialize(appId: appId)
        == TiCloudStorageErrorCode.ok else { return }

let cloudStorage = TiCloudStorage(token: token)
let replay = cloudStorage.createReplay()
let videoOutput = TiCloudStorageVideoOutput()
let audioOutput = TiCloudStorageAudioOutput()
replay.onError = showReplayError
replay.onCompleted = showReplayCompleted

videoOutput.attachView(videoView)
videoOutput.attach(replay: replay, channelId: videoChannelId)
audioOutput.attach(replay: replay, channelId: audioChannelId)

replay.play(
    startTimeMs: selectedRecording.startTimeMs,
    endTimeMs: selectedRecording.endTimeMs
)

同步方法返回非 TiCloudStorageErrorCode.ok 时,当前操作没有生效。通过两个 Output 的状态和 delegate 更新播放界面;Token、网络或录像读取失败时,在 Replay 的错误回调中处理。

页面退出时,先停止 Replay,detach 两个 Output,并调用 videoOutput.detachView()。随后依次 dispose Output 和 Replay。不再访问这台设备时 dispose cloudStorage;应用不再使用 Ti 云存时,最后调用 TiCloudStorage.shutdown()

TiCloudStorage

swift
@objcMembers public final class TiCloudStorage: NSObject {
    public static func initialize(appId: String) -> Int32

    public static func initialize(
        appId: String,
        endpoint: String,
        consoleLogEnabled: Bool
    ) -> Int32

    public static func shutdown() -> Int32

    public static func errorToString(_ code: Int32) -> String

    public init(token: String)

    public func updateToken(_ token: String) -> Int32

    @MainActor @nonobjc public func listRecordingDays(
        startDate: String,
        endDate: String,
        timeZoneId: String = "Asia/Shanghai"
    ) async -> TiCloudStorageRecordingDaysResult

    @objc(listRecordingDaysWithStartDate:endDate:completion:)
    @MainActor public func listRecordingDaysForObjectiveC(
        startDate: String,
        endDate: String,
        completion: @escaping @MainActor @Sendable (TiCloudStorageRecordingDaysResult) -> Void
    )

    @objc(listRecordingDaysWithStartDate:endDate:timeZoneId:completion:)
    @MainActor public func listRecordingDaysForObjectiveC(
        startDate: String,
        endDate: String,
        timeZoneId: String,
        completion: @escaping @MainActor @Sendable (TiCloudStorageRecordingDaysResult) -> Void
    )

    @MainActor @nonobjc public func listRecordings(
        startTimeMs: Int64,
        endTimeMs: Int64
    ) async -> TiCloudStorageRecordingRangesResult

    @objc(listRecordingsWithStartTimeMs:endTimeMs:completion:)
    @MainActor public func listRecordingsForObjectiveC(
        startTimeMs: Int64,
        endTimeMs: Int64,
        completion: @escaping @MainActor @Sendable (TiCloudStorageRecordingRangesResult) -> Void
    )

    public func createReplay() -> TiCloudStorageReplay

    public func exportRecording(
        _ request: TiCloudStorageExportRequest,
        progress: ((Double) -> Void)?,
        completion: @escaping (TiCloudStorageRecordingResult) -> Void
    ) -> TiCloudStorageExportTaskStartResult

    public func dispose() -> Int32
}

使用任何 Ti 云存 API 前先调用 TiCloudStorage.initialize(appId:)。初始化后用一台设备的非空 Token 创建 TiCloudStorage 实例;构造不发起网络请求。同时访问多台设备时创建多个实例。释放全部 TiCloudStorage 实例、Replay、Output 和任务后调用 TiCloudStorage.shutdown()

TiRTC 与 Ti 云存可以在同一进程共存,两者可以使用不同的 App ID 和 endpoint。SDK 从 NSCachesDirectory/tirtc 解析出的工作根目录和 consoleLogEnabled 由两者共享,因此配置必须一致。Runtime 在该目录下管理日志、日志归档和临时媒体文件。初始化第二项服务不会重启 Runtime;共享配置不一致时返回 already-initialized,已初始化的服务不受影响。调用 TiCloudStorage.shutdown() 不会停止 TiRTC。

TiCloudStorage.shutdown() 在尚未初始化或已经关闭时幂等返回成功;仍有活动资源时返回 inUse。在对象回调中同步停止、解绑或释放当前对象及其关联资源,也会返回 inUse 且不改变状态。其他无关实例和资源不受此限制。

cloudStorage.dispose() 只有在底层资源释放成功后才使实例失效。若返回 inUse 或其他错误,实例和当前 Token 仍然有效;清理占用资源后可以重试。SDK 不负责清除调用方持有的 Token 字符串。

API说明
initialize(appId:)使用默认服务地址初始化 TiCloudStorage;appId 必填。返回初始化错误码
initialize(appId:endpoint:consoleLogEnabled:)使用完整配置初始化 Ti 云存。endpoint 留空时使用默认服务地址;consoleLogEnabled 控制控制台日志
shutdown()关闭 Ti 云存。调用前必须释放所有 TiCloudStorage 实例、Replay、Output,并等待查询、截图和文件 Task 完成
errorToString(_:)返回错误码对应的稳定名称,用于日志和诊断
updateToken(_:)为同一设备更新 Token,只影响之后启动的 List、Play 和 Export
listRecordingDays(startDate:endDate:timeZoneId:)Swift 查询包含式日期范围,单次最多 31 天。timeZoneId 使用 IANA ID,默认 Asia/Shanghai;结果包含 true/false 日期并按日期升序排列
listRecordingDaysWithStartDate:endDate:completion:Objective-C 使用默认时区的互操作入口
listRecordingDaysWithStartDate:endDate:timeZoneId:completion:Objective-C 使用显式 IANA 时区的互操作入口;completion 在主队列恰好返回一次
listRecordings(startTimeMs:endTimeMs:)Swift 查询当前设备在 [startTimeMs, endTimeMs) 内的录像可用时间段,等待并返回唯一的 TiCloudStorageRecordingRangesResult。单次跨度最长 10 天
listRecordingsWithStartTimeMs:endTimeMs:completion:Objective-C 互操作入口。包括参数、Token、对象状态和运行期错误在内,均由主队列 completion 恰好返回一次,不同步返回另一份错误码
createReplay()创建属于当前设备的 Replay
exportRecording(_:progress:completion:)开始一次录像导出。同步结果包含错误码和可空 Task;接受成功后,completion 返回唯一终局
dispose()释放当前设备实例;仍有查询、Replay、ExportTask 或 callback barrier 时返回 inUse

Token 过期由触发它的 List、Play 或 Export 直接报告 tokenExpired。SDK 不另发过期通知,也不自动刷新或重试。应用取得同一设备的新 Token、调用 updateToken,再显式重做失败的操作。不同非空 Token 建立新的授权代际,只影响之后启动的操作;相同 Token 不清除已确定的过期状态。访问另一台设备时创建新的 TiCloudStorage

List 结果按 startTimeMs 升序排列并裁剪在请求的 [startTimeMs, endTimeMs) 内;重叠或首尾相接的时间段会合并,任何大于 0 的空洞都保留为不同项。结果是设备级完整快照,不保证每个 Channel 都有媒体,也不分页。合并后最多返回 10000 项;查询跨度或结果数量超限时整体返回 rangeTooLarge,不返回部分结果;成功但没有录像时返回空数组。

TiCloudStorageReplay

swift
@objcMembers public final class TiCloudStorageReplay: NSObject {
    public private(set) var speed: TiCloudStorageReplaySpeed
    public private(set) var currentTimeMs: NSNumber?
    public var onTimeChanged: ((Int64) -> Void)?
    public var onError: ((Int32) -> Void)?
    public var onCompleted: (() -> Void)?

    public func play(
        startTimeMs: Int64,
        endTimeMs: Int64,
        initialTimeMs: NSNumber? = nil
    ) -> Int32

    public func pause() -> Int32
    public func resume() -> Int32

    public func seek(toTimeMs timeMs: Int64) -> Int32

    public func setSpeed(_ speed: TiCloudStorageReplaySpeed) -> Int32
    public func startRecording(
        videoChannelId: Int,
        audioChannelId: NSNumber? = nil
    ) -> TiCloudStorageRecordingTaskStartResult
    public func stop() -> Int32
    public func dispose() -> Int32
}

属性与回调

成员说明
speed当前回放倍速,初始值为 .x1
currentTimeMs当前回放位置,UTC Unix 毫秒;首次取得位置前和 stop 后为 nil
onTimeChanged回放位置变化通知;晚设置时不会补发之前的事件
onError当前 play 的 Token、权限、网络或录像读取错误;一次回放最多通知一次
onCompleted当前 play 的时间范围自然耗尽通知;一次回放最多通知一次

方法

API说明
play(startTimeMs:endTimeMs:initialTimeMs:)播放所属设备在 [startTimeMs, endTimeMs) 内的录像。initialTimeMs 可空,缺省时从 startTimeMs 开始;传入时从指定位置开始。返回值表示请求是否被接受
pause()暂停当前回放;重复调用成功
resume()继续当前回放;重复调用成功
seek(toTimeMs:)定位到当前回放范围内的 UTC 时间;同步返回操作是否被接受
setSpeed(_:)设置七档固定速度;非 .x1 时 Audio Output 静音,慢放画面采用持帧显示
startRecording(videoChannelId:audioChannelId:)保存当前回放的一段内容。同步结果包含错误码和可空 RecordingTask
stop()停止当前回放并清除 currentTimeMs;保留 Output 绑定和倍速
dispose()释放 Replay;调用后不能继续使用该实例

Replay 只能由 cloudStorage.createReplay() 创建,并固定属于该设备实例。Replay 没有公开 state。onError 返回当前 play 过程中发生的 Token、权限、网络或录像读取错误。错误发生时恰好调用一次;同步拒绝、主动 stop、被新 play 替换或自然完成不会触发。onCompleted 是 Replay 级自然终局:每个被接受的 play 仅在其时间范围自然耗尽时恰好调用一次;同步拒绝、主动 stop、被新 play 替换或错误终止均不触发。开始 play 前设置回调,晚设置不会重放此前错误或完成事件。接受 Play 时固定使用 TiCloudStorage 实例当前的 Token,之后更新 Token 不改变本次回放。

录像文件已被删除、缺失、损坏或无法读取时,onError 返回 TiCloudStorageErrorCode.recordingUnreadable。网络或服务暂时不可用时,返回 TiCloudStorageErrorCode.cloudStorageUnavailable

  • currentTimeMs 在首次取得位置前和 stop 后为 nil;暂停时保留最后位置,自然完成时为请求的 endTimeMs,回放失败时保留最后已知位置。晚设置 onTimeChanged 不重放旧事件,先读取属性再订阅。
  • speed 初始为 .x1;非 .x1 时 Audio Output 静音。play 前必须至少绑定一个 Output。
  • onCompleted 不取代 Output 的 .completed:前者表示 Replay 来源自然耗尽,后者只表示对应 Output 已排空。自然完成会自动终结活动 RecordingTask。
  • play 要求 startTimeMs < endTimeMs;非空的 initialTimeMs 必须位于 [startTimeMs, endTimeMs)。参数校验失败同步返回 invalidArgument,原回放不受影响。成功接受后从初始位置建立新回放,不会先输出范围开头的媒体;初始位置落在空洞中时从其后的第一段录像开始,其后没有录像时按自然结束处理。
  • 最后一个 Output 离开且没有活动 RecordingTask 时,Replay 停止读取来源,但不触发 onCompleted
  • play 被接受后原回放停止,但保留 Output 绑定、Audio Output 音量和速度;同步拒绝时原回放不受影响。
  • pauseresume 分别幂等;尚未开始、已经 stop、自然完成或失败时返回 notStarted
  • Seek 只能在当前 play 仍在运行或暂停时调用,目标必须位于当前 [startTimeMs, endTimeMs)。回放未活动或目标越界时,分别同步返回 notStartedinvalidArgument,当前回放不受影响。自然完成后要从指定位置重新播放时,调用带 initialTimeMsplay
  • Seek 保留速度和暂停意图,连续调用采用 latest-wins。定位生效后,currentTimeMsonTimeChanged 更新为第一个不早于目标的可播放位置。目标合法但其后没有录像时,位置推进到 endTimeMs 并按自然结束触发 onCompleted
  • stop 幂等,不触发 onCompleted,也不把 Output 标记为 .completed;它会清除 currentTimeMs,并保留 Output 绑定和速度。

Audio/Video Output 扩展

swift
@objc public enum TiCloudStorageAudioOutputState: Int {
    case idle = 0
    case buffering = 1
    case playing = 2
    case failed = 3
    case paused = 4
    case completed = 5
}

@objc public enum TiCloudStorageVideoOutputState: Int {
    case idle = 0
    case buffering = 1
    case rendering = 2
    case failed = 3
    case paused = 4
    case completed = 5
}

@objc public protocol TiCloudStorageAudioOutputDelegate: NSObjectProtocol {
    @objc optional func audioOutput(
        _ output: TiCloudStorageAudioOutput,
        didChangeState state: TiCloudStorageAudioOutputState
    )
    @objc optional func audioOutput(
        _ output: TiCloudStorageAudioOutput,
        didFailWithCode code: Int32
    )
}

@objcMembers public final class TiCloudStorageAudioOutput: NSObject {
    public weak var delegate: TiCloudStorageAudioOutputDelegate?
    public private(set) var state: TiCloudStorageAudioOutputState
    public override init()

    public func attach(replay: TiCloudStorageReplay, channelId: UInt8) -> Int32
    public func setVolume(_ volumePercent: UInt32) -> Int32
    public func detach() -> Int32
    public func dispose() -> Int32
}

@objc public protocol TiCloudStorageVideoOutputDelegate: NSObjectProtocol {
    @objc optional func videoOutput(
        _ output: TiCloudStorageVideoOutput,
        didChangeState state: TiCloudStorageVideoOutputState
    )
    @objc optional func videoOutput(
        _ output: TiCloudStorageVideoOutput,
        didFailWithCode code: Int32
    )
}

@objcMembers public final class TiCloudStorageVideoOutput: NSObject {
    public weak var delegate: TiCloudStorageVideoOutputDelegate?
    public private(set) var state: TiCloudStorageVideoOutputState
    public override init()

    public func attachView(_ view: TiRtcPlatformView) -> Int32
    public func detachView() -> Int32
    public func attach(replay: TiCloudStorageReplay, channelId: UInt8) -> Int32

    @nonobjc public func takeSnapshot() async -> TiCloudStorageSnapshotResult
    @objc(takeSnapshotWithCompletion:)
    @MainActor
    public func takeSnapshotForObjectiveC(
        completion: @escaping @MainActor @Sendable (TiCloudStorageSnapshotResult) -> Void
    )

    public func detach() -> Int32
    public func dispose() -> Int32
}

setVolume(_:) 接收 0...1000 表示静音。它只调整当前 Audio Output,不修改系统全局音量。新一次 play 会保留该值。

Output 状态

Audio 状态Video 状态说明
.idle.idle尚未输出媒体,或已经 detach
.buffering.buffering正在等待足够的媒体数据
.playing.rendering正在播放音频或渲染视频
.paused.pausedReplay 已暂停
.completed.completedReplay 来源已经自然耗尽,并且该 Output 已排空
.failed.failed当前 Output 无法继续输出媒体

属性与 Delegate

成员说明
state当前 Output 状态
delegate弱引用;接收状态变化和当前 Output 的解码、播放或渲染错误
audioOutput(_:didChangeState:) / videoOutput(_:didChangeState:)output 为发生变化的实例,state 为当前状态
audioOutput(_:didFailWithCode:) / videoOutput(_:didFailWithCode:)output 为失败的实例,code 为错误码

方法

API适用对象说明
attachView(_:)Video把 Video Output 绑定到宿主提供的 TiRtcPlatformView;重复绑定同一 View 成功,换绑失败时保留原 View
detachView()Video解除宿主 View 绑定;对象和 Replay 绑定保持不变
attach(replay:channelId:)Audio、Video绑定 Replay 中指定 channel_id 的音频或视频;channelId 取值为 0...255
takeSnapshot() / takeSnapshotWithCompletion:Video把当前视频画面保存为唯一的临时 JPEG;成功结果包含 TiCloudStorageSnapshotFile
detach()Audio、Video解除当前 Replay 绑定;对象仍可再次 attach
dispose()Audio、Video释放 Output;调用后不能继续使用该实例

两个 Output 都提供只读 state 和弱 delegate。delegate 报告状态变化和错误。

attachView 与 Replay 的 attach 相互独立;SDK 借用 TiRtcPlatformViewdetachView 成功为止,应用必须在销毁或复用 View 前先解除绑定。Swift takeSnapshot() 等待唯一终局,Objective-C completion 在主队列完成一次。成功时 file.path 是 SDK 私有 cache 中的临时 JPEG。

当前 binding generation 尚未出画时,completion 返回 noFrame。暂停或自然播放完成后,只要最后画面仍然保留,就可以继续截图;attach 新来源、新的 play 生效、detachViewdetach 后,在新画面到达前返回 noFrame。同一个 Video Output 同时只接受一个 Snapshot;已有请求未完成时,新的 completion 返回 inUse。不同 Output 仍可能因全局资源上限返回 resourceExhausted

Snapshot completion 返回前,dispose()TiCloudStorage.shutdown() 返回 inUse,Output、View 与 Replay 关系保持不变。先等待 completion,再按正常顺序解除 View 和 Replay 绑定并释放 Output。

Video Output 和 Audio Output 分别使用设备配置提供的 channelId,取值范围是 0...255;两者可以相同,也可以不同。使用 exhaustive switch 时,需要处理 pausedcompleted

重复绑定同一个 Replay 的同一个 channel_id 会成功;已经绑定时传入不同 Replay 或 channel_id 返回 inUse 并保留原关系,必须先显式 detach。Replay 正在运行时新增或 detach 后重新绑定 Output,从绑定生效后的下一可独立解码位置开始,不补发此前媒体。同一个 Replay 的同一个 channel_id 只能绑定一个同类播放 Output。stop、自然完成和新 play 都保留绑定;dispose 不隐式解绑,关系仍存在时返回 inUse。某个 Output 解码、播放或渲染失败时,它的 delegate 返回错误,并且只终止该 Output。Token、网络、所选范围过大或录像读取失败时,Replay 的 onError 返回一次错误,并使本次回放的全部 Output 进入 failed

本地媒体文件

swift
@objcMembers public final class TiCloudStorageRecordingFile: NSObject {
    public let path: String
    public let durationMs: Int64
    @nonobjc public func delete() async -> Int32
    @objc(deleteWithCompletion:)
    public func deleteForObjectiveC(
        completion: @escaping @MainActor @Sendable (Int32) -> Void
    )
}

@objcMembers public final class TiCloudStorageSnapshotFile: NSObject {
    public let path: String
    @nonobjc public func delete() async -> Int32
    @objc(deleteWithCompletion:)
    public func deleteForObjectiveC(
        completion: @escaping @MainActor @Sendable (Int32) -> Void
    )
}

@objcMembers public final class TiCloudStorageRecordingResult: NSObject {
    public let code: Int32
    public let file: TiCloudStorageRecordingFile?
}

@objcMembers public final class TiCloudStorageSnapshotResult: NSObject {
    public let code: Int32
    public let file: TiCloudStorageSnapshotFile?
}

文件路径位于应用 container cache。Darwin SDK 只提供受限、幂等的 delete();需要长期保存时由应用自行复制或移动文件。Objective-C 使用对应 delete completion 入口。系统相册便利能力只由 Flutter 与 React Native SDK 提供。

TiCloudStorageRecordingTask

swift
@objcMembers public final class TiCloudStorageRecordingTaskStartResult: NSObject {
    public let code: Int32
    public let task: TiCloudStorageRecordingTask?
}

@objcMembers public final class TiCloudStorageRecordingTask: NSObject {
    @nonobjc public func stop() async -> TiCloudStorageRecordingResult
    @objc(stopWithCompletion:)
    public func stopForObjectiveC(
        completion: @escaping @MainActor @Sendable (TiCloudStorageRecordingResult) -> Void
    )
}

TiCloudStorageReplay.startRecording(videoChannelId:audioChannelId:) 同步返回错误码和可空 Task。Replay 必须正在回放;视频 Channel 必填,音频 Channel 可空。同步失败不创建 Task。

Swift stop() 与 Objective-C stopWithCompletion: 都停止接收新媒体,排空已接收数据并完成 MP4。重复或并发调用取得同一个终局。Replay 自然结束时 Task 自动完成,随后调用 stop 返回缓存结果。

Task 不公开 state、实时 duration、cancel 或 dispose。相同 Channel 可以创建多个 Task,SDK 为每个 Task 生成不同文件;两个视频 Channel 使用两个 Task。

TiCloudStorageExportTask

swift
@objcMembers public final class TiCloudStorageExportRequest: NSObject {
    public let startTimeMs: Int64
    public let endTimeMs: Int64
    public let videoChannelId: Int
    public let audioChannelId: NSNumber?
}

@objcMembers public final class TiCloudStorageExportTaskStartResult: NSObject {
    public let code: Int32
    public let task: TiCloudStorageExportTask?
}

@objcMembers public final class TiCloudStorageExportTask: NSObject {
    public private(set) var progress: Double
    public func stop() -> Int32
}

cloudStorage.exportRecording(_:progress:completion:) 在启动 Task 前固定实例当前的 Token,并保存两个回调,然后同步返回 TiCloudStorageExportTaskStartResult。成功时 Task 已经开始,进度和唯一终局在主队列返回。

同步失败时 task == nil,且不调用回调。SDK 也不会在 exportRecording 返回前调用回调。

progress 位于 0.0...1.0 且单调不回退。只有 MP4 完整生成后才到达 1.0。中间通知可以合并。

活动 Task 调用 stop() 会停止导出、清理临时文件,并使原 completion 返回 .stoppedfile == nil;不生成部分 MP4。自然完成或失败后调用 stop() 不改变缓存终局。重复调用幂等。

Task 在 completion 返回后自动释放 Native 执行资源,不提供 dispose。不同 Task 相互独立并生成不同 cache 文件;资源达到上限返回 .resourceExhausted

错误码

错误码常量常见含义建议处理
0TiCloudStorageErrorCode.ok操作成功继续后续流程
6000TiCloudStorageErrorCode.invalidArgument参数缺失、取值越界或时间范围无效修正参数后重试
6001尚未初始化 TiCloudStorage,或已经关闭先调用 TiCloudStorage.initialize
6014TiCloudStorageErrorCode.tokenExpiredTi 云存 Token 已过期为同一设备更新 Token 后重新发起请求
6022已使用另一组配置初始化保持初始化参数一致,或在全部资源释放后重新初始化
6024TiCloudStorageErrorCode.permissionDeniedToken 无效,或无权访问目标设备或录像检查授权并重新取得 Token
6026对象仍在播放、录制或执行任务,当前操作不能执行先结束活动操作,再重试
6027尚未开始播放或录制先启动对应操作
6029尚未建立当前操作要求的绑定完成对应绑定后重试
6030缺少必要的目标或媒体通道配置补充通道或目标配置后重试
6043当前设备没有足够资源创建或继续任务结束其他任务并释放资源后重试
6046TiCloudStorageErrorCode.fileWriteFailed无法创建或写入输出文件检查目录权限和磁盘空间
6113TiCloudStorageErrorCode.unsupportedFormat录像的音视频格式不受支持提示当前录像无法播放或导出
6114TiCloudStorageErrorCode.ioFailed底层 I/O 或运行时边界失败保留错误码并检查运行环境
6115TiCloudStorageErrorCode.cancelledList 请求被取消结束对应等待
6117TiCloudStorageErrorCode.rangeTooLargeList 查询跨度超过 10 天或合并结果超过 10000 项缩短查询范围后重试
6118TiCloudStorageErrorCode.noFrameVideo Output 尚无可用于截图的视频帧等待出画后重试
6119TiCloudStorageErrorCode.noRecordableMedia所选范围或通道没有可写入的媒体重新选择录像范围或通道
6120TiCloudStorageErrorCode.recordingOverrun本地写入持续跟不上回放数据,保存任务已经终止释放设备资源、检查存储性能后重新保存
6122TiCloudStorageErrorCode.recordingUnreadable录像文件缺失、损坏或无法读取提示当前录像不可用,不要持续重试同一请求
6123TiCloudStorageErrorCode.cloudStorageUnavailable网络、Ti 云存服务或录像数据读取暂时不可用稍后重试
6124TiCloudStorageErrorCode.stopped活动 ExportTask 已被主动停止结束导出进度,不使用输出文件

常量列为“—”的错误通常表示调用顺序或资源状态问题,记录数值用于定位即可,不需要在业务流程中逐项判断。不要根据 errorToString 返回值或日志文本判断错误类型。

队列、生命周期与互操作

  • listRecordings@MainActor 上返回;其他 Swift async 方法返回到调用方所在的并发上下文。Objective-C completion、delegate 和 progress 都进入主队列,不会在发起异步 API 的调用栈中执行。
  • dispose 是 checked 且可重试的:Replay 仍在播放、仍有 Output 绑定或活动 RecordingTask,或者 Output 仍绑定 Replay、宿主 View 或活动 Snapshot 时返回 inUse。失败时对象及关系保持不变。
  • dispose 只有在没有 binding、宿主 View 或活动 Snapshot,并且 native destroy 真正成功后才返回 .ok;失败时对象及关系保持不变。重复调用幂等返回 .ok。成功后普通方法返回 notInitialized,getter 保留最后提交值,SDK 不再调用该对象的 delegate 或状态回调。
  • completion block 由 SDK 保持到完成,你不需要额外持有。
  • MP4 Task 在终局 completion 返回后自动释放 Native 执行资源,不需要额外 dispose。
  • Ti 云存和 Output 构造器只创建 wrapper,不抛 SDK 运行错误;createReplay 同样只建立 Replay wrapper。资源创建失败由第一次需要该资源的方法返回。

Ti 云存开发文档