tirtc-react-native 2.5.0-alpha.1 → 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 +137 -14
- 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 +137 -48
- 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 -1
- 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/raw_dump.js +53 -0
- package/lib/module/raw_dump.js.map +1 -0
- package/lib/module/specs/NativeTiRtc.js.map +1 -1
- package/lib/module/storage.js +185 -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/conn.d.ts +2 -0
- package/lib/typescript/index.d.ts +5 -3
- package/lib/typescript/native.d.ts +1 -1
- package/lib/typescript/raw_dump.d.ts +35 -0
- package/lib/typescript/specs/NativeTiRtc.d.ts +74 -2
- package/lib/typescript/storage.d.ts +82 -3
- package/lib/typescript/types.d.ts +5 -6
- package/package.json +2 -2
- package/src/audio_input.ts +30 -11
- package/src/conn.ts +23 -0
- package/src/events.ts +14 -9
- package/src/index.ts +17 -1
- package/src/native.ts +7 -1
- package/src/raw_dump.ts +84 -0
- package/src/specs/NativeTiRtc.ts +79 -2
- package/src/storage.ts +256 -39
- package/src/types.ts +5 -8
- package/src/video_input.ts +22 -12
|
@@ -3,6 +3,7 @@ import { type ViewProps } from 'react-native';
|
|
|
3
3
|
import { NativeTiRtc, type NativeTiRtcEvent } from './native';
|
|
4
4
|
import { type NativeIdentity } from './native_object_id';
|
|
5
5
|
import { type Resp, type TiRtcGalleryAsset } from './recording';
|
|
6
|
+
import { TiRawDump, type TiCloudStorageRawDumpOptions } from './raw_dump';
|
|
6
7
|
export declare const TI_CLOUD_STORAGE_ERROR_OK: 0;
|
|
7
8
|
export declare const TI_CLOUD_STORAGE_ERROR_INVALID_ARGUMENT: 6000;
|
|
8
9
|
export declare const TI_CLOUD_STORAGE_ERROR_NOT_INITIALIZED: 6001;
|
|
@@ -45,6 +46,69 @@ export type TiCloudStorageRecordingDaysResult = Readonly<{
|
|
|
45
46
|
code: number;
|
|
46
47
|
days: ReadonlyArray<TiCloudStorageRecordingDay>;
|
|
47
48
|
}>;
|
|
49
|
+
export declare const TiCloudStorageRecordingTrackKind: {
|
|
50
|
+
readonly video: "video";
|
|
51
|
+
readonly audio: "audio";
|
|
52
|
+
};
|
|
53
|
+
export type TiCloudStorageRecordingTrackKind = (typeof TiCloudStorageRecordingTrackKind)[keyof typeof TiCloudStorageRecordingTrackKind];
|
|
54
|
+
export type TiCloudStorageRecordingTrack = Readonly<{
|
|
55
|
+
kind: TiCloudStorageRecordingTrackKind;
|
|
56
|
+
channelId: number;
|
|
57
|
+
}>;
|
|
58
|
+
export declare const TiCloudStorageRecordingGapReason: {
|
|
59
|
+
readonly unknown: "unknown";
|
|
60
|
+
readonly notFound: "notFound";
|
|
61
|
+
readonly downloadFailed: "downloadFailed";
|
|
62
|
+
readonly integrityFailed: "integrityFailed";
|
|
63
|
+
readonly mediaUnreadable: "mediaUnreadable";
|
|
64
|
+
readonly noKeyFrame: "noKeyFrame";
|
|
65
|
+
readonly noRecording: "noRecording";
|
|
66
|
+
readonly decryptionFailed: "decryptionFailed";
|
|
67
|
+
readonly unsupportedMedia: "unsupportedMedia";
|
|
68
|
+
readonly trackUnavailable: "trackUnavailable";
|
|
69
|
+
};
|
|
70
|
+
export type TiCloudStorageRecordingGapReason = (typeof TiCloudStorageRecordingGapReason)[keyof typeof TiCloudStorageRecordingGapReason];
|
|
71
|
+
export type TiCloudStorageRecordingGap = Readonly<{
|
|
72
|
+
range: TiCloudStorageRecordingRange;
|
|
73
|
+
tracks: ReadonlyArray<TiCloudStorageRecordingTrack>;
|
|
74
|
+
reasons: ReadonlyArray<TiCloudStorageRecordingGapReason>;
|
|
75
|
+
}>;
|
|
76
|
+
export type TiCloudStorageExportProgress = Readonly<{
|
|
77
|
+
fraction: number;
|
|
78
|
+
coveredDurationMs: number;
|
|
79
|
+
}>;
|
|
80
|
+
export type TiCloudStorageExportSegment = Readonly<{
|
|
81
|
+
sourceRange: TiCloudStorageRecordingRange;
|
|
82
|
+
outputStartMs: number;
|
|
83
|
+
outputEndMs: number;
|
|
84
|
+
}>;
|
|
85
|
+
export declare const TiCloudStorageExportTermination: {
|
|
86
|
+
readonly exhausted: "exhausted";
|
|
87
|
+
readonly interrupted: "interrupted";
|
|
88
|
+
readonly cancelled: "cancelled";
|
|
89
|
+
readonly failed: "failed";
|
|
90
|
+
};
|
|
91
|
+
export type TiCloudStorageExportTermination = (typeof TiCloudStorageExportTermination)[keyof typeof TiCloudStorageExportTermination];
|
|
92
|
+
export type TiCloudStorageExportReport = Readonly<{
|
|
93
|
+
requestedRange: TiCloudStorageRecordingRange;
|
|
94
|
+
coveredDurationMs: number;
|
|
95
|
+
segments: ReadonlyArray<TiCloudStorageExportSegment>;
|
|
96
|
+
gaps: ReadonlyArray<TiCloudStorageRecordingGap>;
|
|
97
|
+
unprocessedRanges: ReadonlyArray<TiCloudStorageRecordingRange>;
|
|
98
|
+
complete: boolean;
|
|
99
|
+
termination: TiCloudStorageExportTermination;
|
|
100
|
+
cause: number;
|
|
101
|
+
}>;
|
|
102
|
+
export type TiCloudStorageExportOutcome = Readonly<{
|
|
103
|
+
code: number;
|
|
104
|
+
file: TiCloudStorageRecordingFile | null;
|
|
105
|
+
report: TiCloudStorageExportReport | null;
|
|
106
|
+
}>;
|
|
107
|
+
export type TiCloudStorageExportObserver = Readonly<{
|
|
108
|
+
onProgress?: (progress: number) => void;
|
|
109
|
+
onProgressDetail?: (progress: TiCloudStorageExportProgress) => void;
|
|
110
|
+
onRecordingGap?: (gap: TiCloudStorageRecordingGap) => void;
|
|
111
|
+
}>;
|
|
48
112
|
export declare const TiCloudStorageReplaySpeed: {
|
|
49
113
|
readonly x0_125: "x0_125";
|
|
50
114
|
readonly x0_25: "x0_25";
|
|
@@ -99,6 +163,7 @@ export declare class TiCloudStorage {
|
|
|
99
163
|
private token;
|
|
100
164
|
private identity;
|
|
101
165
|
private disposed;
|
|
166
|
+
private pendingAsyncOperations;
|
|
102
167
|
constructor(token: string);
|
|
103
168
|
static init(options: Readonly<{
|
|
104
169
|
appId: string;
|
|
@@ -111,19 +176,22 @@ export declare class TiCloudStorage {
|
|
|
111
176
|
listRecordings(startTimeMs: number, endTimeMs: number): Promise<TiCloudStorageRecordingRangesResult>;
|
|
112
177
|
listRecordingDays(startDate: string, endDate: string, timeZoneId?: string): Promise<TiCloudStorageRecordingDaysResult>;
|
|
113
178
|
createReplay(): TiCloudStorageReplay;
|
|
114
|
-
exportRecording(options: TiCloudStorageExportOptions,
|
|
179
|
+
exportRecording(options: TiCloudStorageExportOptions, observer?: ((progress: number) => void) | TiCloudStorageExportObserver): Resp<TiCloudStorageExportTask>;
|
|
115
180
|
dispose(): number;
|
|
181
|
+
private trackAsyncOperation;
|
|
116
182
|
private ensureIdentity;
|
|
117
183
|
}
|
|
118
184
|
export declare class TiCloudStorageReplay {
|
|
119
185
|
private readonly cloudStorage;
|
|
120
186
|
private identity;
|
|
121
187
|
private disposed;
|
|
188
|
+
private inCallback;
|
|
122
189
|
private currentSpeed;
|
|
123
190
|
private currentTime;
|
|
124
191
|
onTimeChanged: ((timeMs: number) => void) | null;
|
|
125
192
|
onError: ((code: number) => void) | null;
|
|
126
193
|
onCompleted: (() => void) | null;
|
|
194
|
+
onRecordingGap: ((gap: TiCloudStorageRecordingGap) => void) | null;
|
|
127
195
|
constructor(cloudStorage: TiCloudStorage);
|
|
128
196
|
get speed(): TiCloudStorageReplaySpeed;
|
|
129
197
|
get currentTimeMs(): number | null;
|
|
@@ -133,6 +201,7 @@ export declare class TiCloudStorageReplay {
|
|
|
133
201
|
seek(timeMs: number): number;
|
|
134
202
|
setSpeed(speed: TiCloudStorageReplaySpeed): number;
|
|
135
203
|
startRecording(options: TiCloudStorageStartRecordingOptions): Resp<TiCloudStorageRecordingTask>;
|
|
204
|
+
startRawDump(options: TiCloudStorageRawDumpOptions): Promise<Resp<TiRawDump>>;
|
|
136
205
|
stop(): number;
|
|
137
206
|
dispose(): number;
|
|
138
207
|
private command;
|
|
@@ -198,11 +267,21 @@ export declare class TiCloudStorageRecordingTask {
|
|
|
198
267
|
export declare class TiCloudStorageExportTask {
|
|
199
268
|
private readonly taskId;
|
|
200
269
|
private readonly owner;
|
|
201
|
-
private readonly onProgress?;
|
|
202
270
|
private resultPromise;
|
|
203
|
-
|
|
271
|
+
private completionPromise;
|
|
272
|
+
private readonly identity;
|
|
273
|
+
private currentProgressDetail;
|
|
274
|
+
private currentReport;
|
|
275
|
+
private readonly observer;
|
|
276
|
+
private terminal;
|
|
277
|
+
constructor(taskId: number, generation: number, owner: TiCloudStorage, observer?: ((progress: number) => void) | TiCloudStorageExportObserver);
|
|
204
278
|
get progress(): number;
|
|
279
|
+
get progressDetail(): TiCloudStorageExportProgress;
|
|
280
|
+
get report(): TiCloudStorageExportReport | null;
|
|
281
|
+
get completion(): Promise<TiCloudStorageExportOutcome>;
|
|
205
282
|
get result(): Promise<Resp<TiCloudStorageRecordingFile>>;
|
|
283
|
+
cancel(): number;
|
|
206
284
|
stop(): Promise<Resp<TiCloudStorageRecordingFile>>;
|
|
285
|
+
private handleEvent;
|
|
207
286
|
}
|
|
208
287
|
export {};
|
|
@@ -66,11 +66,6 @@ export declare const TiRtcVideoCodec: {
|
|
|
66
66
|
readonly mjpeg: "mjpeg";
|
|
67
67
|
};
|
|
68
68
|
export type TiRtcVideoCodec = (typeof TiRtcVideoCodec)[keyof typeof TiRtcVideoCodec];
|
|
69
|
-
export declare const TiRtcVideoEncoderCodec: {
|
|
70
|
-
readonly h264: "h264";
|
|
71
|
-
readonly mjpeg: "mjpeg";
|
|
72
|
-
};
|
|
73
|
-
export type TiRtcVideoEncoderCodec = (typeof TiRtcVideoEncoderCodec)[keyof typeof TiRtcVideoEncoderCodec];
|
|
74
69
|
export declare const TiRtcVideoFrameRate: {
|
|
75
70
|
readonly fps10: "fps10";
|
|
76
71
|
readonly fps15: "fps15";
|
|
@@ -145,6 +140,9 @@ export type TiRtcVideoOutputViewProps = ViewProps & Readonly<{
|
|
|
145
140
|
resizeMode?: 'contain' | 'cover' | 'stretch';
|
|
146
141
|
}>;
|
|
147
142
|
export type TiRtcAudioInputOptions = Readonly<{
|
|
143
|
+
/** Nano audio media: 1 PCM, 2 G711A, 3 AAC, 4 Opus, 5 AMR. Omitted or -1 uses codec. */
|
|
144
|
+
media?: number;
|
|
145
|
+
/** @deprecated Use media. The legacy default is g711a. */
|
|
148
146
|
codec?: TiRtcAudioCodec;
|
|
149
147
|
sampleRate?: TiRtcAudioSampleRate;
|
|
150
148
|
channels?: TiRtcAudioChannelCount;
|
|
@@ -153,7 +151,8 @@ export type TiRtcAudioInputOptions = Readonly<{
|
|
|
153
151
|
ansLevel?: TiRtcAudioAnsLevel;
|
|
154
152
|
}>;
|
|
155
153
|
export type TiRtcVideoInputOptions = Readonly<{
|
|
156
|
-
|
|
154
|
+
/** Nano video media: 66 H.264 (default) or 65 MJPEG. */
|
|
155
|
+
media?: number;
|
|
157
156
|
width?: number;
|
|
158
157
|
height?: number;
|
|
159
158
|
frameRate?: TiRtcVideoFrameRate;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tirtc-react-native",
|
|
3
|
-
"version": "2.5.0
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "TiRTC React Native SDK",
|
|
5
5
|
"homepage": "https://tange.ai/",
|
|
6
6
|
"repository": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"build": "node scripts/clean_generated_lib.mjs && tsc -p tsconfig.build.json && node scripts/freeze_build_identity.mjs && node scripts/write_codegen_component_specs.mjs",
|
|
50
50
|
"lint": "node test/source_guard.mjs",
|
|
51
51
|
"preflight:npm": "node scripts/npm_preflight.mjs",
|
|
52
|
-
"test": "node test/parity_guard.mjs && node test/package_artifact_guard.mjs && node test/lifecycle_contract_guard.mjs && node test/lifecycle_behavior_guard.mjs && node test/integration_contract_guard.mjs && node test/runner_schema_guard.mjs",
|
|
52
|
+
"test": "node test/parity_guard.mjs && node test/package_artifact_guard.mjs && node test/lifecycle_contract_guard.mjs && node test/lifecycle_behavior_guard.mjs && node test/integration_contract_guard.mjs && node test/runner_schema_guard.mjs && node --test test/source_fingerprint.test.mjs",
|
|
53
53
|
"test:contract-red": "node test/contract_red_summary.mjs",
|
|
54
54
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
55
55
|
"codegen:check": "node test/codegen_contract_guard.mjs"
|
package/src/audio_input.ts
CHANGED
|
@@ -21,6 +21,7 @@ export class TiRtcAudioInput {
|
|
|
21
21
|
private queue: Promise<unknown> = Promise.resolve();
|
|
22
22
|
private currentState: TiRtcInputState = 'idle';
|
|
23
23
|
private options: Required<TiRtcAudioInputOptions> = {
|
|
24
|
+
media: -1,
|
|
24
25
|
codec: 'g711a',
|
|
25
26
|
sampleRate: 'rate16k',
|
|
26
27
|
channels: 'mono',
|
|
@@ -58,8 +59,20 @@ export class TiRtcAudioInput {
|
|
|
58
59
|
if (!isPlainObject(options)) {
|
|
59
60
|
return Promise.resolve(TIRTC_ERROR_INVALID_ARGUMENT);
|
|
60
61
|
}
|
|
62
|
+
const media = options.media === undefined ? -1 : options.media;
|
|
63
|
+
const source = media === -1 ? (options.codec === undefined ? 'default' : 'legacy') : 'media';
|
|
64
|
+
const rawLegacy = options.codec === undefined ? 'omitted' :
|
|
65
|
+
['g711a', 'aac', 'pcm', 'opus', 'amr'].includes(options.codec) ? options.codec : 'invalid';
|
|
66
|
+
const legacyCodec = options.codec ?? 'g711a';
|
|
67
|
+
if (!Number.isInteger(media) || ![-1, 1, 2, 3, 4, 5].includes(media) ||
|
|
68
|
+
(media === -1 && !['g711a', 'aac', 'pcm', 'opus', 'amr'].includes(legacyCodec))) {
|
|
69
|
+
logRtcOutcome('audio_input_set_options', TIRTC_ERROR_INVALID_ARGUMENT,
|
|
70
|
+
` nano_media=${typeof media === 'number' ? media : typeof media} legacy_codec=${rawLegacy} source=${source}`);
|
|
71
|
+
return Promise.resolve(TIRTC_ERROR_INVALID_ARGUMENT);
|
|
72
|
+
}
|
|
61
73
|
const normalized = {
|
|
62
|
-
|
|
74
|
+
media,
|
|
75
|
+
codec: media === -1 ? legacyCodec : 'g711a' as const,
|
|
63
76
|
sampleRate: options.sampleRate ?? 'rate16k',
|
|
64
77
|
channels: options.channels ?? 'mono',
|
|
65
78
|
aecMode: options.aecMode ?? 'disabled',
|
|
@@ -72,6 +85,8 @@ export class TiRtcAudioInput {
|
|
|
72
85
|
return identity;
|
|
73
86
|
}
|
|
74
87
|
const code = await NativeTiRtc.audioInputSetOptions(identity.objectId, normalized);
|
|
88
|
+
logRtcOutcome('audio_input_set_options', code,
|
|
89
|
+
` nano_media=${media} legacy_codec=${rawLegacy} source=${source} sample_rate=${['rate8k', 'rate16k'].includes(normalized.sampleRate) ? normalized.sampleRate : 'invalid'} channels=${normalized.channels === 'mono' ? 'mono' : 'invalid'}`);
|
|
75
90
|
if (code === TIRTC_ERROR_OK) {
|
|
76
91
|
this.options = normalized;
|
|
77
92
|
}
|
|
@@ -100,16 +115,20 @@ export class TiRtcAudioInput {
|
|
|
100
115
|
}
|
|
101
116
|
|
|
102
117
|
start(): Promise<number> {
|
|
103
|
-
return this.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
return this.enqueue(async () => {
|
|
119
|
+
const identity = this.ensureIdentity();
|
|
120
|
+
if (typeof identity === 'number') {
|
|
121
|
+
logRtcOutcome('audio_input_start', identity);
|
|
122
|
+
return identity;
|
|
123
|
+
}
|
|
124
|
+
const wasRunning = this.state === 'running';
|
|
125
|
+
const code = await NativeTiRtc.audioInputStart(identity.objectId);
|
|
126
|
+
if (code !== TIRTC_ERROR_OK || !wasRunning) {
|
|
127
|
+
logRtcOutcome('audio_input_start', code,
|
|
128
|
+
` object_id=${identity.objectId} nano_media=${this.options.media} legacy_codec=${this.options.codec} sample_rate=${this.options.sampleRate} channels=${this.options.channels}`);
|
|
129
|
+
}
|
|
130
|
+
return code;
|
|
131
|
+
});
|
|
113
132
|
}
|
|
114
133
|
|
|
115
134
|
stop(): Promise<number> {
|
package/src/conn.ts
CHANGED
|
@@ -27,6 +27,12 @@ import type {
|
|
|
27
27
|
TiRtcOnConnStateChanged,
|
|
28
28
|
TiRtcOnConnStreamMessage,
|
|
29
29
|
} from './types';
|
|
30
|
+
import {
|
|
31
|
+
createRawDumpFromNative,
|
|
32
|
+
normalizeRawDumpIds,
|
|
33
|
+
TiRawDump,
|
|
34
|
+
type TiRtcRawDumpOptions,
|
|
35
|
+
} from './raw_dump';
|
|
30
36
|
|
|
31
37
|
export class TiRtcConn {
|
|
32
38
|
private identity: NativeIdentity | null = null;
|
|
@@ -59,6 +65,23 @@ export class TiRtcConn {
|
|
|
59
65
|
return typeof identity === 'number' ? recordingFailure(identity) : startRecording(identity.objectId, options);
|
|
60
66
|
}
|
|
61
67
|
|
|
68
|
+
async startRawDump(options: TiRtcRawDumpOptions): Promise<Resp<TiRawDump>> {
|
|
69
|
+
if (options === null || typeof options !== 'object') return recordingFailure(TIRTC_ERROR_INVALID_ARGUMENT);
|
|
70
|
+
const audio = normalizeRawDumpIds(options.audioStreamIds ?? [], 15);
|
|
71
|
+
const video = normalizeRawDumpIds(options.videoStreamIds ?? [], 15);
|
|
72
|
+
const uplinkAudio = normalizeRawDumpIds(options.uplinkAudioStreamIds ?? [], 15);
|
|
73
|
+
if (audio === null || video === null || uplinkAudio === null ||
|
|
74
|
+
(audio.length === 0 && video.length === 0 && uplinkAudio.length === 0)) {
|
|
75
|
+
return recordingFailure(TIRTC_ERROR_INVALID_ARGUMENT);
|
|
76
|
+
}
|
|
77
|
+
const identity = this.ensureIdentity();
|
|
78
|
+
if (typeof identity === 'number') return recordingFailure(identity);
|
|
79
|
+
const result = await NativeTiRtc.connStartRawDump(identity.objectId, audio, video, uplinkAudio);
|
|
80
|
+
return result.code === 0 && result.dumpId !== null
|
|
81
|
+
? {success: true, code: null, message: null, data: createRawDumpFromNative(result.dumpId)}
|
|
82
|
+
: recordingFailure(result.code);
|
|
83
|
+
}
|
|
84
|
+
|
|
62
85
|
get state(): TiRtcConnState {
|
|
63
86
|
if (this.identity !== null && !this.disposed) {
|
|
64
87
|
const result = NativeTiRtc.connGetState(this.identity.objectId);
|
package/src/events.ts
CHANGED
|
@@ -16,20 +16,25 @@ function ensureSubscribed(): void {
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
subscription = NativeTiRtc.onTiRtcEvent((event) => {
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
handler(event);
|
|
19
|
+
if (event.type === 'tiCloudStorageCallbackReady') {
|
|
20
|
+
const pending = NativeTiRtc.tiCloudStorageTakeCallback();
|
|
21
|
+
if (pending === null) return;
|
|
22
|
+
try {
|
|
23
|
+
deliver(pending.event);
|
|
24
|
+
} finally {
|
|
25
|
+
NativeTiRtc.tiCloudStorageAcknowledgeCallback(pending.deliveryId);
|
|
26
|
+
}
|
|
28
27
|
return;
|
|
29
28
|
}
|
|
29
|
+
deliver(event);
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
function deliver(event: NativeTiRtcEvent): void {
|
|
34
|
+
if (!isPositiveInt32(event.objectId) || !isPositiveInt32(event.generation)) return;
|
|
35
|
+
handlers.get(eventKey({objectId: event.objectId, generation: event.generation}))?.(event);
|
|
36
|
+
}
|
|
37
|
+
|
|
33
38
|
export function registerNativeEventHandler(identity: NativeIdentity, handler: NativeEventHandler): void {
|
|
34
39
|
handlers.set(eventKey(identity), handler);
|
|
35
40
|
ensureSubscribed();
|
package/src/index.ts
CHANGED
|
@@ -9,7 +9,6 @@ export {
|
|
|
9
9
|
TiRtcAudioAgcLevel,
|
|
10
10
|
TiRtcAudioAnsLevel,
|
|
11
11
|
TiRtcVideoCodec,
|
|
12
|
-
TiRtcVideoEncoderCodec,
|
|
13
12
|
TiRtcVideoFrameRate,
|
|
14
13
|
TiRtcCameraFacing,
|
|
15
14
|
TiRtcVideoDecoderPreference,
|
|
@@ -60,6 +59,13 @@ export {TiRtcAudioInput} from './audio_input';
|
|
|
60
59
|
export {TiRtcVideoInput, TiRtcVideoInputPreview} from './video_input';
|
|
61
60
|
export {TiRtcLogging} from './logging';
|
|
62
61
|
export {TiRtcRecordingTask} from './recording';
|
|
62
|
+
export {TiRawDump} from './raw_dump';
|
|
63
|
+
export type {
|
|
64
|
+
TiRtcRawDumpOptions,
|
|
65
|
+
TiCloudStorageRawDumpOptions,
|
|
66
|
+
TiRawDumpStopReason,
|
|
67
|
+
TiRawDumpArchive,
|
|
68
|
+
} from './raw_dump';
|
|
63
69
|
export type {
|
|
64
70
|
Resp,
|
|
65
71
|
TiRtcGalleryAsset,
|
|
@@ -95,6 +101,9 @@ export {
|
|
|
95
101
|
TI_CLOUD_STORAGE_ERROR_NETWORK_UNAVAILABLE,
|
|
96
102
|
TI_CLOUD_STORAGE_ERROR_ENDPOINT_DNS_RESOLUTION_FAILED,
|
|
97
103
|
TiCloudStorageReplaySpeed,
|
|
104
|
+
TiCloudStorageRecordingTrackKind,
|
|
105
|
+
TiCloudStorageRecordingGapReason,
|
|
106
|
+
TiCloudStorageExportTermination,
|
|
98
107
|
TiCloudStorageAudioOutputState,
|
|
99
108
|
TiCloudStorageVideoOutputState,
|
|
100
109
|
TiCloudStorage,
|
|
@@ -107,6 +116,13 @@ export {
|
|
|
107
116
|
} from './storage';
|
|
108
117
|
export type {
|
|
109
118
|
TiCloudStorageRecordingRange,
|
|
119
|
+
TiCloudStorageRecordingTrack,
|
|
120
|
+
TiCloudStorageRecordingGap,
|
|
121
|
+
TiCloudStorageExportProgress,
|
|
122
|
+
TiCloudStorageExportSegment,
|
|
123
|
+
TiCloudStorageExportReport,
|
|
124
|
+
TiCloudStorageExportOutcome,
|
|
125
|
+
TiCloudStorageExportObserver,
|
|
110
126
|
TiCloudStorageRecordingRangesResult,
|
|
111
127
|
TiCloudStorageRecordingDay,
|
|
112
128
|
TiCloudStorageRecordingDaysResult,
|
package/src/native.ts
CHANGED
|
@@ -3,4 +3,10 @@ import NativeTiRtcVideoInputPreview from './specs/TiRtcVideoInputPreviewNativeCo
|
|
|
3
3
|
import NativeTiRtcVideoOutputView from './specs/TiRtcVideoOutputViewNativeComponent';
|
|
4
4
|
|
|
5
5
|
export {NativeTiRtc, NativeTiRtcVideoOutputView, NativeTiRtcVideoInputPreview};
|
|
6
|
-
export type {
|
|
6
|
+
export type {
|
|
7
|
+
NativeTiRtcEvent,
|
|
8
|
+
NativeTiCloudStorageExportProgress,
|
|
9
|
+
NativeTiCloudStorageExportReport,
|
|
10
|
+
NativeTiCloudStorageRecordingGap,
|
|
11
|
+
NativeRawDumpArchive,
|
|
12
|
+
} from './specs/NativeTiRtc';
|
package/src/raw_dump.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {isFiniteSafeInteger, TIRTC_ERROR_INVALID_ARGUMENT} from './errors';
|
|
2
|
+
import {NativeTiRtc, type NativeRawDumpArchive} from './native';
|
|
3
|
+
import type {Resp} from './recording';
|
|
4
|
+
|
|
5
|
+
export type TiRawDumpStopReason =
|
|
6
|
+
| 'unknown' | 'user' | 'timeLimit' | 'byteLimit' | 'sourceClosed'
|
|
7
|
+
| 'resourceLimit' | 'writeFailed';
|
|
8
|
+
|
|
9
|
+
export type TiRtcRawDumpOptions = Readonly<{
|
|
10
|
+
/** Remote downlink audio stream IDs. */
|
|
11
|
+
audioStreamIds?: ReadonlyArray<number>;
|
|
12
|
+
/** Remote downlink video stream IDs. */
|
|
13
|
+
videoStreamIds?: ReadonlyArray<number>;
|
|
14
|
+
/** Local uplink audio stream IDs used by TiRtcAudioInput.attach. */
|
|
15
|
+
uplinkAudioStreamIds?: ReadonlyArray<number>;
|
|
16
|
+
}>;
|
|
17
|
+
|
|
18
|
+
export type TiCloudStorageRawDumpOptions = Readonly<{
|
|
19
|
+
audioChannelIds?: ReadonlyArray<number>;
|
|
20
|
+
videoChannelIds?: ReadonlyArray<number>;
|
|
21
|
+
}>;
|
|
22
|
+
|
|
23
|
+
export type TiRawDumpArchive = Readonly<{
|
|
24
|
+
captureId: string; path: string; size: number; sha256: string; capturedDurationMs: number;
|
|
25
|
+
captureComplete: boolean; stopReason: TiRawDumpStopReason;
|
|
26
|
+
unsavedPacketCount: number; unsavedByteCount: number; empty: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
const reasons: ReadonlyArray<TiRawDumpStopReason> = [
|
|
30
|
+
'unknown', 'user', 'timeLimit', 'byteLimit', 'sourceClosed', 'resourceLimit', 'writeFailed',
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
function archiveFromNative(value: NativeRawDumpArchive): TiRawDumpArchive {
|
|
34
|
+
return {...value, stopReason: reasons[value.stopReason] ?? 'unknown'};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function failure<T>(code: number): Resp<T> {
|
|
38
|
+
return {success: false, code, message: null, data: null};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function normalizeRawDumpIds(
|
|
42
|
+
value: unknown,
|
|
43
|
+
maximum: number,
|
|
44
|
+
): ReadonlyArray<number> | null {
|
|
45
|
+
if (!Array.isArray(value)) return null;
|
|
46
|
+
const result = new Set<number>();
|
|
47
|
+
for (const item of value) {
|
|
48
|
+
if (!isFiniteSafeInteger(item) || item < 0 || item > maximum) return null;
|
|
49
|
+
result.add(item);
|
|
50
|
+
}
|
|
51
|
+
return [...result];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class TiRawDump {
|
|
55
|
+
private stopPromise: Promise<Resp<TiRawDumpArchive>> | null = null;
|
|
56
|
+
|
|
57
|
+
private constructor(private readonly nativeId: number) {}
|
|
58
|
+
|
|
59
|
+
stop(): Promise<Resp<TiRawDumpArchive>> {
|
|
60
|
+
if (this.stopPromise === null) {
|
|
61
|
+
this.stopPromise = NativeTiRtc.rawDumpStop(this.nativeId).then((result) => {
|
|
62
|
+
if (result.code !== 0 || result.archive === null) {
|
|
63
|
+
if (!result.terminal) this.stopPromise = null;
|
|
64
|
+
return failure<TiRawDumpArchive>(result.code);
|
|
65
|
+
}
|
|
66
|
+
const archive = archiveFromNative(result.archive);
|
|
67
|
+
return {success: true, code: null, message: null, data: archive};
|
|
68
|
+
}).catch(() => {
|
|
69
|
+
this.stopPromise = null;
|
|
70
|
+
return failure<TiRawDumpArchive>(TIRTC_ERROR_INVALID_ARGUMENT);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return this.stopPromise!;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async dispose(): Promise<number> {
|
|
77
|
+
const result = await this.stop();
|
|
78
|
+
return result.success ? 0 : result.code ?? TIRTC_ERROR_INVALID_ARGUMENT;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function createRawDumpFromNative(nativeId: number): TiRawDump {
|
|
83
|
+
return Reflect.construct(TiRawDump, [nativeId]) as TiRawDump;
|
|
84
|
+
}
|
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,6 +298,11 @@ 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
|
|
|
@@ -251,6 +312,8 @@ interface Spec extends TurboModule {
|
|
|
251
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>;
|