realtime-avatar 0.27.2 → 0.27.3
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 +14 -1
- package/dist/{chunk-SP5SYYSS.js → chunk-QBOIOZ3O.js} +1 -1
- package/dist/{chunk-YR5NJTEO.js → chunk-W4DGBG4Z.js} +10 -4
- package/dist/express.d.ts +2 -2
- package/dist/express.js +2 -2
- package/dist/hono.d.ts +2 -2
- package/dist/hono.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/nextjs.d.ts +2 -2
- package/dist/nextjs.js +2 -2
- package/dist/{proxy-client-DW_EOvmE.d.ts → proxy-client-BAY77sJZ.d.ts} +35 -0
- package/dist/react-native.d.ts +2 -2
- package/dist/react-native.js +9 -3
- package/dist/react.d.ts +4 -4
- package/dist/react.js +70 -24
- package/dist/{recording-DjswTx5B.d.ts → recording-ydFVySSd.d.ts} +35 -0
- package/dist/recording.d.ts +9 -3
- package/dist/recording.js +23 -8
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/tanstack-start.d.ts +2 -2
- package/dist/tanstack-start.js +2 -2
- package/dist/{types-D_s7ff7w.d.ts → types-kgmS7ECd.d.ts} +127 -8
- package/dist/{types-BH9O5leB.d.ts → types-lgS4Z9rd.d.ts} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,8 +86,12 @@ if (recording.status === "ready") {
|
|
|
86
86
|
|
|
87
87
|
Omitted or `"off"` disables recording. `"audio"` records published user and avatar audio;
|
|
88
88
|
`"video"` records published video without audio; `"audio_video"` keeps both on one media timeline.
|
|
89
|
+
`"participants"` keeps each participant's voice and camera in its own continuous file.
|
|
90
|
+
`"tracks"` saves separate published audio/video tracks and replacement-camera segments;
|
|
91
|
+
use `listRecordings({ sessionId: call.sessionId })` because its initial grant omits recording
|
|
92
|
+
metadata so older installed clients remain compatible.
|
|
89
93
|
Recording does not enable the microphone, camera, or screen sharing. Only tracks that participants
|
|
90
|
-
authorize and publish can be recorded.
|
|
94
|
+
authorize and publish can be recorded.
|
|
91
95
|
|
|
92
96
|
Recordings may finish processing after a call ends. Use `listRecordings({ sessionId })` to find
|
|
93
97
|
them, or refresh `getRecording(recordingId)` while processing. These methods and
|
|
@@ -98,6 +102,15 @@ default); each URL expires at `expiresAt` (up to one hour, capped by retention).
|
|
|
98
102
|
access before replaying or seeking after expiry. An expired URL does not delete the file.
|
|
99
103
|
Treat the URL as private: anyone who has it can play that file until it expires.
|
|
100
104
|
|
|
105
|
+
For participant replay, pass every ready `{ recording, url }` asset to `RecordingPlayer`
|
|
106
|
+
from `realtime-avatar/react`. It accepts combined participant MP4s and separate audio/video
|
|
107
|
+
segments, including camera republication. Follow `nextCursor` when listing a session's recordings.
|
|
108
|
+
The optional `mediaStartOffsetMs` preserves a file's first native media timestamp; it delays
|
|
109
|
+
that track's visibility without shifting its playback clock. The player preserves native
|
|
110
|
+
timestamps across gaps and uses the artifact's duration instead of an initially truncated
|
|
111
|
+
WebM container duration. `mediaMutedIntervalsMs` hides a muted camera while keeping media
|
|
112
|
+
clocks and audio running, including audio carried by a legacy combined file.
|
|
113
|
+
|
|
101
114
|
## Optional connection history
|
|
102
115
|
|
|
103
116
|
Set `connectionHistory: true` in the server's `startCall` policy when the caller needs a
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sessionModeSchema, liveKitSessionReleaseReasonSchema, RealtimeAvatar, ROUTE_TIMEOUT_MS, isQueued, RealtimeAvatarHttpError, RealtimeAvatarError } from './chunk-
|
|
1
|
+
import { sessionModeSchema, liveKitSessionReleaseReasonSchema, RealtimeAvatar, ROUTE_TIMEOUT_MS, isQueued, RealtimeAvatarHttpError, RealtimeAvatarError } from './chunk-W4DGBG4Z.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
// ../http-client/src/generated/error-semantics.ts
|
|
@@ -239,13 +239,17 @@ var schema26 = z.strictObject({
|
|
|
239
239
|
var clipLibraryResponseSchema = schema24;
|
|
240
240
|
var clipLibraryUpdateSchema = schema26;
|
|
241
241
|
var RECORDED_MEDIA_MODES = ["audio", "video", "audio_video"];
|
|
242
|
-
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices.");
|
|
242
|
+
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants", "tracks"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices. tracks saves each published participant audio/video track separately; list recordings by session after capture.");
|
|
243
243
|
var RECORDING_STATUSES = ["pending", "recording", "processing", "ready", "failed", "expired"];
|
|
244
244
|
z.enum(RECORDING_STATUSES);
|
|
245
245
|
var recordingParticipantSchema = z.object({
|
|
246
246
|
participantIdentity: z.string().min(1).max(160),
|
|
247
247
|
role: z.enum(["user", "avatar"])
|
|
248
248
|
}).strict();
|
|
249
|
+
var recordingMutedIntervalSchema = z.object({
|
|
250
|
+
startMs: z.number().int().min(0),
|
|
251
|
+
endMs: z.number().int().positive()
|
|
252
|
+
}).strict().refine((interval) => interval.endMs > interval.startMs, "Muted interval must end after it starts");
|
|
249
253
|
var recordingMetadataSchema = z.object({
|
|
250
254
|
sessionId: z.string().min(1),
|
|
251
255
|
recordingId: z.string().min(1),
|
|
@@ -254,13 +258,15 @@ var recordingMetadataSchema = z.object({
|
|
|
254
258
|
retainedUntil: z.string().datetime({ offset: true }),
|
|
255
259
|
participant: recordingParticipantSchema.optional(),
|
|
256
260
|
mediaStartedAt: z.string().datetime({ offset: true }).optional(),
|
|
257
|
-
mediaEndedAt: z.string().datetime({ offset: true }).optional()
|
|
261
|
+
mediaEndedAt: z.string().datetime({ offset: true }).optional(),
|
|
262
|
+
mediaStartOffsetMs: z.number().int().min(0).optional().describe("First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero."),
|
|
263
|
+
mediaMutedIntervalsMs: z.array(recordingMutedIntervalSchema).optional().describe("Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals.")
|
|
258
264
|
});
|
|
259
265
|
var recordingArtifactSchema = z.discriminatedUnion("status", [
|
|
260
266
|
recordingMetadataSchema.extend({ status: z.enum(["pending", "recording", "processing", "expired"]) }).strict(),
|
|
261
267
|
recordingMetadataSchema.extend({
|
|
262
268
|
status: z.literal("ready"),
|
|
263
|
-
mediaType: z.enum(["audio/mp4", "video/mp4"]),
|
|
269
|
+
mediaType: z.enum(["audio/mp4", "video/mp4", "audio/ogg", "video/webm"]),
|
|
264
270
|
sizeBytes: z.number().int().positive(),
|
|
265
271
|
durationMs: z.number().int().nonnegative().nullable()
|
|
266
272
|
}).strict(),
|
|
@@ -669,7 +675,7 @@ var liveKitSessionReleaseReasonSchema = z.enum([
|
|
|
669
675
|
|
|
670
676
|
// ../http-client/src/client.ts
|
|
671
677
|
var DEFAULT_BASE_URL = "https://realtimeavatar.ai/api/v1";
|
|
672
|
-
var SDK_VERSION = "0.27.
|
|
678
|
+
var SDK_VERSION = "0.27.3";
|
|
673
679
|
var RealtimeAvatar = class {
|
|
674
680
|
#apiKey;
|
|
675
681
|
#baseUrl;
|
package/dist/express.d.ts
CHANGED
package/dist/express.js
CHANGED
package/dist/hono.d.ts
CHANGED
package/dist/hono.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as CallPolicy, C as CallMode, S as StartCallResult, E as EndCallOptions, A as Avatar, b as AvatarUpdate, c as AvatarSourceSwap, d as ClipLibraryDeclaration, e as ClipLibraryUpdate, L as LoopRedirect, f as ClipLibrary, g as AssetKind, h as Asset, i as ListSessionsOptions, U as UsageSessionPage, j as UsageSession, k as ListRecordingsQuery, l as ListRecordingsResponse, R as RecordingArtifact, m as RecordingAccessResponse, n as CreditBalance, T as TranscriptPayload } from './types-
|
|
2
|
-
export { o as AvatarClip, p as CallConnection, q as CallQueued, r as ClipDeclaration, s as ClipLibraryPlan, t as ClipSource, u as ContextMessage, v as EndCallReason, w as ExternalLlm, x as RecordingArtifactStatus, y as RecordingMode, V as VideoPolicy, z as isQueued, B as listRecordingsResponseSchema, D as recordingAccessResponseSchema, F as recordingArtifactSchema, G as recordingModeSchema } from './types-
|
|
1
|
+
import { a as CallPolicy, C as CallMode, S as StartCallResult, E as EndCallOptions, A as Avatar, b as AvatarUpdate, c as AvatarSourceSwap, d as ClipLibraryDeclaration, e as ClipLibraryUpdate, L as LoopRedirect, f as ClipLibrary, g as AssetKind, h as Asset, i as ListSessionsOptions, U as UsageSessionPage, j as UsageSession, k as ListRecordingsQuery, l as ListRecordingsResponse, R as RecordingArtifact, m as RecordingAccessResponse, n as CreditBalance, T as TranscriptPayload } from './types-kgmS7ECd.js';
|
|
2
|
+
export { o as AvatarClip, p as CallConnection, q as CallQueued, r as ClipDeclaration, s as ClipLibraryPlan, t as ClipSource, u as ContextMessage, v as EndCallReason, w as ExternalLlm, x as RecordingArtifactStatus, y as RecordingMode, V as VideoPolicy, z as isQueued, B as listRecordingsResponseSchema, D as recordingAccessResponseSchema, F as recordingArtifactSchema, G as recordingModeSchema } from './types-kgmS7ECd.js';
|
|
3
3
|
import { ConnectionHistoryResponse } from './connection-history.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, listRecordingsResponseSchema, recordingAccessResponseSchema, recordingArtifactSchema, recordingModeSchema, verifyTranscript } from './chunk-
|
|
1
|
+
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, listRecordingsResponseSchema, recordingAccessResponseSchema, recordingArtifactSchema, recordingModeSchema, verifyTranscript } from './chunk-W4DGBG4Z.js';
|
|
2
2
|
import './chunk-MCIXU6XP.js';
|
package/dist/nextjs.d.ts
CHANGED
package/dist/nextjs.js
CHANGED
|
@@ -266,6 +266,11 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
266
266
|
}, z.core.$strict>>;
|
|
267
267
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
268
268
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
269
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
270
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
271
|
+
startMs: z.ZodNumber;
|
|
272
|
+
endMs: z.ZodNumber;
|
|
273
|
+
}, z.core.$strict>>>;
|
|
269
274
|
status: z.ZodEnum<{
|
|
270
275
|
pending: "pending";
|
|
271
276
|
recording: "recording";
|
|
@@ -291,10 +296,17 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
291
296
|
}, z.core.$strict>>;
|
|
292
297
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
293
298
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
299
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
300
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
301
|
+
startMs: z.ZodNumber;
|
|
302
|
+
endMs: z.ZodNumber;
|
|
303
|
+
}, z.core.$strict>>>;
|
|
294
304
|
status: z.ZodLiteral<"ready">;
|
|
295
305
|
mediaType: z.ZodEnum<{
|
|
296
306
|
"audio/mp4": "audio/mp4";
|
|
297
307
|
"video/mp4": "video/mp4";
|
|
308
|
+
"audio/ogg": "audio/ogg";
|
|
309
|
+
"video/webm": "video/webm";
|
|
298
310
|
}>;
|
|
299
311
|
sizeBytes: z.ZodNumber;
|
|
300
312
|
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
@@ -317,6 +329,11 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
317
329
|
}, z.core.$strict>>;
|
|
318
330
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
319
331
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
332
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
333
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
334
|
+
startMs: z.ZodNumber;
|
|
335
|
+
endMs: z.ZodNumber;
|
|
336
|
+
}, z.core.$strict>>>;
|
|
320
337
|
status: z.ZodLiteral<"failed">;
|
|
321
338
|
errorCode: z.ZodEnum<{
|
|
322
339
|
recording_failed: "recording_failed";
|
|
@@ -329,6 +346,7 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
329
346
|
audio_video: "audio_video";
|
|
330
347
|
off: "off";
|
|
331
348
|
participants: "participants";
|
|
349
|
+
tracks: "tracks";
|
|
332
350
|
}>>;
|
|
333
351
|
recordings: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
334
352
|
sessionId: z.ZodString;
|
|
@@ -349,6 +367,11 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
349
367
|
}, z.core.$strict>>;
|
|
350
368
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
351
369
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
370
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
371
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
372
|
+
startMs: z.ZodNumber;
|
|
373
|
+
endMs: z.ZodNumber;
|
|
374
|
+
}, z.core.$strict>>>;
|
|
352
375
|
status: z.ZodEnum<{
|
|
353
376
|
pending: "pending";
|
|
354
377
|
recording: "recording";
|
|
@@ -374,10 +397,17 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
374
397
|
}, z.core.$strict>>;
|
|
375
398
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
376
399
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
400
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
401
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
402
|
+
startMs: z.ZodNumber;
|
|
403
|
+
endMs: z.ZodNumber;
|
|
404
|
+
}, z.core.$strict>>>;
|
|
377
405
|
status: z.ZodLiteral<"ready">;
|
|
378
406
|
mediaType: z.ZodEnum<{
|
|
379
407
|
"audio/mp4": "audio/mp4";
|
|
380
408
|
"video/mp4": "video/mp4";
|
|
409
|
+
"audio/ogg": "audio/ogg";
|
|
410
|
+
"video/webm": "video/webm";
|
|
381
411
|
}>;
|
|
382
412
|
sizeBytes: z.ZodNumber;
|
|
383
413
|
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
@@ -400,6 +430,11 @@ declare const liveKitSessionGrantSchema: z.ZodObject<{
|
|
|
400
430
|
}, z.core.$strict>>;
|
|
401
431
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
402
432
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
433
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
434
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
435
|
+
startMs: z.ZodNumber;
|
|
436
|
+
endMs: z.ZodNumber;
|
|
437
|
+
}, z.core.$strict>>>;
|
|
403
438
|
status: z.ZodLiteral<"failed">;
|
|
404
439
|
errorCode: z.ZodEnum<{
|
|
405
440
|
recording_failed: "recording_failed";
|
package/dist/react-native.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LiveKitRoomProps } from '@livekit/react-native';
|
|
2
2
|
export { AudioSession, VideoTrack, VideoTrackProps, registerGlobals } from '@livekit/react-native';
|
|
3
|
-
import { L as LiveKitSessionGrant, A as AvatarVideoFit } from './proxy-client-
|
|
4
|
-
export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarConnectionDetails, h as AvatarSessionClient, B as BehaviorSnapshot, C as CallTranscript, i as CallTranscriptSegment, j as CartesiaTtsModel, k as ClipResult, l as ClosingTurnResult, m as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, n as DEFAULT_CREDITS_LOW_LEAD_SECONDS, o as DEFAULT_GOVERNOR_CONFIG, p as DEFAULT_GRACE_CEILING_SECONDS, q as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, r as DEFAULT_IDLE_SECONDS, s as DEFAULT_IDLE_WARN_LEAD_SECONDS, t as DEFAULT_READY_TIMEOUT_SECONDS, u as DEFAULT_TURN_TIMEOUT_SECONDS, v as DeclaredInputSource, E as EndReason, w as EndedEvent, x as ExtendResult, F as FishTtsModel, y as FreezeReadingFn, G as Governor, z as GovernorAction, H as GovernorConfig, I as GovernorSignal, J as GovernorState, K as GraceWindowClosedEvent, M as GraceWindowOpenEvent, N as GraceWindowState, O as IdleWarningEvent, P as InboundRtpCursor, Q as InboundRtpReading, R as KnownBehaviorState, S as LLMProvider, T as LLMSelection, U as LiveKitAvatarGrantState, V as LiveKitAvatarGrantStatus, W as LiveKitCapacityState, X as LiveKitConnectionStatus, Y as LiveKitSessionRequest, Z as LiveKitSessionStartResult, _ as MAX_RECONNECT_ATTEMPTS, $ as MAX_SESSION_INSTRUCTIONS_CHARS, a0 as ProxyClientOptions, a1 as QualityCap, a2 as RECONNECT_BACKOFF_MS, a3 as RealtimeAvatarRequestOptions, a4 as RealtimeSessionApi, a5 as RealtimeSessionMedia, a6 as RealtimeSessionRoomSinks, a7 as ReconnectPolicy, a8 as ReconnectingEvent, a9 as RecoveryState, aa as RetryStep, ab as SendTurnOptions, ac as SessionBehavior, ad as SessionClip, ae as SessionClocks, af as SessionEndReason, ag as SessionLifecycleApi, ah as SessionLifecyclePhase, ai as SessionLifecyclePhaseKind, aj as SessionLifecycleRoomBridge, ak as SessionLifecycleRoomBridgeProps, al as SessionReadinessFailure, am as SurfaceLayers, an as TranscriptSender, ao as TranscriptSenderOptions, ap as TurnState, aq as TurnTimeoutEvent, ar as UseAvatarQualityGovernorInput, as as UseLiveKitAvatarGrantInput, at as UseRealtimeSessionInput, au as UseSessionLifecycleInput, av as VoiceSpec, aw as VoiceSpecInput, ax as capacityErrorFromBusy, ay as capacityStateFromGrant, az as createProxyClient, aA as isNativeLiveTrackSubscribed, aB as knownBehaviorStates, aC as mapTurnState, aD as readInboundRtp, aE as sessionBehaviorSchema, aF as sessionClipSchema, aG as splitCallTranscript, aH as useAvatarAdaptivePlayoutDelay, aI as useAvatarCamera, aJ as useAvatarPlayoutDelay, aK as useAvatarQualityGovernor, aL as useCallTranscript, aM as useLiveKitAvatarGrant, aN as useLiveTrackProducing, aO as useMicLease, aP as useRealtimeSession, aQ as useReleaseMicLeaseOnTrackEnded, aR as useSessionLifecycle } from './proxy-client-
|
|
3
|
+
import { L as LiveKitSessionGrant, A as AvatarVideoFit } from './proxy-client-BAY77sJZ.js';
|
|
4
|
+
export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarConnectionDetails, h as AvatarSessionClient, B as BehaviorSnapshot, C as CallTranscript, i as CallTranscriptSegment, j as CartesiaTtsModel, k as ClipResult, l as ClosingTurnResult, m as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, n as DEFAULT_CREDITS_LOW_LEAD_SECONDS, o as DEFAULT_GOVERNOR_CONFIG, p as DEFAULT_GRACE_CEILING_SECONDS, q as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, r as DEFAULT_IDLE_SECONDS, s as DEFAULT_IDLE_WARN_LEAD_SECONDS, t as DEFAULT_READY_TIMEOUT_SECONDS, u as DEFAULT_TURN_TIMEOUT_SECONDS, v as DeclaredInputSource, E as EndReason, w as EndedEvent, x as ExtendResult, F as FishTtsModel, y as FreezeReadingFn, G as Governor, z as GovernorAction, H as GovernorConfig, I as GovernorSignal, J as GovernorState, K as GraceWindowClosedEvent, M as GraceWindowOpenEvent, N as GraceWindowState, O as IdleWarningEvent, P as InboundRtpCursor, Q as InboundRtpReading, R as KnownBehaviorState, S as LLMProvider, T as LLMSelection, U as LiveKitAvatarGrantState, V as LiveKitAvatarGrantStatus, W as LiveKitCapacityState, X as LiveKitConnectionStatus, Y as LiveKitSessionRequest, Z as LiveKitSessionStartResult, _ as MAX_RECONNECT_ATTEMPTS, $ as MAX_SESSION_INSTRUCTIONS_CHARS, a0 as ProxyClientOptions, a1 as QualityCap, a2 as RECONNECT_BACKOFF_MS, a3 as RealtimeAvatarRequestOptions, a4 as RealtimeSessionApi, a5 as RealtimeSessionMedia, a6 as RealtimeSessionRoomSinks, a7 as ReconnectPolicy, a8 as ReconnectingEvent, a9 as RecoveryState, aa as RetryStep, ab as SendTurnOptions, ac as SessionBehavior, ad as SessionClip, ae as SessionClocks, af as SessionEndReason, ag as SessionLifecycleApi, ah as SessionLifecyclePhase, ai as SessionLifecyclePhaseKind, aj as SessionLifecycleRoomBridge, ak as SessionLifecycleRoomBridgeProps, al as SessionReadinessFailure, am as SurfaceLayers, an as TranscriptSender, ao as TranscriptSenderOptions, ap as TurnState, aq as TurnTimeoutEvent, ar as UseAvatarQualityGovernorInput, as as UseLiveKitAvatarGrantInput, at as UseRealtimeSessionInput, au as UseSessionLifecycleInput, av as VoiceSpec, aw as VoiceSpecInput, ax as capacityErrorFromBusy, ay as capacityStateFromGrant, az as createProxyClient, aA as isNativeLiveTrackSubscribed, aB as knownBehaviorStates, aC as mapTurnState, aD as readInboundRtp, aE as sessionBehaviorSchema, aF as sessionClipSchema, aG as splitCallTranscript, aH as useAvatarAdaptivePlayoutDelay, aI as useAvatarCamera, aJ as useAvatarPlayoutDelay, aK as useAvatarQualityGovernor, aL as useCallTranscript, aM as useLiveKitAvatarGrant, aN as useLiveTrackProducing, aO as useMicLease, aP as useRealtimeSession, aQ as useReleaseMicLeaseOnTrackEnded, aR as useSessionLifecycle } from './proxy-client-BAY77sJZ.js';
|
|
5
5
|
import { ReactNode, ReactElement } from 'react';
|
|
6
6
|
import { StyleProp, ViewStyle } from 'react-native';
|
|
7
7
|
export { useChat, useConnectionState, useLocalParticipant, useRoomContext, useTrackToggle, useTranscriptions, useVoiceAssistant } from '@livekit/components-react';
|
package/dist/react-native.js
CHANGED
|
@@ -1630,13 +1630,17 @@ var styles = StyleSheet.create({
|
|
|
1630
1630
|
}
|
|
1631
1631
|
});
|
|
1632
1632
|
var RECORDED_MEDIA_MODES = ["audio", "video", "audio_video"];
|
|
1633
|
-
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices.");
|
|
1633
|
+
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants", "tracks"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices. tracks saves each published participant audio/video track separately; list recordings by session after capture.");
|
|
1634
1634
|
var RECORDING_STATUSES = ["pending", "recording", "processing", "ready", "failed", "expired"];
|
|
1635
1635
|
z.enum(RECORDING_STATUSES);
|
|
1636
1636
|
var recordingParticipantSchema = z.object({
|
|
1637
1637
|
participantIdentity: z.string().min(1).max(160),
|
|
1638
1638
|
role: z.enum(["user", "avatar"])
|
|
1639
1639
|
}).strict();
|
|
1640
|
+
var recordingMutedIntervalSchema = z.object({
|
|
1641
|
+
startMs: z.number().int().min(0),
|
|
1642
|
+
endMs: z.number().int().positive()
|
|
1643
|
+
}).strict().refine((interval) => interval.endMs > interval.startMs, "Muted interval must end after it starts");
|
|
1640
1644
|
var recordingMetadataSchema = z.object({
|
|
1641
1645
|
sessionId: z.string().min(1),
|
|
1642
1646
|
recordingId: z.string().min(1),
|
|
@@ -1645,13 +1649,15 @@ var recordingMetadataSchema = z.object({
|
|
|
1645
1649
|
retainedUntil: z.string().datetime({ offset: true }),
|
|
1646
1650
|
participant: recordingParticipantSchema.optional(),
|
|
1647
1651
|
mediaStartedAt: z.string().datetime({ offset: true }).optional(),
|
|
1648
|
-
mediaEndedAt: z.string().datetime({ offset: true }).optional()
|
|
1652
|
+
mediaEndedAt: z.string().datetime({ offset: true }).optional(),
|
|
1653
|
+
mediaStartOffsetMs: z.number().int().min(0).optional().describe("First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero."),
|
|
1654
|
+
mediaMutedIntervalsMs: z.array(recordingMutedIntervalSchema).optional().describe("Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals.")
|
|
1649
1655
|
});
|
|
1650
1656
|
var recordingArtifactSchema = z.discriminatedUnion("status", [
|
|
1651
1657
|
recordingMetadataSchema.extend({ status: z.enum(["pending", "recording", "processing", "expired"]) }).strict(),
|
|
1652
1658
|
recordingMetadataSchema.extend({
|
|
1653
1659
|
status: z.literal("ready"),
|
|
1654
|
-
mediaType: z.enum(["audio/mp4", "video/mp4"]),
|
|
1660
|
+
mediaType: z.enum(["audio/mp4", "video/mp4", "audio/ogg", "video/webm"]),
|
|
1655
1661
|
sizeBytes: z.number().int().positive(),
|
|
1656
1662
|
durationMs: z.number().int().nonnegative().nullable()
|
|
1657
1663
|
}).strict(),
|
package/dist/react.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ToolRegistration, RegisteredTool } from './tools.js';
|
|
2
|
-
import { ak as SessionLifecycleRoomBridgeProps, h as AvatarSessionClient, A as AvatarVideoFit, aS as CallMicrophone, aT as CallAudioPlayback, aU as CallMicrophoneProblem } from './proxy-client-
|
|
3
|
-
export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarConnectionDetails, aV as AvatarVideoSurface, aW as AvatarVideoSurfaceProps, B as BehaviorSnapshot, C as CallTranscript, i as CallTranscriptSegment, j as CartesiaTtsModel, k as ClipResult, l as ClosingTurnResult, m as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, n as DEFAULT_CREDITS_LOW_LEAD_SECONDS, o as DEFAULT_GOVERNOR_CONFIG, p as DEFAULT_GRACE_CEILING_SECONDS, q as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, r as DEFAULT_IDLE_SECONDS, s as DEFAULT_IDLE_WARN_LEAD_SECONDS, t as DEFAULT_READY_TIMEOUT_SECONDS, u as DEFAULT_TURN_TIMEOUT_SECONDS, v as DeclaredInputSource, E as EndReason, w as EndedEvent, x as ExtendResult, F as FishTtsModel, y as FreezeReadingFn, G as Governor, z as GovernorAction, H as GovernorConfig, I as GovernorSignal, J as GovernorState, K as GraceWindowClosedEvent, M as GraceWindowOpenEvent, N as GraceWindowState, O as IdleWarningEvent, P as InboundRtpCursor, Q as InboundRtpReading, R as KnownBehaviorState, S as LLMProvider, T as LLMSelection, U as LiveKitAvatarGrantState, V as LiveKitAvatarGrantStatus, W as LiveKitCapacityState, X as LiveKitConnectionStatus, Y as LiveKitSessionRequest, Z as LiveKitSessionStartResult, aX as LivePlaybackKeeper, _ as MAX_RECONNECT_ATTEMPTS, $ as MAX_SESSION_INSTRUCTIONS_CHARS, aY as MIC_LEASE_ENDED_TIMEOUT_MS, aZ as MicLease, a_ as NETWORK_QUALITY_POLICY, a$ as NetworkQualityStatus, b0 as PlayableVideoElement, a0 as ProxyClientOptions, a1 as QualityCap, a2 as RECONNECT_BACKOFF_MS, b1 as RealtimeAvatarCapacityError, b2 as RealtimeAvatarLiveKitRoom, b3 as RealtimeAvatarLiveKitRoomProps, a3 as RealtimeAvatarRequestOptions, a4 as RealtimeSessionApi, a5 as RealtimeSessionMedia, a6 as RealtimeSessionRoomSinks, a7 as ReconnectPolicy, a8 as ReconnectingEvent, a9 as RecoveryState, aa as RetryStep, ab as SendTurnOptions, ac as SessionBehavior, ad as SessionClip, ae as SessionClocks, af as SessionEndReason, ag as SessionLifecycleApi, ah as SessionLifecyclePhase, ai as SessionLifecyclePhaseKind, aj as SessionLifecycleRoomBridge, al as SessionReadinessFailure, am as SurfaceLayers, an as TranscriptSender, ao as TranscriptSenderOptions, ap as TurnState, aq as TurnTimeoutEvent, ar as UseAvatarQualityGovernorInput, as as UseLiveKitAvatarGrantInput, at as UseRealtimeSessionInput, au as UseSessionLifecycleInput, av as VoiceSpec, aw as VoiceSpecInput, ax as capacityErrorFromBusy, ay as capacityStateFromGrant, az as createProxyClient, aB as knownBehaviorStates, aC as mapTurnState, aD as readInboundRtp, aE as sessionBehaviorSchema, aF as sessionClipSchema, b4 as shouldReplayPendingTurn, aG as splitCallTranscript, aH as useAvatarAdaptivePlayoutDelay, aI as useAvatarCamera, aJ as useAvatarPlayoutDelay, aK as useAvatarQualityGovernor, aL as useCallTranscript, aM as useLiveKitAvatarGrant, aO as useMicLease, aP as useRealtimeSession, aQ as useReleaseMicLeaseOnTrackEnded, aR as useSessionLifecycle } from './proxy-client-
|
|
2
|
+
import { ak as SessionLifecycleRoomBridgeProps, h as AvatarSessionClient, A as AvatarVideoFit, aS as CallMicrophone, aT as CallAudioPlayback, aU as CallMicrophoneProblem } from './proxy-client-BAY77sJZ.js';
|
|
3
|
+
export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarConnectionDetails, aV as AvatarVideoSurface, aW as AvatarVideoSurfaceProps, B as BehaviorSnapshot, C as CallTranscript, i as CallTranscriptSegment, j as CartesiaTtsModel, k as ClipResult, l as ClosingTurnResult, m as CreditsLowEvent, D as DEFAULT_APPROACHING_END_LEAD_SECONDS, n as DEFAULT_CREDITS_LOW_LEAD_SECONDS, o as DEFAULT_GOVERNOR_CONFIG, p as DEFAULT_GRACE_CEILING_SECONDS, q as DEFAULT_GRACE_WINDOW_LEAD_SECONDS, r as DEFAULT_IDLE_SECONDS, s as DEFAULT_IDLE_WARN_LEAD_SECONDS, t as DEFAULT_READY_TIMEOUT_SECONDS, u as DEFAULT_TURN_TIMEOUT_SECONDS, v as DeclaredInputSource, E as EndReason, w as EndedEvent, x as ExtendResult, F as FishTtsModel, y as FreezeReadingFn, G as Governor, z as GovernorAction, H as GovernorConfig, I as GovernorSignal, J as GovernorState, K as GraceWindowClosedEvent, M as GraceWindowOpenEvent, N as GraceWindowState, O as IdleWarningEvent, P as InboundRtpCursor, Q as InboundRtpReading, R as KnownBehaviorState, S as LLMProvider, T as LLMSelection, U as LiveKitAvatarGrantState, V as LiveKitAvatarGrantStatus, W as LiveKitCapacityState, X as LiveKitConnectionStatus, Y as LiveKitSessionRequest, Z as LiveKitSessionStartResult, aX as LivePlaybackKeeper, _ as MAX_RECONNECT_ATTEMPTS, $ as MAX_SESSION_INSTRUCTIONS_CHARS, aY as MIC_LEASE_ENDED_TIMEOUT_MS, aZ as MicLease, a_ as NETWORK_QUALITY_POLICY, a$ as NetworkQualityStatus, b0 as PlayableVideoElement, a0 as ProxyClientOptions, a1 as QualityCap, a2 as RECONNECT_BACKOFF_MS, b1 as RealtimeAvatarCapacityError, b2 as RealtimeAvatarLiveKitRoom, b3 as RealtimeAvatarLiveKitRoomProps, a3 as RealtimeAvatarRequestOptions, a4 as RealtimeSessionApi, a5 as RealtimeSessionMedia, a6 as RealtimeSessionRoomSinks, a7 as ReconnectPolicy, a8 as ReconnectingEvent, a9 as RecoveryState, aa as RetryStep, ab as SendTurnOptions, ac as SessionBehavior, ad as SessionClip, ae as SessionClocks, af as SessionEndReason, ag as SessionLifecycleApi, ah as SessionLifecyclePhase, ai as SessionLifecyclePhaseKind, aj as SessionLifecycleRoomBridge, al as SessionReadinessFailure, am as SurfaceLayers, an as TranscriptSender, ao as TranscriptSenderOptions, ap as TurnState, aq as TurnTimeoutEvent, ar as UseAvatarQualityGovernorInput, as as UseLiveKitAvatarGrantInput, at as UseRealtimeSessionInput, au as UseSessionLifecycleInput, av as VoiceSpec, aw as VoiceSpecInput, ax as capacityErrorFromBusy, ay as capacityStateFromGrant, az as createProxyClient, aB as knownBehaviorStates, aC as mapTurnState, aD as readInboundRtp, aE as sessionBehaviorSchema, aF as sessionClipSchema, b4 as shouldReplayPendingTurn, aG as splitCallTranscript, aH as useAvatarAdaptivePlayoutDelay, aI as useAvatarCamera, aJ as useAvatarPlayoutDelay, aK as useAvatarQualityGovernor, aL as useCallTranscript, aM as useLiveKitAvatarGrant, aO as useMicLease, aP as useRealtimeSession, aQ as useReleaseMicLeaseOnTrackEnded, aR as useSessionLifecycle } from './proxy-client-BAY77sJZ.js';
|
|
4
4
|
import { CSSProperties, ReactNode } from 'react';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
|
-
import { R as RecordingArtifact } from './recording-
|
|
6
|
+
import { R as RecordingArtifact } from './recording-ydFVySSd.js';
|
|
7
7
|
export { D as DEFAULT_AVATAR_PLAYOUT_DELAY_SECONDS } from './playout-delay-CtRZdtsj.js';
|
|
8
8
|
import 'zod';
|
|
9
9
|
import 'livekit-client';
|
|
@@ -201,7 +201,7 @@ type RecordingPlaybackAsset = {
|
|
|
201
201
|
recording: RecordingArtifact;
|
|
202
202
|
url: string;
|
|
203
203
|
};
|
|
204
|
-
/**
|
|
204
|
+
/** Participant files and separate track segments share one clock without mixing voices. */
|
|
205
205
|
declare function RecordingPlayer({ assets, className }: {
|
|
206
206
|
assets: readonly RecordingPlaybackAsset[];
|
|
207
207
|
className?: string;
|
package/dist/react.js
CHANGED
|
@@ -2249,13 +2249,17 @@ var AVATAR_VIDEO_BADGE = {
|
|
|
2249
2249
|
var AVATAR_VIDEO_BADGE_DOT = { width: 6, height: 6, borderRadius: 9999, background: "#34d399" };
|
|
2250
2250
|
var AVATAR_VIDEO_OVERLAY = { position: "absolute", inset: 0, zIndex: 40 };
|
|
2251
2251
|
var RECORDED_MEDIA_MODES = ["audio", "video", "audio_video"];
|
|
2252
|
-
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices.");
|
|
2252
|
+
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants", "tracks"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices. tracks saves each published participant audio/video track separately; list recordings by session after capture.");
|
|
2253
2253
|
var RECORDING_STATUSES = ["pending", "recording", "processing", "ready", "failed", "expired"];
|
|
2254
2254
|
z.enum(RECORDING_STATUSES);
|
|
2255
2255
|
var recordingParticipantSchema = z.object({
|
|
2256
2256
|
participantIdentity: z.string().min(1).max(160),
|
|
2257
2257
|
role: z.enum(["user", "avatar"])
|
|
2258
2258
|
}).strict();
|
|
2259
|
+
var recordingMutedIntervalSchema = z.object({
|
|
2260
|
+
startMs: z.number().int().min(0),
|
|
2261
|
+
endMs: z.number().int().positive()
|
|
2262
|
+
}).strict().refine((interval) => interval.endMs > interval.startMs, "Muted interval must end after it starts");
|
|
2259
2263
|
var recordingMetadataSchema = z.object({
|
|
2260
2264
|
sessionId: z.string().min(1),
|
|
2261
2265
|
recordingId: z.string().min(1),
|
|
@@ -2264,13 +2268,15 @@ var recordingMetadataSchema = z.object({
|
|
|
2264
2268
|
retainedUntil: z.string().datetime({ offset: true }),
|
|
2265
2269
|
participant: recordingParticipantSchema.optional(),
|
|
2266
2270
|
mediaStartedAt: z.string().datetime({ offset: true }).optional(),
|
|
2267
|
-
mediaEndedAt: z.string().datetime({ offset: true }).optional()
|
|
2271
|
+
mediaEndedAt: z.string().datetime({ offset: true }).optional(),
|
|
2272
|
+
mediaStartOffsetMs: z.number().int().min(0).optional().describe("First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero."),
|
|
2273
|
+
mediaMutedIntervalsMs: z.array(recordingMutedIntervalSchema).optional().describe("Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals.")
|
|
2268
2274
|
});
|
|
2269
2275
|
var recordingArtifactSchema = z.discriminatedUnion("status", [
|
|
2270
2276
|
recordingMetadataSchema.extend({ status: z.enum(["pending", "recording", "processing", "expired"]) }).strict(),
|
|
2271
2277
|
recordingMetadataSchema.extend({
|
|
2272
2278
|
status: z.literal("ready"),
|
|
2273
|
-
mediaType: z.enum(["audio/mp4", "video/mp4"]),
|
|
2279
|
+
mediaType: z.enum(["audio/mp4", "video/mp4", "audio/ogg", "video/webm"]),
|
|
2274
2280
|
sizeBytes: z.number().int().positive(),
|
|
2275
2281
|
durationMs: z.number().int().nonnegative().nullable()
|
|
2276
2282
|
}).strict(),
|
|
@@ -4592,43 +4598,57 @@ function recordingTimeline(recordings) {
|
|
|
4592
4598
|
if (new Set(recordings.map((recording) => recording.sessionId)).size > 1) throw new Error("Recordings belong to different sessions");
|
|
4593
4599
|
if (new Set(recordings.map((recording) => recording.recordingId)).size !== recordings.length) throw new Error("Duplicate recording assets");
|
|
4594
4600
|
const participants = recordings.filter((recording) => recording.participant && recording.status === "ready");
|
|
4595
|
-
if (new Set(participants.map((recording) => recording.participant?.role)).size !== participants.length) throw new Error("Duplicate participant recordings");
|
|
4596
4601
|
const entries = participants.map((recording) => {
|
|
4597
4602
|
if (recording.status !== "ready" || !recording.mediaStartedAt || !recording.mediaEndedAt || recording.durationMs === null) {
|
|
4598
4603
|
throw new Error("Recording media timing is unavailable");
|
|
4599
4604
|
}
|
|
4600
4605
|
const start = Date.parse(recording.mediaStartedAt);
|
|
4601
4606
|
const end = Math.min(Date.parse(recording.mediaEndedAt), start + recording.durationMs);
|
|
4602
|
-
|
|
4603
|
-
|
|
4607
|
+
const activeStart = start + (recording.mediaStartOffsetMs ?? 0);
|
|
4608
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || !Number.isFinite(activeStart) || end <= activeStart) throw new Error("Recording media timing is invalid");
|
|
4609
|
+
return { recording, start, activeStart, end };
|
|
4604
4610
|
});
|
|
4605
4611
|
if (!entries.length) return null;
|
|
4612
|
+
const laneEnds = /* @__PURE__ */ new Map();
|
|
4613
|
+
for (const { recording, activeStart, end } of [...entries].sort((a, b) => a.activeStart - b.activeStart)) {
|
|
4614
|
+
const kinds = recording.mode === "audio_video" ? ["audio", "video"] : [recording.mode];
|
|
4615
|
+
for (const kind of kinds) {
|
|
4616
|
+
const lane = `${recording.participant?.role}:${kind}`;
|
|
4617
|
+
if (activeStart < (laneEnds.get(lane) ?? -Infinity)) throw new Error(`Duplicate participant ${kind} recordings overlap`);
|
|
4618
|
+
laneEnds.set(lane, end);
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4606
4621
|
const originMs = Math.min(...entries.map((entry) => entry.start));
|
|
4607
4622
|
return {
|
|
4608
4623
|
originMs,
|
|
4609
4624
|
durationMs: Math.max(...entries.map((entry) => entry.end)) - originMs,
|
|
4610
|
-
entries: entries.map(({ recording, start, end }) => ({ recording, startMs: start - originMs, endMs: end - originMs }))
|
|
4625
|
+
entries: entries.map(({ recording, start, activeStart, end }) => ({ recording, startMs: start - originMs, activeStartMs: activeStart - originMs, endMs: end - originMs }))
|
|
4611
4626
|
};
|
|
4612
4627
|
}
|
|
4613
4628
|
function recordingPositions(timeline, positionMs) {
|
|
4614
4629
|
return timeline.entries.map((entry) => ({
|
|
4615
4630
|
recordingId: entry.recording.recordingId,
|
|
4616
|
-
active: positionMs >= entry.
|
|
4631
|
+
active: positionMs >= entry.activeStartMs && positionMs < entry.endMs,
|
|
4617
4632
|
timeSeconds: Math.max(0, Math.min(positionMs, entry.endMs) - entry.startMs) / 1e3
|
|
4618
4633
|
}));
|
|
4619
4634
|
}
|
|
4620
|
-
function
|
|
4621
|
-
|
|
4635
|
+
function recordingVideoVisible(recording, timeSeconds) {
|
|
4636
|
+
const mediaMs = timeSeconds * 1e3;
|
|
4637
|
+
return recording.mode !== "audio" && !(recording.mediaMutedIntervalsMs ?? []).some(
|
|
4638
|
+
(interval) => mediaMs >= interval.startMs && mediaMs < interval.endMs
|
|
4639
|
+
);
|
|
4622
4640
|
}
|
|
4623
4641
|
function RecordingPlayer({ assets, className }) {
|
|
4642
|
+
const timelineKey = JSON.stringify(assets.map((asset) => asset.recording));
|
|
4624
4643
|
const timeline = useMemo(() => {
|
|
4625
4644
|
try {
|
|
4626
4645
|
return recordingTimeline(assets.map((asset) => asset.recording));
|
|
4627
4646
|
} catch {
|
|
4628
4647
|
return null;
|
|
4629
4648
|
}
|
|
4630
|
-
}, [
|
|
4649
|
+
}, [timelineKey]);
|
|
4631
4650
|
const media = useRef(/* @__PURE__ */ new Map());
|
|
4651
|
+
const seeks = useRef(/* @__PURE__ */ new Map());
|
|
4632
4652
|
const position = useRef(0);
|
|
4633
4653
|
const anchor = useRef(null);
|
|
4634
4654
|
const [displayPosition, setDisplayPosition] = useState(0);
|
|
@@ -4636,6 +4656,11 @@ function RecordingPlayer({ assets, className }) {
|
|
|
4636
4656
|
const [buffering, setBuffering] = useState(false);
|
|
4637
4657
|
const [error, setError] = useState("");
|
|
4638
4658
|
const sourceKey = assets.map((asset) => `${asset.recording.recordingId}:${asset.url}`).join("|");
|
|
4659
|
+
const seekMedia = (recordingId, element, seconds) => {
|
|
4660
|
+
if (element.readyState < 1 || Math.abs(element.currentTime - seconds) <= 0.02) return;
|
|
4661
|
+
seeks.current.set(recordingId, { seconds, retries: 0 });
|
|
4662
|
+
element.currentTime = seconds;
|
|
4663
|
+
};
|
|
4639
4664
|
useEffect(() => {
|
|
4640
4665
|
if (!timeline) return;
|
|
4641
4666
|
const sessionId = timeline.entries[0].recording.sessionId;
|
|
@@ -4652,6 +4677,7 @@ function RecordingPlayer({ assets, className }) {
|
|
|
4652
4677
|
let last = performance.now();
|
|
4653
4678
|
let painted = last;
|
|
4654
4679
|
const starting = /* @__PURE__ */ new Set();
|
|
4680
|
+
const active = /* @__PURE__ */ new Set();
|
|
4655
4681
|
const stopMedia = () => {
|
|
4656
4682
|
for (const element of media.current.values()) element.pause();
|
|
4657
4683
|
};
|
|
@@ -4668,19 +4694,23 @@ function RecordingPlayer({ assets, className }) {
|
|
|
4668
4694
|
const states = recordingPositions(timeline, proposed);
|
|
4669
4695
|
const waiting = playing && states.some((state) => {
|
|
4670
4696
|
const element = media.current.get(state.recordingId);
|
|
4671
|
-
return state.active && (!element || !
|
|
4697
|
+
return state.active && (!element || (!element.ended || seeks.current.has(state.recordingId)) && (element.readyState < 2 || element.seeking));
|
|
4672
4698
|
});
|
|
4673
4699
|
setBuffering(waiting);
|
|
4674
4700
|
if (!waiting) position.current = proposed;
|
|
4675
4701
|
for (const state of recordingPositions(timeline, position.current)) {
|
|
4676
4702
|
const element = media.current.get(state.recordingId);
|
|
4677
4703
|
if (!element) continue;
|
|
4678
|
-
if (!state.active
|
|
4704
|
+
if (!state.active) {
|
|
4679
4705
|
element.pause();
|
|
4706
|
+
active.delete(state.recordingId);
|
|
4680
4707
|
continue;
|
|
4681
4708
|
}
|
|
4682
|
-
if (
|
|
4683
|
-
|
|
4709
|
+
if (!active.has(state.recordingId)) seekMedia(state.recordingId, element, state.timeSeconds);
|
|
4710
|
+
if (element.readyState >= 1) active.add(state.recordingId);
|
|
4711
|
+
if (element.ended && !seeks.current.has(state.recordingId)) {
|
|
4712
|
+
element.pause();
|
|
4713
|
+
continue;
|
|
4684
4714
|
}
|
|
4685
4715
|
if (!playing || waiting) {
|
|
4686
4716
|
element.pause();
|
|
@@ -4716,14 +4746,14 @@ function RecordingPlayer({ assets, className }) {
|
|
|
4716
4746
|
stopMedia();
|
|
4717
4747
|
};
|
|
4718
4748
|
}, [timeline, playing, sourceKey]);
|
|
4719
|
-
const
|
|
4749
|
+
const positions = new Map(timeline ? recordingPositions(timeline, displayPosition).map((state) => [state.recordingId, state]) : []);
|
|
4720
4750
|
const seek = (value) => {
|
|
4721
4751
|
position.current = value;
|
|
4722
4752
|
setDisplayPosition(value);
|
|
4723
4753
|
if (timeline) for (const state of recordingPositions(timeline, value)) {
|
|
4724
4754
|
const element = media.current.get(state.recordingId);
|
|
4725
4755
|
if (!element) continue;
|
|
4726
|
-
|
|
4756
|
+
seekMedia(state.recordingId, element, state.timeSeconds);
|
|
4727
4757
|
if (!state.active) element.pause();
|
|
4728
4758
|
}
|
|
4729
4759
|
};
|
|
@@ -4737,8 +4767,8 @@ function RecordingPlayer({ assets, className }) {
|
|
|
4737
4767
|
if (position.current >= timeline.durationMs) seek(0);
|
|
4738
4768
|
for (const state of recordingPositions(timeline, position.current)) {
|
|
4739
4769
|
const element = media.current.get(state.recordingId);
|
|
4740
|
-
if (state.active && element
|
|
4741
|
-
|
|
4770
|
+
if (state.active && element) {
|
|
4771
|
+
seekMedia(state.recordingId, element, state.timeSeconds);
|
|
4742
4772
|
void element.play().catch((cause) => {
|
|
4743
4773
|
if (cause instanceof Error && cause.name === "AbortError") return;
|
|
4744
4774
|
for (const current of media.current.values()) current.pause();
|
|
@@ -4752,6 +4782,8 @@ function RecordingPlayer({ assets, className }) {
|
|
|
4752
4782
|
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
4753
4783
|
/* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 240px), 1fr))", gap: 12 }, children: assets.map(({ recording, url }) => {
|
|
4754
4784
|
if (!recording.participant) return null;
|
|
4785
|
+
const state = positions.get(recording.recordingId);
|
|
4786
|
+
const visible = Boolean(state?.active && recordingVideoVisible(recording, state.timeSeconds));
|
|
4755
4787
|
const label = recording.participant.role === "user" ? "User" : "Character";
|
|
4756
4788
|
const ref = (element) => {
|
|
4757
4789
|
if (element) media.current.set(recording.recordingId, element);
|
|
@@ -4762,22 +4794,36 @@ function RecordingPlayer({ assets, className }) {
|
|
|
4762
4794
|
setPlaying(false);
|
|
4763
4795
|
setError("A recording could not load. Refresh access and try again.");
|
|
4764
4796
|
};
|
|
4765
|
-
|
|
4797
|
+
const onLoadedMetadata = (event) => {
|
|
4798
|
+
const state2 = timeline && recordingPositions(timeline, position.current).find((item) => item.recordingId === recording.recordingId);
|
|
4799
|
+
if (state2) seekMedia(recording.recordingId, event.currentTarget, state2.timeSeconds);
|
|
4800
|
+
};
|
|
4801
|
+
const onSeeked = (event) => {
|
|
4802
|
+
const pending = seeks.current.get(recording.recordingId);
|
|
4803
|
+
if (!pending) return;
|
|
4804
|
+
if (Math.abs(event.currentTarget.currentTime - pending.seconds) > 0.08 && pending.retries < 2) {
|
|
4805
|
+
pending.retries++;
|
|
4806
|
+
event.currentTarget.currentTime = pending.seconds;
|
|
4807
|
+
} else seeks.current.delete(recording.recordingId);
|
|
4808
|
+
};
|
|
4809
|
+
return recording.mode !== "audio" ? /* @__PURE__ */ jsxs("figure", { hidden: !visible, style: { margin: 0 }, children: [
|
|
4766
4810
|
/* @__PURE__ */ jsx("figcaption", { children: label }),
|
|
4767
4811
|
/* @__PURE__ */ jsx(
|
|
4768
4812
|
"video",
|
|
4769
4813
|
{
|
|
4770
4814
|
ref,
|
|
4771
4815
|
src: url,
|
|
4816
|
+
muted: recording.mode === "video",
|
|
4772
4817
|
playsInline: true,
|
|
4773
4818
|
preload: "auto",
|
|
4774
4819
|
onError,
|
|
4775
|
-
|
|
4820
|
+
onLoadedMetadata,
|
|
4821
|
+
onSeeked,
|
|
4822
|
+
hidden: !visible,
|
|
4776
4823
|
style: { width: "100%", maxHeight: 360, objectFit: "contain" }
|
|
4777
4824
|
}
|
|
4778
|
-
)
|
|
4779
|
-
|
|
4780
|
-
] }, recording.recordingId) : /* @__PURE__ */ jsx("audio", { ref, src: url, preload: "auto", onError, "aria-label": `${label} audio` }, recording.recordingId);
|
|
4825
|
+
)
|
|
4826
|
+
] }, recording.recordingId) : /* @__PURE__ */ jsx("audio", { ref, src: url, preload: "auto", onError, onLoadedMetadata, onSeeked, "aria-label": `${label} audio` }, recording.recordingId);
|
|
4781
4827
|
}) }),
|
|
4782
4828
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
4783
4829
|
/* @__PURE__ */ jsx("button", { type: "button", onClick: toggle, disabled: !timeline, style: { minHeight: 44, minWidth: 44 }, children: playing ? "Pause" : "Play" }),
|
|
@@ -6,6 +6,7 @@ declare const recordingModeSchema: z.ZodEnum<{
|
|
|
6
6
|
audio_video: "audio_video";
|
|
7
7
|
off: "off";
|
|
8
8
|
participants: "participants";
|
|
9
|
+
tracks: "tracks";
|
|
9
10
|
}>;
|
|
10
11
|
type RecordingMode = z.infer<typeof recordingModeSchema>;
|
|
11
12
|
declare const recordingArtifactStatusSchema: z.ZodEnum<{
|
|
@@ -44,6 +45,11 @@ declare const recordingArtifactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
44
45
|
}, z.core.$strict>>;
|
|
45
46
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
46
47
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
48
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
49
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
50
|
+
startMs: z.ZodNumber;
|
|
51
|
+
endMs: z.ZodNumber;
|
|
52
|
+
}, z.core.$strict>>>;
|
|
47
53
|
status: z.ZodEnum<{
|
|
48
54
|
pending: "pending";
|
|
49
55
|
recording: "recording";
|
|
@@ -69,10 +75,17 @@ declare const recordingArtifactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
69
75
|
}, z.core.$strict>>;
|
|
70
76
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
71
77
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
78
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
79
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
80
|
+
startMs: z.ZodNumber;
|
|
81
|
+
endMs: z.ZodNumber;
|
|
82
|
+
}, z.core.$strict>>>;
|
|
72
83
|
status: z.ZodLiteral<"ready">;
|
|
73
84
|
mediaType: z.ZodEnum<{
|
|
74
85
|
"audio/mp4": "audio/mp4";
|
|
75
86
|
"video/mp4": "video/mp4";
|
|
87
|
+
"audio/ogg": "audio/ogg";
|
|
88
|
+
"video/webm": "video/webm";
|
|
76
89
|
}>;
|
|
77
90
|
sizeBytes: z.ZodNumber;
|
|
78
91
|
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
@@ -95,6 +108,11 @@ declare const recordingArtifactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
95
108
|
}, z.core.$strict>>;
|
|
96
109
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
97
110
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
111
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
112
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
113
|
+
startMs: z.ZodNumber;
|
|
114
|
+
endMs: z.ZodNumber;
|
|
115
|
+
}, z.core.$strict>>>;
|
|
98
116
|
status: z.ZodLiteral<"failed">;
|
|
99
117
|
errorCode: z.ZodEnum<{
|
|
100
118
|
recording_failed: "recording_failed";
|
|
@@ -128,6 +146,11 @@ declare const listRecordingsResponseSchema: z.ZodObject<{
|
|
|
128
146
|
}, z.core.$strict>>;
|
|
129
147
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
130
148
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
149
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
150
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
151
|
+
startMs: z.ZodNumber;
|
|
152
|
+
endMs: z.ZodNumber;
|
|
153
|
+
}, z.core.$strict>>>;
|
|
131
154
|
status: z.ZodEnum<{
|
|
132
155
|
pending: "pending";
|
|
133
156
|
recording: "recording";
|
|
@@ -153,10 +176,17 @@ declare const listRecordingsResponseSchema: z.ZodObject<{
|
|
|
153
176
|
}, z.core.$strict>>;
|
|
154
177
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
155
178
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
179
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
180
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
181
|
+
startMs: z.ZodNumber;
|
|
182
|
+
endMs: z.ZodNumber;
|
|
183
|
+
}, z.core.$strict>>>;
|
|
156
184
|
status: z.ZodLiteral<"ready">;
|
|
157
185
|
mediaType: z.ZodEnum<{
|
|
158
186
|
"audio/mp4": "audio/mp4";
|
|
159
187
|
"video/mp4": "video/mp4";
|
|
188
|
+
"audio/ogg": "audio/ogg";
|
|
189
|
+
"video/webm": "video/webm";
|
|
160
190
|
}>;
|
|
161
191
|
sizeBytes: z.ZodNumber;
|
|
162
192
|
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
@@ -179,6 +209,11 @@ declare const listRecordingsResponseSchema: z.ZodObject<{
|
|
|
179
209
|
}, z.core.$strict>>;
|
|
180
210
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
181
211
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
212
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
213
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
214
|
+
startMs: z.ZodNumber;
|
|
215
|
+
endMs: z.ZodNumber;
|
|
216
|
+
}, z.core.$strict>>>;
|
|
182
217
|
status: z.ZodLiteral<"failed">;
|
|
183
218
|
errorCode: z.ZodEnum<{
|
|
184
219
|
recording_failed: "recording_failed";
|
package/dist/recording.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as RecordingArtifact } from './recording-
|
|
2
|
-
export { L as ListRecordingsQuery, a as ListRecordingsResponse, b as RecordingAccessResponse, c as RecordingArtifactStatus, d as RecordingMode, e as RecordingParticipant, l as listRecordingsQuerySchema, f as listRecordingsResponseSchema, r as recordingAccessResponseSchema, g as recordingArtifactSchema, h as recordingArtifactStatusSchema, i as recordingModeSchema, j as recordingParticipantSchema } from './recording-
|
|
1
|
+
import { R as RecordingArtifact } from './recording-ydFVySSd.js';
|
|
2
|
+
export { L as ListRecordingsQuery, a as ListRecordingsResponse, b as RecordingAccessResponse, c as RecordingArtifactStatus, d as RecordingMode, e as RecordingParticipant, l as listRecordingsQuerySchema, f as listRecordingsResponseSchema, r as recordingAccessResponseSchema, g as recordingArtifactSchema, h as recordingArtifactStatusSchema, i as recordingModeSchema, j as recordingParticipantSchema } from './recording-ydFVySSd.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
declare function recordingTimeline(recordings: readonly RecordingArtifact[]): {
|
|
@@ -13,7 +13,7 @@ declare function recordingTimeline(recordings: readonly RecordingArtifact[]): {
|
|
|
13
13
|
createdAt: string;
|
|
14
14
|
retainedUntil: string;
|
|
15
15
|
status: "ready";
|
|
16
|
-
mediaType: "audio/mp4" | "video/mp4";
|
|
16
|
+
mediaType: "audio/mp4" | "video/mp4" | "audio/ogg" | "video/webm";
|
|
17
17
|
sizeBytes: number;
|
|
18
18
|
durationMs: number | null;
|
|
19
19
|
participant?: {
|
|
@@ -22,8 +22,14 @@ declare function recordingTimeline(recordings: readonly RecordingArtifact[]): {
|
|
|
22
22
|
} | undefined;
|
|
23
23
|
mediaStartedAt?: string | undefined;
|
|
24
24
|
mediaEndedAt?: string | undefined;
|
|
25
|
+
mediaStartOffsetMs?: number | undefined;
|
|
26
|
+
mediaMutedIntervalsMs?: {
|
|
27
|
+
startMs: number;
|
|
28
|
+
endMs: number;
|
|
29
|
+
}[] | undefined;
|
|
25
30
|
};
|
|
26
31
|
startMs: number;
|
|
32
|
+
activeStartMs: number;
|
|
27
33
|
endMs: number;
|
|
28
34
|
}[];
|
|
29
35
|
} | null;
|
package/dist/recording.js
CHANGED
|
@@ -2,13 +2,17 @@ import { z } from 'zod';
|
|
|
2
2
|
|
|
3
3
|
// ../http-client/src/generated/recording.ts
|
|
4
4
|
var RECORDED_MEDIA_MODES = ["audio", "video", "audio_video"];
|
|
5
|
-
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices.");
|
|
5
|
+
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES, "participants", "tracks"]).describe("Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices. tracks saves each published participant audio/video track separately; list recordings by session after capture.");
|
|
6
6
|
var RECORDING_STATUSES = ["pending", "recording", "processing", "ready", "failed", "expired"];
|
|
7
7
|
var recordingArtifactStatusSchema = z.enum(RECORDING_STATUSES);
|
|
8
8
|
var recordingParticipantSchema = z.object({
|
|
9
9
|
participantIdentity: z.string().min(1).max(160),
|
|
10
10
|
role: z.enum(["user", "avatar"])
|
|
11
11
|
}).strict();
|
|
12
|
+
var recordingMutedIntervalSchema = z.object({
|
|
13
|
+
startMs: z.number().int().min(0),
|
|
14
|
+
endMs: z.number().int().positive()
|
|
15
|
+
}).strict().refine((interval) => interval.endMs > interval.startMs, "Muted interval must end after it starts");
|
|
12
16
|
var recordingMetadataSchema = z.object({
|
|
13
17
|
sessionId: z.string().min(1),
|
|
14
18
|
recordingId: z.string().min(1),
|
|
@@ -17,13 +21,15 @@ var recordingMetadataSchema = z.object({
|
|
|
17
21
|
retainedUntil: z.string().datetime({ offset: true }),
|
|
18
22
|
participant: recordingParticipantSchema.optional(),
|
|
19
23
|
mediaStartedAt: z.string().datetime({ offset: true }).optional(),
|
|
20
|
-
mediaEndedAt: z.string().datetime({ offset: true }).optional()
|
|
24
|
+
mediaEndedAt: z.string().datetime({ offset: true }).optional(),
|
|
25
|
+
mediaStartOffsetMs: z.number().int().min(0).optional().describe("First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero."),
|
|
26
|
+
mediaMutedIntervalsMs: z.array(recordingMutedIntervalSchema).optional().describe("Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals.")
|
|
21
27
|
});
|
|
22
28
|
var recordingArtifactSchema = z.discriminatedUnion("status", [
|
|
23
29
|
recordingMetadataSchema.extend({ status: z.enum(["pending", "recording", "processing", "expired"]) }).strict(),
|
|
24
30
|
recordingMetadataSchema.extend({
|
|
25
31
|
status: z.literal("ready"),
|
|
26
|
-
mediaType: z.enum(["audio/mp4", "video/mp4"]),
|
|
32
|
+
mediaType: z.enum(["audio/mp4", "video/mp4", "audio/ogg", "video/webm"]),
|
|
27
33
|
sizeBytes: z.number().int().positive(),
|
|
28
34
|
durationMs: z.number().int().nonnegative().nullable()
|
|
29
35
|
}).strict(),
|
|
@@ -52,28 +58,37 @@ function recordingTimeline(recordings) {
|
|
|
52
58
|
if (new Set(recordings.map((recording) => recording.sessionId)).size > 1) throw new Error("Recordings belong to different sessions");
|
|
53
59
|
if (new Set(recordings.map((recording) => recording.recordingId)).size !== recordings.length) throw new Error("Duplicate recording assets");
|
|
54
60
|
const participants = recordings.filter((recording) => recording.participant && recording.status === "ready");
|
|
55
|
-
if (new Set(participants.map((recording) => recording.participant?.role)).size !== participants.length) throw new Error("Duplicate participant recordings");
|
|
56
61
|
const entries = participants.map((recording) => {
|
|
57
62
|
if (recording.status !== "ready" || !recording.mediaStartedAt || !recording.mediaEndedAt || recording.durationMs === null) {
|
|
58
63
|
throw new Error("Recording media timing is unavailable");
|
|
59
64
|
}
|
|
60
65
|
const start = Date.parse(recording.mediaStartedAt);
|
|
61
66
|
const end = Math.min(Date.parse(recording.mediaEndedAt), start + recording.durationMs);
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
const activeStart = start + (recording.mediaStartOffsetMs ?? 0);
|
|
68
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || !Number.isFinite(activeStart) || end <= activeStart) throw new Error("Recording media timing is invalid");
|
|
69
|
+
return { recording, start, activeStart, end };
|
|
64
70
|
});
|
|
65
71
|
if (!entries.length) return null;
|
|
72
|
+
const laneEnds = /* @__PURE__ */ new Map();
|
|
73
|
+
for (const { recording, activeStart, end } of [...entries].sort((a, b) => a.activeStart - b.activeStart)) {
|
|
74
|
+
const kinds = recording.mode === "audio_video" ? ["audio", "video"] : [recording.mode];
|
|
75
|
+
for (const kind of kinds) {
|
|
76
|
+
const lane = `${recording.participant?.role}:${kind}`;
|
|
77
|
+
if (activeStart < (laneEnds.get(lane) ?? -Infinity)) throw new Error(`Duplicate participant ${kind} recordings overlap`);
|
|
78
|
+
laneEnds.set(lane, end);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
66
81
|
const originMs = Math.min(...entries.map((entry) => entry.start));
|
|
67
82
|
return {
|
|
68
83
|
originMs,
|
|
69
84
|
durationMs: Math.max(...entries.map((entry) => entry.end)) - originMs,
|
|
70
|
-
entries: entries.map(({ recording, start, end }) => ({ recording, startMs: start - originMs, endMs: end - originMs }))
|
|
85
|
+
entries: entries.map(({ recording, start, activeStart, end }) => ({ recording, startMs: start - originMs, activeStartMs: activeStart - originMs, endMs: end - originMs }))
|
|
71
86
|
};
|
|
72
87
|
}
|
|
73
88
|
function recordingPositions(timeline, positionMs) {
|
|
74
89
|
return timeline.entries.map((entry) => ({
|
|
75
90
|
recordingId: entry.recording.recordingId,
|
|
76
|
-
active: positionMs >= entry.
|
|
91
|
+
active: positionMs >= entry.activeStartMs && positionMs < entry.endMs,
|
|
77
92
|
timeSeconds: Math.max(0, Math.min(positionMs, entry.endMs) - entry.startMs) / 1e3
|
|
78
93
|
}));
|
|
79
94
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, RealtimeAvatarOptions, StartCallOptions, clipLibraryDeclarationSchema, verifyTranscript } from './index.js';
|
|
2
|
-
export { h as Asset, g as AssetKind, A as Avatar, o as AvatarClip, c as AvatarSourceSwap, b as AvatarUpdate, p as CallConnection, C as CallMode, a as CallPolicy, q as CallQueued, r as ClipDeclaration, f as ClipLibrary, d as ClipLibraryDeclaration, s as ClipLibraryPlan, e as ClipLibraryUpdate, t as ClipSource, u as ContextMessage, n as CreditBalance, E as EndCallOptions, v as EndCallReason, w as ExternalLlm, k as ListRecordingsQuery, l as ListRecordingsResponse, i as ListSessionsOptions, L as LoopRedirect, m as RecordingAccessResponse, R as RecordingArtifact, x as RecordingArtifactStatus, y as RecordingMode, S as StartCallResult, T as TranscriptPayload, j as UsageSession, U as UsageSessionPage, V as VideoPolicy, z as isQueued, B as listRecordingsResponseSchema, D as recordingAccessResponseSchema, F as recordingArtifactSchema, G as recordingModeSchema } from './types-
|
|
2
|
+
export { h as Asset, g as AssetKind, A as Avatar, o as AvatarClip, c as AvatarSourceSwap, b as AvatarUpdate, p as CallConnection, C as CallMode, a as CallPolicy, q as CallQueued, r as ClipDeclaration, f as ClipLibrary, d as ClipLibraryDeclaration, s as ClipLibraryPlan, e as ClipLibraryUpdate, t as ClipSource, u as ContextMessage, n as CreditBalance, E as EndCallOptions, v as EndCallReason, w as ExternalLlm, k as ListRecordingsQuery, l as ListRecordingsResponse, i as ListSessionsOptions, L as LoopRedirect, m as RecordingAccessResponse, R as RecordingArtifact, x as RecordingArtifactStatus, y as RecordingMode, S as StartCallResult, T as TranscriptPayload, j as UsageSession, U as UsageSessionPage, V as VideoPolicy, z as isQueued, B as listRecordingsResponseSchema, D as recordingAccessResponseSchema, F as recordingArtifactSchema, G as recordingModeSchema } from './types-kgmS7ECd.js';
|
|
3
3
|
import './connection-history.js';
|
|
4
4
|
import 'zod';
|
package/dist/server.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, listRecordingsResponseSchema, recordingAccessResponseSchema, recordingArtifactSchema, recordingModeSchema, verifyTranscript } from './chunk-
|
|
1
|
+
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, listRecordingsResponseSchema, recordingAccessResponseSchema, recordingArtifactSchema, recordingModeSchema, verifyTranscript } from './chunk-W4DGBG4Z.js';
|
|
2
2
|
import './chunk-MCIXU6XP.js';
|
package/dist/tanstack-start.d.ts
CHANGED
package/dist/tanstack-start.js
CHANGED
|
@@ -176,10 +176,10 @@ interface components {
|
|
|
176
176
|
*/
|
|
177
177
|
content_policy?: "minor-sexual-content-v1";
|
|
178
178
|
/**
|
|
179
|
-
* @description Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices.
|
|
179
|
+
* @description Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices. tracks saves each published participant audio/video track separately; list recordings by session after capture.
|
|
180
180
|
* @enum {string}
|
|
181
181
|
*/
|
|
182
|
-
recording?: "off" | "audio" | "video" | "audio_video" | "participants";
|
|
182
|
+
recording?: "off" | "audio" | "video" | "audio_video" | "participants" | "tracks";
|
|
183
183
|
connection_history?: boolean;
|
|
184
184
|
client_metadata?: {
|
|
185
185
|
[key: string]: string;
|
|
@@ -264,6 +264,13 @@ interface components {
|
|
|
264
264
|
mediaStartedAt?: string;
|
|
265
265
|
/** Format: date-time */
|
|
266
266
|
mediaEndedAt?: string;
|
|
267
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
268
|
+
mediaStartOffsetMs?: number;
|
|
269
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
270
|
+
mediaMutedIntervalsMs?: {
|
|
271
|
+
startMs: number;
|
|
272
|
+
endMs: number;
|
|
273
|
+
}[];
|
|
267
274
|
/** @enum {string} */
|
|
268
275
|
status: "pending" | "recording" | "processing" | "expired";
|
|
269
276
|
} | {
|
|
@@ -284,10 +291,17 @@ interface components {
|
|
|
284
291
|
mediaStartedAt?: string;
|
|
285
292
|
/** Format: date-time */
|
|
286
293
|
mediaEndedAt?: string;
|
|
294
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
295
|
+
mediaStartOffsetMs?: number;
|
|
296
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
297
|
+
mediaMutedIntervalsMs?: {
|
|
298
|
+
startMs: number;
|
|
299
|
+
endMs: number;
|
|
300
|
+
}[];
|
|
287
301
|
/** @constant */
|
|
288
302
|
status: "ready";
|
|
289
303
|
/** @enum {string} */
|
|
290
|
-
mediaType: "audio/mp4" | "video/mp4";
|
|
304
|
+
mediaType: "audio/mp4" | "video/mp4" | "audio/ogg" | "video/webm";
|
|
291
305
|
sizeBytes: number;
|
|
292
306
|
durationMs: number | null;
|
|
293
307
|
} | {
|
|
@@ -308,16 +322,23 @@ interface components {
|
|
|
308
322
|
mediaStartedAt?: string;
|
|
309
323
|
/** Format: date-time */
|
|
310
324
|
mediaEndedAt?: string;
|
|
325
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
326
|
+
mediaStartOffsetMs?: number;
|
|
327
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
328
|
+
mediaMutedIntervalsMs?: {
|
|
329
|
+
startMs: number;
|
|
330
|
+
endMs: number;
|
|
331
|
+
}[];
|
|
311
332
|
/** @constant */
|
|
312
333
|
status: "failed";
|
|
313
334
|
/** @enum {string} */
|
|
314
335
|
errorCode: "recording_failed" | "recording_unavailable";
|
|
315
336
|
};
|
|
316
337
|
/**
|
|
317
|
-
* @description Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices.
|
|
338
|
+
* @description Server-owned recording policy; omitted means off. Legacy audio includes user and avatar audio. participants saves one continuous audio/video file per participant, without mixing their voices. tracks saves each published participant audio/video track separately; list recordings by session after capture.
|
|
318
339
|
* @enum {string}
|
|
319
340
|
*/
|
|
320
|
-
readonly recording_mode?: "off" | "audio" | "video" | "audio_video" | "participants";
|
|
341
|
+
readonly recording_mode?: "off" | "audio" | "video" | "audio_video" | "participants" | "tracks";
|
|
321
342
|
readonly recordings?: ({
|
|
322
343
|
sessionId: string;
|
|
323
344
|
recordingId: string;
|
|
@@ -336,6 +357,13 @@ interface components {
|
|
|
336
357
|
mediaStartedAt?: string;
|
|
337
358
|
/** Format: date-time */
|
|
338
359
|
mediaEndedAt?: string;
|
|
360
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
361
|
+
mediaStartOffsetMs?: number;
|
|
362
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
363
|
+
mediaMutedIntervalsMs?: {
|
|
364
|
+
startMs: number;
|
|
365
|
+
endMs: number;
|
|
366
|
+
}[];
|
|
339
367
|
/** @enum {string} */
|
|
340
368
|
status: "pending" | "recording" | "processing" | "expired";
|
|
341
369
|
} | {
|
|
@@ -356,10 +384,17 @@ interface components {
|
|
|
356
384
|
mediaStartedAt?: string;
|
|
357
385
|
/** Format: date-time */
|
|
358
386
|
mediaEndedAt?: string;
|
|
387
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
388
|
+
mediaStartOffsetMs?: number;
|
|
389
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
390
|
+
mediaMutedIntervalsMs?: {
|
|
391
|
+
startMs: number;
|
|
392
|
+
endMs: number;
|
|
393
|
+
}[];
|
|
359
394
|
/** @constant */
|
|
360
395
|
status: "ready";
|
|
361
396
|
/** @enum {string} */
|
|
362
|
-
mediaType: "audio/mp4" | "video/mp4";
|
|
397
|
+
mediaType: "audio/mp4" | "video/mp4" | "audio/ogg" | "video/webm";
|
|
363
398
|
sizeBytes: number;
|
|
364
399
|
durationMs: number | null;
|
|
365
400
|
} | {
|
|
@@ -380,6 +415,13 @@ interface components {
|
|
|
380
415
|
mediaStartedAt?: string;
|
|
381
416
|
/** Format: date-time */
|
|
382
417
|
mediaEndedAt?: string;
|
|
418
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
419
|
+
mediaStartOffsetMs?: number;
|
|
420
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
421
|
+
mediaMutedIntervalsMs?: {
|
|
422
|
+
startMs: number;
|
|
423
|
+
endMs: number;
|
|
424
|
+
}[];
|
|
383
425
|
/** @constant */
|
|
384
426
|
status: "failed";
|
|
385
427
|
/** @enum {string} */
|
|
@@ -919,6 +961,13 @@ interface components {
|
|
|
919
961
|
mediaStartedAt?: string;
|
|
920
962
|
/** Format: date-time */
|
|
921
963
|
mediaEndedAt?: string;
|
|
964
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
965
|
+
mediaStartOffsetMs?: number;
|
|
966
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
967
|
+
mediaMutedIntervalsMs?: {
|
|
968
|
+
startMs: number;
|
|
969
|
+
endMs: number;
|
|
970
|
+
}[];
|
|
922
971
|
/** @enum {string} */
|
|
923
972
|
status: "pending" | "recording" | "processing" | "expired";
|
|
924
973
|
} | {
|
|
@@ -939,10 +988,17 @@ interface components {
|
|
|
939
988
|
mediaStartedAt?: string;
|
|
940
989
|
/** Format: date-time */
|
|
941
990
|
mediaEndedAt?: string;
|
|
991
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
992
|
+
mediaStartOffsetMs?: number;
|
|
993
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
994
|
+
mediaMutedIntervalsMs?: {
|
|
995
|
+
startMs: number;
|
|
996
|
+
endMs: number;
|
|
997
|
+
}[];
|
|
942
998
|
/** @constant */
|
|
943
999
|
status: "ready";
|
|
944
1000
|
/** @enum {string} */
|
|
945
|
-
mediaType: "audio/mp4" | "video/mp4";
|
|
1001
|
+
mediaType: "audio/mp4" | "video/mp4" | "audio/ogg" | "video/webm";
|
|
946
1002
|
sizeBytes: number;
|
|
947
1003
|
durationMs: number | null;
|
|
948
1004
|
} | {
|
|
@@ -963,6 +1019,13 @@ interface components {
|
|
|
963
1019
|
mediaStartedAt?: string;
|
|
964
1020
|
/** Format: date-time */
|
|
965
1021
|
mediaEndedAt?: string;
|
|
1022
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
1023
|
+
mediaStartOffsetMs?: number;
|
|
1024
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
1025
|
+
mediaMutedIntervalsMs?: {
|
|
1026
|
+
startMs: number;
|
|
1027
|
+
endMs: number;
|
|
1028
|
+
}[];
|
|
966
1029
|
/** @constant */
|
|
967
1030
|
status: "failed";
|
|
968
1031
|
/** @enum {string} */
|
|
@@ -987,6 +1050,13 @@ interface components {
|
|
|
987
1050
|
mediaStartedAt?: string;
|
|
988
1051
|
/** Format: date-time */
|
|
989
1052
|
mediaEndedAt?: string;
|
|
1053
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
1054
|
+
mediaStartOffsetMs?: number;
|
|
1055
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
1056
|
+
mediaMutedIntervalsMs?: {
|
|
1057
|
+
startMs: number;
|
|
1058
|
+
endMs: number;
|
|
1059
|
+
}[];
|
|
990
1060
|
/** @enum {string} */
|
|
991
1061
|
status: "pending" | "recording" | "processing" | "expired";
|
|
992
1062
|
} | {
|
|
@@ -1007,10 +1077,17 @@ interface components {
|
|
|
1007
1077
|
mediaStartedAt?: string;
|
|
1008
1078
|
/** Format: date-time */
|
|
1009
1079
|
mediaEndedAt?: string;
|
|
1080
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
1081
|
+
mediaStartOffsetMs?: number;
|
|
1082
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
1083
|
+
mediaMutedIntervalsMs?: {
|
|
1084
|
+
startMs: number;
|
|
1085
|
+
endMs: number;
|
|
1086
|
+
}[];
|
|
1010
1087
|
/** @constant */
|
|
1011
1088
|
status: "ready";
|
|
1012
1089
|
/** @enum {string} */
|
|
1013
|
-
mediaType: "audio/mp4" | "video/mp4";
|
|
1090
|
+
mediaType: "audio/mp4" | "video/mp4" | "audio/ogg" | "video/webm";
|
|
1014
1091
|
sizeBytes: number;
|
|
1015
1092
|
durationMs: number | null;
|
|
1016
1093
|
} | {
|
|
@@ -1031,6 +1108,13 @@ interface components {
|
|
|
1031
1108
|
mediaStartedAt?: string;
|
|
1032
1109
|
/** Format: date-time */
|
|
1033
1110
|
mediaEndedAt?: string;
|
|
1111
|
+
/** @description First playable native media timestamp relative to mediaStartedAt. Playback retains this offset; it does not reset the file clock to zero. */
|
|
1112
|
+
mediaStartOffsetMs?: number;
|
|
1113
|
+
/** @description Intervals of hidden camera video relative to mediaStartedAt, using native media timestamps. Audio playback continues through these intervals. */
|
|
1114
|
+
mediaMutedIntervalsMs?: {
|
|
1115
|
+
startMs: number;
|
|
1116
|
+
endMs: number;
|
|
1117
|
+
}[];
|
|
1034
1118
|
/** @constant */
|
|
1035
1119
|
status: "failed";
|
|
1036
1120
|
/** @enum {string} */
|
|
@@ -1323,6 +1407,7 @@ declare const recordingModeSchema: z.ZodEnum<{
|
|
|
1323
1407
|
video: "video";
|
|
1324
1408
|
audio_video: "audio_video";
|
|
1325
1409
|
participants: "participants";
|
|
1410
|
+
tracks: "tracks";
|
|
1326
1411
|
}>;
|
|
1327
1412
|
type RecordingMode = z.infer<typeof recordingModeSchema>;
|
|
1328
1413
|
declare const recordingArtifactStatusSchema: z.ZodEnum<{
|
|
@@ -1353,6 +1438,11 @@ declare const recordingArtifactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1353
1438
|
}, z.core.$strict>>;
|
|
1354
1439
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
1355
1440
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
1441
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
1442
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1443
|
+
startMs: z.ZodNumber;
|
|
1444
|
+
endMs: z.ZodNumber;
|
|
1445
|
+
}, z.core.$strict>>>;
|
|
1356
1446
|
status: z.ZodEnum<{
|
|
1357
1447
|
pending: "pending";
|
|
1358
1448
|
recording: "recording";
|
|
@@ -1378,10 +1468,17 @@ declare const recordingArtifactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1378
1468
|
}, z.core.$strict>>;
|
|
1379
1469
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
1380
1470
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
1471
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
1472
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1473
|
+
startMs: z.ZodNumber;
|
|
1474
|
+
endMs: z.ZodNumber;
|
|
1475
|
+
}, z.core.$strict>>>;
|
|
1381
1476
|
status: z.ZodLiteral<"ready">;
|
|
1382
1477
|
mediaType: z.ZodEnum<{
|
|
1383
1478
|
"audio/mp4": "audio/mp4";
|
|
1384
1479
|
"video/mp4": "video/mp4";
|
|
1480
|
+
"audio/ogg": "audio/ogg";
|
|
1481
|
+
"video/webm": "video/webm";
|
|
1385
1482
|
}>;
|
|
1386
1483
|
sizeBytes: z.ZodNumber;
|
|
1387
1484
|
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
@@ -1404,6 +1501,11 @@ declare const recordingArtifactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
1404
1501
|
}, z.core.$strict>>;
|
|
1405
1502
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
1406
1503
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
1504
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
1505
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1506
|
+
startMs: z.ZodNumber;
|
|
1507
|
+
endMs: z.ZodNumber;
|
|
1508
|
+
}, z.core.$strict>>>;
|
|
1407
1509
|
status: z.ZodLiteral<"failed">;
|
|
1408
1510
|
errorCode: z.ZodEnum<{
|
|
1409
1511
|
recording_failed: "recording_failed";
|
|
@@ -1437,6 +1539,11 @@ declare const listRecordingsResponseSchema: z.ZodObject<{
|
|
|
1437
1539
|
}, z.core.$strict>>;
|
|
1438
1540
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
1439
1541
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
1542
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
1543
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1544
|
+
startMs: z.ZodNumber;
|
|
1545
|
+
endMs: z.ZodNumber;
|
|
1546
|
+
}, z.core.$strict>>>;
|
|
1440
1547
|
status: z.ZodEnum<{
|
|
1441
1548
|
pending: "pending";
|
|
1442
1549
|
recording: "recording";
|
|
@@ -1462,10 +1569,17 @@ declare const listRecordingsResponseSchema: z.ZodObject<{
|
|
|
1462
1569
|
}, z.core.$strict>>;
|
|
1463
1570
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
1464
1571
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
1572
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
1573
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1574
|
+
startMs: z.ZodNumber;
|
|
1575
|
+
endMs: z.ZodNumber;
|
|
1576
|
+
}, z.core.$strict>>>;
|
|
1465
1577
|
status: z.ZodLiteral<"ready">;
|
|
1466
1578
|
mediaType: z.ZodEnum<{
|
|
1467
1579
|
"audio/mp4": "audio/mp4";
|
|
1468
1580
|
"video/mp4": "video/mp4";
|
|
1581
|
+
"audio/ogg": "audio/ogg";
|
|
1582
|
+
"video/webm": "video/webm";
|
|
1469
1583
|
}>;
|
|
1470
1584
|
sizeBytes: z.ZodNumber;
|
|
1471
1585
|
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
@@ -1488,6 +1602,11 @@ declare const listRecordingsResponseSchema: z.ZodObject<{
|
|
|
1488
1602
|
}, z.core.$strict>>;
|
|
1489
1603
|
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
1490
1604
|
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
1605
|
+
mediaStartOffsetMs: z.ZodOptional<z.ZodNumber>;
|
|
1606
|
+
mediaMutedIntervalsMs: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1607
|
+
startMs: z.ZodNumber;
|
|
1608
|
+
endMs: z.ZodNumber;
|
|
1609
|
+
}, z.core.$strict>>>;
|
|
1491
1610
|
status: z.ZodLiteral<"failed">;
|
|
1492
1611
|
errorCode: z.ZodEnum<{
|
|
1493
1612
|
recording_failed: "recording_failed";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as CallMode, a as CallPolicy } from './types-
|
|
1
|
+
import { C as CallMode, a as CallPolicy } from './types-kgmS7ECd.js';
|
|
2
2
|
|
|
3
3
|
/** The three things a caller can ask the proxy to do. Gate on these, not on URLs. */
|
|
4
4
|
type ProxyOperation = "connect" | "end" | "avatars" | "credits";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "realtime-avatar",
|
|
3
|
-
"version": "0.27.
|
|
3
|
+
"version": "0.27.3",
|
|
4
4
|
"description": "Realtime Avatar SDK. `realtime-avatar` and the route adapters hold your API key and are server-only; `realtime-avatar/react`, `/browser` and `/tools` never can — importing a server entry into a browser build throws at bundle time.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "The Influence Company",
|