tirtc-react-native 2.4.2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -6
- package/TiRtcReactNative.podspec +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcModule.kt +140 -17
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeCleanup.kt +54 -19
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeCloudStorageCallbacks.kt +60 -0
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeEventBinder.kt +2 -0
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeEventSink.kt +20 -0
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeMaps.kt +112 -5
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeOptions.kt +2 -7
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeRegistry.kt +3 -0
- package/android/src/main/java/com/tange/ai/tirtc/reactnative/TiRtcReactNativeStorageSupport.kt +46 -22
- package/ios/TiRtcReactNative+Conn.mm +61 -0
- package/ios/TiRtcReactNative+Output.mm +1 -7
- package/ios/TiRtcReactNative+Private.h +1 -0
- package/ios/TiRtcReactNative+Storage.mm +133 -35
- package/ios/TiRtcReactNative.mm +142 -51
- package/ios/TiRtcReactNativeCloudStorageCallbacks.h +13 -0
- package/ios/TiRtcReactNativeCloudStorageCallbacks.mm +67 -0
- package/ios/TiRtcReactNativeEventBinder.h +4 -0
- package/ios/TiRtcReactNativeEventBinder.mm +11 -0
- package/ios/TiRtcReactNativeEventSink.h +5 -0
- package/ios/TiRtcReactNativeEventSink.mm +18 -0
- package/ios/TiRtcReactNativeMaps.h +6 -0
- package/ios/TiRtcReactNativeMaps.mm +47 -0
- package/ios/TiRtcReactNativeOptions.mm +2 -6
- package/lib/module/audio_input.js +23 -4
- package/lib/module/audio_input.js.map +1 -1
- package/lib/module/build_identity.js +1 -0
- package/lib/module/conn.js +19 -0
- package/lib/module/conn.js.map +1 -1
- package/lib/module/events.js +16 -9
- package/lib/module/events.js.map +1 -1
- package/lib/module/index.js +3 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/logging_internal.js +16 -0
- package/lib/module/logging_internal.js.map +1 -1
- package/lib/module/raw_dump.js +53 -0
- package/lib/module/raw_dump.js.map +1 -0
- package/lib/module/runtime.js +3 -1
- package/lib/module/runtime.js.map +1 -1
- package/lib/module/specs/NativeTiRtc.js.map +1 -1
- package/lib/module/storage.js +190 -33
- package/lib/module/storage.js.map +1 -1
- package/lib/module/types.js +0 -4
- package/lib/module/types.js.map +1 -1
- package/lib/module/video_input.js +16 -6
- package/lib/module/video_input.js.map +1 -1
- package/lib/typescript/build_identity.d.ts +6 -0
- package/lib/typescript/conn.d.ts +2 -0
- package/lib/typescript/index.d.ts +5 -3
- package/lib/typescript/logging_internal.d.ts +1 -0
- package/lib/typescript/native.d.ts +1 -1
- package/lib/typescript/raw_dump.d.ts +35 -0
- package/lib/typescript/specs/NativeTiRtc.d.ts +75 -3
- package/lib/typescript/storage.d.ts +84 -3
- package/lib/typescript/types.d.ts +5 -6
- package/package.json +3 -3
- package/src/audio_input.ts +30 -11
- package/src/build_identity.ts +6 -0
- package/src/conn.ts +23 -0
- package/src/events.ts +14 -9
- package/src/index.ts +19 -1
- package/src/logging_internal.ts +18 -0
- package/src/native.ts +7 -1
- package/src/raw_dump.ts +84 -0
- package/src/runtime.ts +2 -1
- package/src/specs/NativeTiRtc.ts +80 -3
- package/src/storage.ts +260 -39
- package/src/types.ts +5 -8
- package/src/video_input.ts +22 -12
package/src/specs/NativeTiRtc.ts
CHANGED
|
@@ -36,6 +36,7 @@ export type NativeVideoOutputOptions = Readonly<{
|
|
|
36
36
|
}>;
|
|
37
37
|
|
|
38
38
|
export type NativeAudioInputOptions = Readonly<{
|
|
39
|
+
media: number;
|
|
39
40
|
codec: 'g711a' | 'aac' | 'pcm' | 'opus' | 'amr';
|
|
40
41
|
sampleRate: 'rate8k' | 'rate16k';
|
|
41
42
|
channels: 'mono';
|
|
@@ -45,7 +46,7 @@ export type NativeAudioInputOptions = Readonly<{
|
|
|
45
46
|
}>;
|
|
46
47
|
|
|
47
48
|
export type NativeVideoInputOptions = Readonly<{
|
|
48
|
-
|
|
49
|
+
media: number;
|
|
49
50
|
width: number;
|
|
50
51
|
height: number;
|
|
51
52
|
frameRate: 'fps10' | 'fps15' | 'fps30';
|
|
@@ -102,11 +103,63 @@ export type NativeLoggingUploadResult = Readonly<{
|
|
|
102
103
|
logId: string | null;
|
|
103
104
|
}>;
|
|
104
105
|
|
|
106
|
+
export type NativeRawDumpStartResult = Readonly<{code: number; dumpId: NativeObjectId | null}>;
|
|
107
|
+
export type NativeRawDumpArchive = Readonly<{
|
|
108
|
+
captureId: string; path: string; size: number; sha256: string; capturedDurationMs: number;
|
|
109
|
+
captureComplete: boolean; stopReason: number;
|
|
110
|
+
unsavedPacketCount: number; unsavedByteCount: number; empty: boolean;
|
|
111
|
+
}>;
|
|
112
|
+
export type NativeRawDumpStopResult = Readonly<{
|
|
113
|
+
code: number; archive: NativeRawDumpArchive | null; terminal: boolean;
|
|
114
|
+
}>;
|
|
115
|
+
|
|
105
116
|
export type NativeTiCloudStorageRecordingRange = Readonly<{
|
|
106
117
|
startTimeMs: number;
|
|
107
118
|
endTimeMs: number;
|
|
108
119
|
}>;
|
|
109
120
|
|
|
121
|
+
export type NativeTiCloudStorageRecordingTrack = Readonly<{
|
|
122
|
+
kind: number;
|
|
123
|
+
channelId: number;
|
|
124
|
+
}>;
|
|
125
|
+
|
|
126
|
+
export type NativeTiCloudStorageRecordingGap = Readonly<{
|
|
127
|
+
range: NativeTiCloudStorageRecordingRange;
|
|
128
|
+
tracks: ReadonlyArray<NativeTiCloudStorageRecordingTrack>;
|
|
129
|
+
reasons: ReadonlyArray<number>;
|
|
130
|
+
}>;
|
|
131
|
+
|
|
132
|
+
export type NativeTiCloudStorageExportProgress = Readonly<{
|
|
133
|
+
fraction: number;
|
|
134
|
+
coveredDurationMs: number;
|
|
135
|
+
}>;
|
|
136
|
+
|
|
137
|
+
export type NativeTiCloudStorageExportSegment = Readonly<{
|
|
138
|
+
sourceRange: NativeTiCloudStorageRecordingRange;
|
|
139
|
+
outputStartMs: number;
|
|
140
|
+
outputEndMs: number;
|
|
141
|
+
}>;
|
|
142
|
+
|
|
143
|
+
export type NativeTiCloudStorageExportReport = Readonly<{
|
|
144
|
+
requestedRange: NativeTiCloudStorageRecordingRange;
|
|
145
|
+
coveredDurationMs: number;
|
|
146
|
+
segments: ReadonlyArray<NativeTiCloudStorageExportSegment>;
|
|
147
|
+
gaps: ReadonlyArray<NativeTiCloudStorageRecordingGap>;
|
|
148
|
+
unprocessedRanges: ReadonlyArray<NativeTiCloudStorageRecordingRange>;
|
|
149
|
+
complete: boolean;
|
|
150
|
+
termination: number;
|
|
151
|
+
cause: number;
|
|
152
|
+
}>;
|
|
153
|
+
|
|
154
|
+
export type NativeTiCloudStorageExportResult = Readonly<{
|
|
155
|
+
code: number;
|
|
156
|
+
fileId: NativeObjectId | null;
|
|
157
|
+
filePath: string | null;
|
|
158
|
+
durationMs: number | null;
|
|
159
|
+
report: NativeTiCloudStorageExportReport | null;
|
|
160
|
+
progressDetail: NativeTiCloudStorageExportProgress | null;
|
|
161
|
+
}>;
|
|
162
|
+
|
|
110
163
|
export type NativeTiCloudStorageRecordingRangesResult = Readonly<{
|
|
111
164
|
code: number;
|
|
112
165
|
recordings: ReadonlyArray<NativeTiCloudStorageRecordingRange>;
|
|
@@ -131,6 +184,7 @@ export type NativeTiCloudStorageReplayInfo = Readonly<{
|
|
|
131
184
|
export type NativeTiCloudStorageTaskStartResult = Readonly<{
|
|
132
185
|
code: number;
|
|
133
186
|
taskId: NativeObjectId | null;
|
|
187
|
+
generation: number;
|
|
134
188
|
}>;
|
|
135
189
|
|
|
136
190
|
export type NativeTiRtcEvent = Readonly<{
|
|
@@ -147,6 +201,8 @@ export type NativeTiRtcEvent = Readonly<{
|
|
|
147
201
|
data?: NativeBytes;
|
|
148
202
|
size?: NativeSize;
|
|
149
203
|
fps?: number;
|
|
204
|
+
exportProgress?: NativeTiCloudStorageExportProgress;
|
|
205
|
+
recordingGap?: NativeTiCloudStorageRecordingGap;
|
|
150
206
|
}>;
|
|
151
207
|
|
|
152
208
|
type NativeConnMetricsResult = Readonly<{
|
|
@@ -242,15 +298,22 @@ type NativeVideoOutputDebugSnapshotResult = Readonly<{
|
|
|
242
298
|
}> | null;
|
|
243
299
|
}>;
|
|
244
300
|
|
|
301
|
+
type NativeTiCloudStorageCallback = Readonly<{
|
|
302
|
+
deliveryId: number;
|
|
303
|
+
event: NativeTiRtcEvent;
|
|
304
|
+
}>;
|
|
305
|
+
|
|
245
306
|
interface Spec extends TurboModule {
|
|
246
307
|
readonly onTiRtcEvent: CodegenTypes.EventEmitter<NativeTiRtcEvent>;
|
|
247
308
|
|
|
248
309
|
initialize(options: NativeInitOptions): Promise<number>;
|
|
249
310
|
shutdown(): number;
|
|
250
311
|
errorToString(code: number): string;
|
|
251
|
-
writeLog(level: number, tag: string, message: string):
|
|
312
|
+
writeLog(level: number, tag: string, message: string): number;
|
|
252
313
|
uploadLogs(): Promise<NativeLoggingUploadResult>;
|
|
253
314
|
|
|
315
|
+
tiCloudStorageTakeCallback(): NativeTiCloudStorageCallback | null;
|
|
316
|
+
tiCloudStorageAcknowledgeCallback(deliveryId: number): number;
|
|
254
317
|
tiCloudStorageInitialize(options: NativeInitOptions): Promise<number>;
|
|
255
318
|
tiCloudStorageShutdown(): number;
|
|
256
319
|
tiCloudStorageCreate(token: string): NativeCreateResult;
|
|
@@ -275,7 +338,9 @@ interface Spec extends TurboModule {
|
|
|
275
338
|
audioChannelId: number | null,
|
|
276
339
|
): NativeTiCloudStorageTaskStartResult;
|
|
277
340
|
tiCloudStorageExportProgress(id: NativeObjectId): number;
|
|
278
|
-
|
|
341
|
+
tiCloudStorageExportProgressDetail(id: NativeObjectId): NativeTiCloudStorageExportProgress;
|
|
342
|
+
tiCloudStorageExportResult(id: NativeObjectId): Promise<NativeTiCloudStorageExportResult>;
|
|
343
|
+
tiCloudStorageExportCancel(id: NativeObjectId): number;
|
|
279
344
|
tiCloudStorageExportStop(id: NativeObjectId): number;
|
|
280
345
|
tiCloudStorageDispose(id: NativeObjectId): number;
|
|
281
346
|
|
|
@@ -290,6 +355,11 @@ interface Spec extends TurboModule {
|
|
|
290
355
|
videoChannelId: number,
|
|
291
356
|
audioChannelId: number | null,
|
|
292
357
|
): NativeTiCloudStorageTaskStartResult;
|
|
358
|
+
tiCloudStorageReplayStartRawDump(
|
|
359
|
+
id: NativeObjectId,
|
|
360
|
+
audioChannelIds: ReadonlyArray<number>,
|
|
361
|
+
videoChannelIds: ReadonlyArray<number>,
|
|
362
|
+
): Promise<NativeRawDumpStartResult>;
|
|
293
363
|
tiCloudStorageRecordingTaskStop(id: NativeObjectId): Promise<NativeMp4Result>;
|
|
294
364
|
tiCloudStorageReplayStop(id: NativeObjectId): number;
|
|
295
365
|
tiCloudStorageReplayDispose(id: NativeObjectId): number;
|
|
@@ -326,6 +396,13 @@ interface Spec extends TurboModule {
|
|
|
326
396
|
id: NativeObjectId,
|
|
327
397
|
options: NativeRecordingOptions,
|
|
328
398
|
): NativeRecordingStartResult;
|
|
399
|
+
connStartRawDump(
|
|
400
|
+
id: NativeObjectId,
|
|
401
|
+
audioStreamIds: ReadonlyArray<number>,
|
|
402
|
+
videoStreamIds: ReadonlyArray<number>,
|
|
403
|
+
uplinkAudioStreamIds: ReadonlyArray<number>,
|
|
404
|
+
): Promise<NativeRawDumpStartResult>;
|
|
405
|
+
rawDumpStop(id: NativeObjectId): Promise<NativeRawDumpStopResult>;
|
|
329
406
|
recordingTaskStop(id: NativeObjectId): Promise<NativeMp4Result>;
|
|
330
407
|
mediaFileMoveToGallery(id: NativeObjectId, fileName: string | null): Promise<NativeGalleryResult>;
|
|
331
408
|
mediaFileDelete(id: NativeObjectId): Promise<number>;
|
package/src/storage.ts
CHANGED
|
@@ -11,7 +11,15 @@ import {
|
|
|
11
11
|
} from './errors';
|
|
12
12
|
import {registerNativeEventHandler, unregisterNativeEventHandler} from './events';
|
|
13
13
|
import {TiRtcLogging} from './logging';
|
|
14
|
-
import {
|
|
14
|
+
import {logBuildIdentity} from './logging_internal';
|
|
15
|
+
import {
|
|
16
|
+
NativeTiRtc,
|
|
17
|
+
NativeTiRtcVideoOutputView,
|
|
18
|
+
type NativeTiRtcEvent,
|
|
19
|
+
type NativeTiCloudStorageExportProgress,
|
|
20
|
+
type NativeTiCloudStorageExportReport,
|
|
21
|
+
type NativeTiCloudStorageRecordingGap,
|
|
22
|
+
} from './native';
|
|
15
23
|
import {
|
|
16
24
|
clearNativeIdentity,
|
|
17
25
|
readNativeIdentity,
|
|
@@ -20,6 +28,12 @@ import {
|
|
|
20
28
|
type NativeIdentity,
|
|
21
29
|
} from './native_object_id';
|
|
22
30
|
import {NativeMediaFileBase, recordingFailure, type Resp, type TiRtcGalleryAsset} from './recording';
|
|
31
|
+
import {
|
|
32
|
+
createRawDumpFromNative,
|
|
33
|
+
normalizeRawDumpIds,
|
|
34
|
+
TiRawDump,
|
|
35
|
+
type TiCloudStorageRawDumpOptions,
|
|
36
|
+
} from './raw_dump';
|
|
23
37
|
|
|
24
38
|
export const TI_CLOUD_STORAGE_ERROR_OK = 0 as const;
|
|
25
39
|
export const TI_CLOUD_STORAGE_ERROR_INVALID_ARGUMENT = 6000 as const;
|
|
@@ -45,6 +59,8 @@ export const TI_CLOUD_STORAGE_ERROR_UNAVAILABLE = 6123 as const;
|
|
|
45
59
|
export const TI_CLOUD_STORAGE_ERROR_STOPPED = 6124 as const;
|
|
46
60
|
export const TI_CLOUD_STORAGE_ERROR_RECORDING_NOT_FOUND = 6134 as const;
|
|
47
61
|
export const TI_CLOUD_STORAGE_ERROR_RECORDING_DOWNLOAD_FAILED = 6135 as const;
|
|
62
|
+
export const TI_CLOUD_STORAGE_ERROR_NETWORK_UNAVAILABLE = 6136 as const;
|
|
63
|
+
export const TI_CLOUD_STORAGE_ERROR_ENDPOINT_DNS_RESOLUTION_FAILED = 6137 as const;
|
|
48
64
|
|
|
49
65
|
export type TiCloudStorageRecordingRange = Readonly<{
|
|
50
66
|
startTimeMs: number;
|
|
@@ -63,6 +79,70 @@ export type TiCloudStorageRecordingDaysResult = Readonly<{
|
|
|
63
79
|
days: ReadonlyArray<TiCloudStorageRecordingDay>;
|
|
64
80
|
}>;
|
|
65
81
|
|
|
82
|
+
export const TiCloudStorageRecordingTrackKind = {video: 'video', audio: 'audio'} as const;
|
|
83
|
+
export type TiCloudStorageRecordingTrackKind =
|
|
84
|
+
(typeof TiCloudStorageRecordingTrackKind)[keyof typeof TiCloudStorageRecordingTrackKind];
|
|
85
|
+
export type TiCloudStorageRecordingTrack = Readonly<{
|
|
86
|
+
kind: TiCloudStorageRecordingTrackKind;
|
|
87
|
+
channelId: number;
|
|
88
|
+
}>;
|
|
89
|
+
export const TiCloudStorageRecordingGapReason = {
|
|
90
|
+
unknown: 'unknown',
|
|
91
|
+
notFound: 'notFound',
|
|
92
|
+
downloadFailed: 'downloadFailed',
|
|
93
|
+
integrityFailed: 'integrityFailed',
|
|
94
|
+
mediaUnreadable: 'mediaUnreadable',
|
|
95
|
+
noKeyFrame: 'noKeyFrame',
|
|
96
|
+
noRecording: 'noRecording',
|
|
97
|
+
decryptionFailed: 'decryptionFailed',
|
|
98
|
+
unsupportedMedia: 'unsupportedMedia',
|
|
99
|
+
trackUnavailable: 'trackUnavailable',
|
|
100
|
+
} as const;
|
|
101
|
+
export type TiCloudStorageRecordingGapReason =
|
|
102
|
+
(typeof TiCloudStorageRecordingGapReason)[keyof typeof TiCloudStorageRecordingGapReason];
|
|
103
|
+
export type TiCloudStorageRecordingGap = Readonly<{
|
|
104
|
+
range: TiCloudStorageRecordingRange;
|
|
105
|
+
tracks: ReadonlyArray<TiCloudStorageRecordingTrack>;
|
|
106
|
+
reasons: ReadonlyArray<TiCloudStorageRecordingGapReason>;
|
|
107
|
+
}>;
|
|
108
|
+
export type TiCloudStorageExportProgress = Readonly<{
|
|
109
|
+
fraction: number;
|
|
110
|
+
coveredDurationMs: number;
|
|
111
|
+
}>;
|
|
112
|
+
export type TiCloudStorageExportSegment = Readonly<{
|
|
113
|
+
sourceRange: TiCloudStorageRecordingRange;
|
|
114
|
+
outputStartMs: number;
|
|
115
|
+
outputEndMs: number;
|
|
116
|
+
}>;
|
|
117
|
+
export const TiCloudStorageExportTermination = {
|
|
118
|
+
exhausted: 'exhausted',
|
|
119
|
+
interrupted: 'interrupted',
|
|
120
|
+
cancelled: 'cancelled',
|
|
121
|
+
failed: 'failed',
|
|
122
|
+
} as const;
|
|
123
|
+
export type TiCloudStorageExportTermination =
|
|
124
|
+
(typeof TiCloudStorageExportTermination)[keyof typeof TiCloudStorageExportTermination];
|
|
125
|
+
export type TiCloudStorageExportReport = Readonly<{
|
|
126
|
+
requestedRange: TiCloudStorageRecordingRange;
|
|
127
|
+
coveredDurationMs: number;
|
|
128
|
+
segments: ReadonlyArray<TiCloudStorageExportSegment>;
|
|
129
|
+
gaps: ReadonlyArray<TiCloudStorageRecordingGap>;
|
|
130
|
+
unprocessedRanges: ReadonlyArray<TiCloudStorageRecordingRange>;
|
|
131
|
+
complete: boolean;
|
|
132
|
+
termination: TiCloudStorageExportTermination;
|
|
133
|
+
cause: number;
|
|
134
|
+
}>;
|
|
135
|
+
export type TiCloudStorageExportOutcome = Readonly<{
|
|
136
|
+
code: number;
|
|
137
|
+
file: TiCloudStorageRecordingFile | null;
|
|
138
|
+
report: TiCloudStorageExportReport | null;
|
|
139
|
+
}>;
|
|
140
|
+
export type TiCloudStorageExportObserver = Readonly<{
|
|
141
|
+
onProgress?: (progress: number) => void;
|
|
142
|
+
onProgressDetail?: (progress: TiCloudStorageExportProgress) => void;
|
|
143
|
+
onRecordingGap?: (gap: TiCloudStorageRecordingGap) => void;
|
|
144
|
+
}>;
|
|
145
|
+
|
|
66
146
|
export const TiCloudStorageReplaySpeed = {
|
|
67
147
|
x0_125: 'x0_125',
|
|
68
148
|
x0_25: 'x0_25',
|
|
@@ -144,6 +224,37 @@ function success<T>(data: T): Resp<T> {
|
|
|
144
224
|
function validTime(value: number): boolean {
|
|
145
225
|
return isFiniteSafeInteger(value) && value >= 0;
|
|
146
226
|
}
|
|
227
|
+
|
|
228
|
+
function recordingGapFromNative(value: NativeTiCloudStorageRecordingGap): TiCloudStorageRecordingGap {
|
|
229
|
+
const kinds = [TiCloudStorageRecordingTrackKind.video, TiCloudStorageRecordingTrackKind.audio] as const;
|
|
230
|
+
const reasons = Object.values(TiCloudStorageRecordingGapReason);
|
|
231
|
+
return {
|
|
232
|
+
range: value.range,
|
|
233
|
+
tracks: value.tracks.flatMap((track) => {
|
|
234
|
+
const kind = kinds[track.kind - 1];
|
|
235
|
+
return kind === undefined ? [] : [{kind, channelId: track.channelId}];
|
|
236
|
+
}),
|
|
237
|
+
reasons: value.reasons.map((reason) => reasons[reason] ?? TiCloudStorageRecordingGapReason.unknown),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function exportProgressFromNative(value: NativeTiCloudStorageExportProgress): TiCloudStorageExportProgress {
|
|
242
|
+
return {fraction: value.fraction, coveredDurationMs: value.coveredDurationMs};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function exportReportFromNative(value: NativeTiCloudStorageExportReport): TiCloudStorageExportReport {
|
|
246
|
+
const terminations = Object.values(TiCloudStorageExportTermination);
|
|
247
|
+
return {
|
|
248
|
+
requestedRange: value.requestedRange,
|
|
249
|
+
coveredDurationMs: value.coveredDurationMs,
|
|
250
|
+
segments: value.segments,
|
|
251
|
+
gaps: value.gaps.map(recordingGapFromNative),
|
|
252
|
+
unprocessedRanges: value.unprocessedRanges,
|
|
253
|
+
complete: value.complete,
|
|
254
|
+
termination: terminations[value.termination] ?? TiCloudStorageExportTermination.failed,
|
|
255
|
+
cause: value.cause,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
147
258
|
function speedToNative(speed: TiCloudStorageReplaySpeed): number | null {
|
|
148
259
|
switch (speed) {
|
|
149
260
|
case TiCloudStorageReplaySpeed.x0_125:
|
|
@@ -214,6 +325,7 @@ function videoStateFromNative(state: unknown): TiCloudStorageVideoOutputState {
|
|
|
214
325
|
export class TiCloudStorage {
|
|
215
326
|
private identity: NativeIdentity | null = null;
|
|
216
327
|
private disposed = false;
|
|
328
|
+
private pendingAsyncOperations = 0;
|
|
217
329
|
constructor(private token: string) {}
|
|
218
330
|
|
|
219
331
|
static init(
|
|
@@ -232,6 +344,7 @@ export class TiCloudStorage {
|
|
|
232
344
|
endpoint: options.endpoint ?? '',
|
|
233
345
|
consoleLogEnabled: options.consoleLogEnabled ?? false,
|
|
234
346
|
}).then((code) => {
|
|
347
|
+
if (code === 0) logBuildIdentity('cloud_storage');
|
|
235
348
|
tiCloudStorageLogOutcome('cloud_storage_initialize', code);
|
|
236
349
|
return code;
|
|
237
350
|
});
|
|
@@ -268,10 +381,12 @@ export class TiCloudStorage {
|
|
|
268
381
|
return Promise.resolve({code: identity, recordings: []});
|
|
269
382
|
}
|
|
270
383
|
TiRtcLogging.i(tiCloudStorageLogTag, `[recording_list] outcome=started range_duration_ms=${endTimeMs - startTimeMs}`);
|
|
271
|
-
return
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
384
|
+
return this.trackAsyncOperation(() =>
|
|
385
|
+
NativeTiRtc.tiCloudStorageListRecordings(identity.objectId, startTimeMs, endTimeMs).then((result) => {
|
|
386
|
+
tiCloudStorageLogOutcome('recording_list', result.code, ` recording_count=${result.recordings.length}`);
|
|
387
|
+
return result;
|
|
388
|
+
}),
|
|
389
|
+
);
|
|
275
390
|
}
|
|
276
391
|
listRecordingDays(
|
|
277
392
|
startDate: string,
|
|
@@ -292,20 +407,25 @@ export class TiCloudStorage {
|
|
|
292
407
|
return Promise.resolve({code: identity, days: []});
|
|
293
408
|
}
|
|
294
409
|
TiRtcLogging.i(tiCloudStorageLogTag, '[recording_days_list] outcome=started');
|
|
295
|
-
return
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
410
|
+
return this.trackAsyncOperation(() =>
|
|
411
|
+
NativeTiRtc.tiCloudStorageListRecordingDays(
|
|
412
|
+
identity.objectId,
|
|
413
|
+
startDate,
|
|
414
|
+
endDate,
|
|
415
|
+
timeZoneId,
|
|
416
|
+
).then((result) => {
|
|
417
|
+
tiCloudStorageLogOutcome('recording_days_list', result.code, ` day_count=${result.days.length}`);
|
|
418
|
+
return result;
|
|
419
|
+
}),
|
|
420
|
+
);
|
|
304
421
|
}
|
|
305
422
|
createReplay(): TiCloudStorageReplay {
|
|
306
423
|
return new TiCloudStorageReplay(this);
|
|
307
424
|
}
|
|
308
|
-
exportRecording(
|
|
425
|
+
exportRecording(
|
|
426
|
+
options: TiCloudStorageExportOptions,
|
|
427
|
+
observer?: ((progress: number) => void) | TiCloudStorageExportObserver,
|
|
428
|
+
): Resp<TiCloudStorageExportTask> {
|
|
309
429
|
if (
|
|
310
430
|
!validTime(options.startTimeMs) ||
|
|
311
431
|
!validTime(options.endTimeMs) ||
|
|
@@ -326,11 +446,12 @@ export class TiCloudStorage {
|
|
|
326
446
|
);
|
|
327
447
|
tiCloudStorageLogOutcome('export_start', result.code, ` range_duration_ms=${options.endTimeMs - options.startTimeMs}`);
|
|
328
448
|
return result.code === 0 && result.taskId !== null
|
|
329
|
-
? success(new TiCloudStorageExportTask(result.taskId, this,
|
|
449
|
+
? success(new TiCloudStorageExportTask(result.taskId, result.generation, this, observer))
|
|
330
450
|
: recordingFailure(result.code);
|
|
331
451
|
}
|
|
332
452
|
dispose(): number {
|
|
333
453
|
if (this.disposed) return 0;
|
|
454
|
+
if (this.pendingAsyncOperations > 0) return TI_CLOUD_STORAGE_ERROR_IN_USE;
|
|
334
455
|
if (this.identity === null) {
|
|
335
456
|
this.disposed = true;
|
|
336
457
|
this.token = '';
|
|
@@ -347,6 +468,17 @@ export class TiCloudStorage {
|
|
|
347
468
|
}
|
|
348
469
|
return code;
|
|
349
470
|
}
|
|
471
|
+
private trackAsyncOperation<T>(operation: () => Promise<T>): Promise<T> {
|
|
472
|
+
this.pendingAsyncOperations += 1;
|
|
473
|
+
try {
|
|
474
|
+
return operation().finally(() => {
|
|
475
|
+
this.pendingAsyncOperations -= 1;
|
|
476
|
+
});
|
|
477
|
+
} catch (error) {
|
|
478
|
+
this.pendingAsyncOperations -= 1;
|
|
479
|
+
return Promise.reject(error);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
350
482
|
private ensureIdentity(): NativeIdentity | number {
|
|
351
483
|
if (this.disposed) return TI_CLOUD_STORAGE_ERROR_NOT_INITIALIZED;
|
|
352
484
|
if (this.identity !== null) return this.identity;
|
|
@@ -369,11 +501,13 @@ function tiCloudStorageNativeIdentity(cloudStorage: TiCloudStorage): NativeIdent
|
|
|
369
501
|
export class TiCloudStorageReplay {
|
|
370
502
|
private identity: NativeIdentity | null = null;
|
|
371
503
|
private disposed = false;
|
|
504
|
+
private inCallback = false;
|
|
372
505
|
private currentSpeed: TiCloudStorageReplaySpeed = 'x1';
|
|
373
506
|
private currentTime: number | null = null;
|
|
374
507
|
onTimeChanged: ((timeMs: number) => void) | null = null;
|
|
375
508
|
onError: ((code: number) => void) | null = null;
|
|
376
509
|
onCompleted: (() => void) | null = null;
|
|
510
|
+
onRecordingGap: ((gap: TiCloudStorageRecordingGap) => void) | null = null;
|
|
377
511
|
constructor(private readonly cloudStorage: TiCloudStorage) {}
|
|
378
512
|
get speed(): TiCloudStorageReplaySpeed {
|
|
379
513
|
if (this.identity !== null) {
|
|
@@ -390,6 +524,7 @@ export class TiCloudStorageReplay {
|
|
|
390
524
|
return this.currentTime;
|
|
391
525
|
}
|
|
392
526
|
play(startTimeMs: number, endTimeMs: number, initialTimeMs?: number): number {
|
|
527
|
+
if (this.inCallback) return TI_CLOUD_STORAGE_ERROR_IN_USE;
|
|
393
528
|
if (
|
|
394
529
|
!validTime(startTimeMs) ||
|
|
395
530
|
!validTime(endTimeMs) ||
|
|
@@ -417,6 +552,7 @@ export class TiCloudStorageReplay {
|
|
|
417
552
|
return code;
|
|
418
553
|
}
|
|
419
554
|
seek(timeMs: number): number {
|
|
555
|
+
if (this.inCallback) return TI_CLOUD_STORAGE_ERROR_IN_USE;
|
|
420
556
|
if (!validTime(timeMs)) return TI_CLOUD_STORAGE_ERROR_INVALID_ARGUMENT;
|
|
421
557
|
const identity = this.ensureIdentity();
|
|
422
558
|
const code = typeof identity === 'number' ? identity : NativeTiRtc.tiCloudStorageReplaySeek(identity.objectId, timeMs);
|
|
@@ -452,19 +588,38 @@ export class TiCloudStorageReplay {
|
|
|
452
588
|
? success(new TiCloudStorageRecordingTask(result.taskId, this))
|
|
453
589
|
: recordingFailure(result.code);
|
|
454
590
|
}
|
|
591
|
+
async startRawDump(options: TiCloudStorageRawDumpOptions): Promise<Resp<TiRawDump>> {
|
|
592
|
+
if (options === null || typeof options !== 'object')
|
|
593
|
+
return recordingFailure(TI_CLOUD_STORAGE_ERROR_INVALID_ARGUMENT);
|
|
594
|
+
const audio = normalizeRawDumpIds(options.audioChannelIds ?? [], 255);
|
|
595
|
+
const video = normalizeRawDumpIds(options.videoChannelIds ?? [], 255);
|
|
596
|
+
if (audio === null || video === null || (audio.length === 0 && video.length === 0))
|
|
597
|
+
return recordingFailure(TI_CLOUD_STORAGE_ERROR_INVALID_ARGUMENT);
|
|
598
|
+
const identity = this.ensureIdentity();
|
|
599
|
+
if (typeof identity === 'number') return recordingFailure(identity);
|
|
600
|
+
const result = await NativeTiRtc.tiCloudStorageReplayStartRawDump(
|
|
601
|
+
identity.objectId, audio, video,
|
|
602
|
+
);
|
|
603
|
+
return result.code === 0 && result.dumpId !== null
|
|
604
|
+
? {success: true, code: null, message: null, data: createRawDumpFromNative(result.dumpId)}
|
|
605
|
+
: recordingFailure(result.code);
|
|
606
|
+
}
|
|
455
607
|
stop(): number {
|
|
608
|
+
if (this.inCallback) return TI_CLOUD_STORAGE_ERROR_IN_USE;
|
|
456
609
|
const code = this.command(NativeTiRtc.tiCloudStorageReplayStop);
|
|
457
610
|
if (code === 0) this.currentTime = null;
|
|
458
611
|
tiCloudStorageLogOutcome('replay_stop', code);
|
|
459
612
|
return code;
|
|
460
613
|
}
|
|
461
614
|
dispose(): number {
|
|
615
|
+
if (this.inCallback) return TI_CLOUD_STORAGE_ERROR_IN_USE;
|
|
462
616
|
if (this.disposed) return 0;
|
|
463
617
|
if (this.identity === null) {
|
|
464
618
|
this.disposed = true;
|
|
465
619
|
this.onTimeChanged = null;
|
|
466
620
|
this.onError = null;
|
|
467
621
|
this.onCompleted = null;
|
|
622
|
+
this.onRecordingGap = null;
|
|
468
623
|
return 0;
|
|
469
624
|
}
|
|
470
625
|
const identity = this.identity;
|
|
@@ -477,6 +632,7 @@ export class TiCloudStorageReplay {
|
|
|
477
632
|
this.onTimeChanged = null;
|
|
478
633
|
this.onError = null;
|
|
479
634
|
this.onCompleted = null;
|
|
635
|
+
this.onRecordingGap = null;
|
|
480
636
|
}
|
|
481
637
|
tiCloudStorageLogOutcome('replay_dispose', code);
|
|
482
638
|
return code;
|
|
@@ -501,11 +657,18 @@ export class TiCloudStorageReplay {
|
|
|
501
657
|
return this.identity;
|
|
502
658
|
}
|
|
503
659
|
private handleEvent(event: NativeTiRtcEvent): void {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
660
|
+
this.inCallback = true;
|
|
661
|
+
try {
|
|
662
|
+
if (event.type === 'tiCloudStorageReplayTimeChanged' && event.timestampMs !== undefined) {
|
|
663
|
+
this.currentTime = event.timestampMs;
|
|
664
|
+
this.onTimeChanged?.(event.timestampMs);
|
|
665
|
+
} else if (event.type === 'tiCloudStorageReplayCompleted') this.onCompleted?.();
|
|
666
|
+
else if (event.type === 'tiCloudStorageReplayError') this.onError?.(event.code ?? TI_CLOUD_STORAGE_ERROR_UNAVAILABLE);
|
|
667
|
+
else if (event.type === 'tiCloudStorageReplayRecordingGap' && event.recordingGap !== undefined)
|
|
668
|
+
this.onRecordingGap?.(recordingGapFromNative(event.recordingGap));
|
|
669
|
+
} finally {
|
|
670
|
+
this.inCallback = false;
|
|
671
|
+
}
|
|
509
672
|
}
|
|
510
673
|
}
|
|
511
674
|
|
|
@@ -732,40 +895,98 @@ export class TiCloudStorageRecordingTask {
|
|
|
732
895
|
|
|
733
896
|
export class TiCloudStorageExportTask {
|
|
734
897
|
private resultPromise: Promise<Resp<TiCloudStorageRecordingFile>>;
|
|
898
|
+
private completionPromise: Promise<TiCloudStorageExportOutcome>;
|
|
899
|
+
private readonly identity: NativeIdentity;
|
|
900
|
+
private currentProgressDetail: TiCloudStorageExportProgress = {fraction: 0, coveredDurationMs: 0};
|
|
901
|
+
private currentReport: TiCloudStorageExportReport | null = null;
|
|
902
|
+
private readonly observer: TiCloudStorageExportObserver;
|
|
903
|
+
private terminal = false;
|
|
904
|
+
|
|
735
905
|
constructor(
|
|
736
906
|
private readonly taskId: number,
|
|
907
|
+
generation: number,
|
|
737
908
|
private readonly owner: TiCloudStorage,
|
|
738
|
-
|
|
909
|
+
observer?: ((progress: number) => void) | TiCloudStorageExportObserver,
|
|
739
910
|
) {
|
|
740
|
-
this.
|
|
911
|
+
this.identity = {objectId: taskId, generation};
|
|
912
|
+
this.observer = typeof observer === 'function' ? {onProgress: observer} : (observer ?? {});
|
|
913
|
+
registerNativeEventHandler(this.identity, (event) => this.handleEvent(event));
|
|
914
|
+
this.completionPromise = NativeTiRtc.tiCloudStorageExportResult(taskId).then((result) => {
|
|
915
|
+
if (result.progressDetail != null) {
|
|
916
|
+
const progress = exportProgressFromNative(result.progressDetail);
|
|
917
|
+
this.currentProgressDetail = {
|
|
918
|
+
fraction: Math.max(this.currentProgressDetail.fraction, progress.fraction),
|
|
919
|
+
coveredDurationMs: Math.max(this.currentProgressDetail.coveredDurationMs, progress.coveredDurationMs),
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
this.terminal = true;
|
|
923
|
+
unregisterNativeEventHandler(this.identity);
|
|
741
924
|
tiCloudStorageLogOutcome('export_terminal', result.code, ` duration_ms=${result.durationMs ?? 0}`);
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
925
|
+
const file =
|
|
926
|
+
result.fileId !== null && result.filePath !== null && result.durationMs !== null
|
|
927
|
+
? new RecordingFile(result.filePath, result.durationMs, result.fileId)
|
|
928
|
+
: null;
|
|
929
|
+
this.currentReport = result.report === null ? null : exportReportFromNative(result.report);
|
|
930
|
+
if (this.currentReport !== null) {
|
|
931
|
+
this.currentProgressDetail = {
|
|
932
|
+
fraction: this.currentProgressDetail.fraction,
|
|
933
|
+
coveredDurationMs: this.currentReport.coveredDurationMs,
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
return {code: result.code, file, report: this.currentReport};
|
|
745
937
|
});
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
lastProgress = progress;
|
|
752
|
-
onProgress(progress);
|
|
753
|
-
}
|
|
754
|
-
}, 100);
|
|
755
|
-
const clear = () => clearInterval(timer);
|
|
756
|
-
void this.resultPromise.then(clear, clear);
|
|
757
|
-
}
|
|
938
|
+
this.resultPromise = this.completionPromise.then((outcome) =>
|
|
939
|
+
outcome.code === TI_CLOUD_STORAGE_ERROR_OK && outcome.file !== null
|
|
940
|
+
? success(outcome.file)
|
|
941
|
+
: recordingFailure(outcome.code),
|
|
942
|
+
);
|
|
758
943
|
}
|
|
759
944
|
get progress(): number {
|
|
760
945
|
void this.owner;
|
|
761
|
-
return
|
|
946
|
+
return this.progressDetail.fraction;
|
|
947
|
+
}
|
|
948
|
+
get progressDetail(): TiCloudStorageExportProgress {
|
|
949
|
+
if (this.terminal) return this.currentProgressDetail;
|
|
950
|
+
const value = exportProgressFromNative(NativeTiRtc.tiCloudStorageExportProgressDetail(this.taskId));
|
|
951
|
+
this.currentProgressDetail = {
|
|
952
|
+
fraction: Math.max(this.currentProgressDetail.fraction, value.fraction),
|
|
953
|
+
coveredDurationMs: Math.max(this.currentProgressDetail.coveredDurationMs, value.coveredDurationMs),
|
|
954
|
+
};
|
|
955
|
+
return this.currentProgressDetail;
|
|
956
|
+
}
|
|
957
|
+
get report(): TiCloudStorageExportReport | null {
|
|
958
|
+
return this.currentReport;
|
|
959
|
+
}
|
|
960
|
+
get completion(): Promise<TiCloudStorageExportOutcome> {
|
|
961
|
+
return this.completionPromise;
|
|
762
962
|
}
|
|
763
963
|
get result(): Promise<Resp<TiCloudStorageRecordingFile>> {
|
|
764
964
|
return this.resultPromise;
|
|
765
965
|
}
|
|
966
|
+
cancel(): number {
|
|
967
|
+
if (this.terminal) return TI_CLOUD_STORAGE_ERROR_OK;
|
|
968
|
+
const code = NativeTiRtc.tiCloudStorageExportCancel(this.taskId);
|
|
969
|
+
tiCloudStorageLogOutcome('export_cancel', code);
|
|
970
|
+
return code;
|
|
971
|
+
}
|
|
766
972
|
stop(): Promise<Resp<TiCloudStorageRecordingFile>> {
|
|
973
|
+
if (this.terminal) return this.resultPromise;
|
|
767
974
|
const code = NativeTiRtc.tiCloudStorageExportStop(this.taskId);
|
|
768
975
|
tiCloudStorageLogOutcome('export_stop', code);
|
|
769
976
|
return this.resultPromise;
|
|
770
977
|
}
|
|
978
|
+
private handleEvent(event: NativeTiRtcEvent): void {
|
|
979
|
+
if (this.terminal) return;
|
|
980
|
+
if (event.type === 'tiCloudStorageExportProgress' && event.exportProgress !== undefined) {
|
|
981
|
+
const progress = exportProgressFromNative(event.exportProgress);
|
|
982
|
+
this.currentProgressDetail = {
|
|
983
|
+
fraction: Math.max(this.currentProgressDetail.fraction, progress.fraction),
|
|
984
|
+
coveredDurationMs: Math.max(this.currentProgressDetail.coveredDurationMs, progress.coveredDurationMs),
|
|
985
|
+
};
|
|
986
|
+
this.observer.onProgress?.(this.currentProgressDetail.fraction);
|
|
987
|
+
this.observer.onProgressDetail?.(this.currentProgressDetail);
|
|
988
|
+
} else if (event.type === 'tiCloudStorageExportRecordingGap' && event.recordingGap !== undefined) {
|
|
989
|
+
this.observer.onRecordingGap?.(recordingGapFromNative(event.recordingGap));
|
|
990
|
+
}
|
|
991
|
+
}
|
|
771
992
|
}
|
package/src/types.ts
CHANGED
|
@@ -84,13 +84,6 @@ export const TiRtcVideoCodec = {
|
|
|
84
84
|
} as const;
|
|
85
85
|
export type TiRtcVideoCodec = (typeof TiRtcVideoCodec)[keyof typeof TiRtcVideoCodec];
|
|
86
86
|
|
|
87
|
-
export const TiRtcVideoEncoderCodec = {
|
|
88
|
-
h264: 'h264',
|
|
89
|
-
mjpeg: 'mjpeg',
|
|
90
|
-
} as const;
|
|
91
|
-
export type TiRtcVideoEncoderCodec =
|
|
92
|
-
(typeof TiRtcVideoEncoderCodec)[keyof typeof TiRtcVideoEncoderCodec];
|
|
93
|
-
|
|
94
87
|
export const TiRtcVideoFrameRate = {
|
|
95
88
|
fps10: 'fps10',
|
|
96
89
|
fps15: 'fps15',
|
|
@@ -183,6 +176,9 @@ export type TiRtcVideoOutputViewProps = ViewProps &
|
|
|
183
176
|
}>;
|
|
184
177
|
|
|
185
178
|
export type TiRtcAudioInputOptions = Readonly<{
|
|
179
|
+
/** Nano audio media: 1 PCM, 2 G711A, 3 AAC, 4 Opus, 5 AMR. Omitted or -1 uses codec. */
|
|
180
|
+
media?: number;
|
|
181
|
+
/** @deprecated Use media. The legacy default is g711a. */
|
|
186
182
|
codec?: TiRtcAudioCodec;
|
|
187
183
|
sampleRate?: TiRtcAudioSampleRate;
|
|
188
184
|
channels?: TiRtcAudioChannelCount;
|
|
@@ -192,7 +188,8 @@ export type TiRtcAudioInputOptions = Readonly<{
|
|
|
192
188
|
}>;
|
|
193
189
|
|
|
194
190
|
export type TiRtcVideoInputOptions = Readonly<{
|
|
195
|
-
|
|
191
|
+
/** Nano video media: 66 H.264 (default) or 65 MJPEG. */
|
|
192
|
+
media?: number;
|
|
196
193
|
width?: number;
|
|
197
194
|
height?: number;
|
|
198
195
|
frameRate?: TiRtcVideoFrameRate;
|