realtime-avatar 0.22.0 → 0.23.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 +57 -0
- package/dist/{chunk-N76M4MEU.js → chunk-6JLDTWL4.js} +15 -4
- package/dist/{chunk-T3RZSVRI.js → chunk-ICBVEIRK.js} +1 -1
- 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-6ndCkiio.d.ts → proxy-client-DlFXaXtn.d.ts} +130 -6
- package/dist/react-native.d.ts +2 -2
- package/dist/react-native.js +61 -14
- package/dist/react.d.ts +15 -3
- package/dist/react.js +283 -15
- package/dist/recording-DjswTx5B.d.ts +198 -0
- package/dist/recording.d.ts +34 -133
- package/dist/recording.js +42 -4
- 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-Cmto2uGs.d.ts → types-C7s0yw8q.d.ts} +393 -7
- package/dist/{types-k6pW-wKA.d.ts → types-DP4GsT1R.d.ts} +1 -1
- package/package.json +1 -1
package/dist/react.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { RegisteredTool, ToolRegistration } from './tools.js';
|
|
2
|
-
import {
|
|
3
|
-
export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarConnectionDetails,
|
|
2
|
+
import { aj as SessionLifecycleRoomBridgeProps, h as AvatarSessionClient, A as AvatarVideoFit } from './proxy-client-DlFXaXtn.js';
|
|
3
|
+
export { a as AdaptivePlayoutController, b as AdaptivePlayoutDecision, c as AdaptivePlayoutOptions, d as AdaptivePlayoutSample, e as ApproachingEndEvent, f as ApproachingEndReason, g as AvatarConnectionDetails, aQ as AvatarVideoSurface, aR 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_TURN_TIMEOUT_SECONDS, u as DeclaredInputSource, E as EndReason, v as EndedEvent, w as ExtendResult, F as FishTtsModel, x as FreezeReadingFn, G as Governor, y as GovernorAction, z as GovernorConfig, H as GovernorSignal, I as GovernorState, J as GraceWindowClosedEvent, K as GraceWindowOpenEvent, M as GraceWindowState, N as IdleWarningEvent, O as InboundRtpCursor, P as InboundRtpReading, Q as KnownBehaviorState, R as LLMProvider, S as LLMSelection, T as LiveKitAvatarGrantState, U as LiveKitAvatarGrantStatus, V as LiveKitCapacityState, W as LiveKitConnectionStatus, X as LiveKitSessionRequest, Y as LiveKitSessionStartResult, aS as LivePlaybackKeeper, Z as MAX_RECONNECT_ATTEMPTS, _ as MAX_SESSION_INSTRUCTIONS_CHARS, aT as MIC_LEASE_ENDED_TIMEOUT_MS, aU as MicLease, aV as NETWORK_QUALITY_POLICY, aW as NetworkQualityStatus, aX as PlayableVideoElement, $ as ProxyClientOptions, a0 as QualityCap, a1 as RECONNECT_BACKOFF_MS, aY as RealtimeAvatarCapacityError, aZ as RealtimeAvatarLiveKitRoom, a_ as RealtimeAvatarLiveKitRoomProps, a2 as RealtimeAvatarRequestOptions, a3 as RealtimeSessionApi, a4 as RealtimeSessionMedia, a5 as RealtimeSessionRoomSinks, a6 as ReconnectPolicy, a7 as ReconnectingEvent, a8 as RecoveryState, a9 as RetryStep, aa as SendTurnOptions, ab as SessionBehavior, ac as SessionClip, ad as SessionClocks, ae as SessionEndReason, af as SessionLifecycleApi, ag as SessionLifecyclePhase, ah as SessionLifecyclePhaseKind, ai as SessionLifecycleRoomBridge, ak as SurfaceLayers, al as TranscriptSender, am as TranscriptSenderOptions, an as TurnState, ao as TurnTimeoutEvent, ap as UseAvatarQualityGovernorInput, aq as UseLiveKitAvatarGrantInput, ar as UseRealtimeSessionInput, as as UseSessionLifecycleInput, at as VoiceSpec, au as VoiceSpecInput, av as capacityErrorFromBusy, aw as capacityStateFromGrant, ax as createProxyClient, az as knownBehaviorStates, aA as mapTurnState, aB as readInboundRtp, aC as sessionBehaviorSchema, aD as sessionClipSchema, a$ as shouldReplayPendingTurn, aE as splitCallTranscript, aF as useAvatarAdaptivePlayoutDelay, aG as useAvatarCamera, aH as useAvatarPlayoutDelay, aI as useAvatarQualityGovernor, aJ as useCallTranscript, aK as useLiveKitAvatarGrant, aM as useMicLease, aN as useRealtimeSession, aO as useReleaseMicLeaseOnTrackEnded, aP as useSessionLifecycle } from './proxy-client-DlFXaXtn.js';
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
|
+
import { R as RecordingArtifact } from './recording-DjswTx5B.js';
|
|
5
7
|
export { D as DEFAULT_AVATAR_PLAYOUT_DELAY_SECONDS } from './playout-delay-DWOc8iCl.js';
|
|
6
8
|
import 'zod';
|
|
7
9
|
import 'livekit-client';
|
|
@@ -129,4 +131,14 @@ declare function useAvatarCall(props: AvatarCallProps): {
|
|
|
129
131
|
/** One component: a live character on screen. */
|
|
130
132
|
declare function AvatarCall(props: AvatarCallProps): ReactNode;
|
|
131
133
|
|
|
132
|
-
|
|
134
|
+
type RecordingPlaybackAsset = {
|
|
135
|
+
recording: RecordingArtifact;
|
|
136
|
+
url: string;
|
|
137
|
+
};
|
|
138
|
+
/** Each participant file carries only its own voice; one clock drives both files. */
|
|
139
|
+
declare function RecordingPlayer({ assets, className }: {
|
|
140
|
+
assets: readonly RecordingPlaybackAsset[];
|
|
141
|
+
className?: string;
|
|
142
|
+
}): react_jsx_runtime.JSX.Element;
|
|
143
|
+
|
|
144
|
+
export { AvatarCall, type AvatarCallEndReason, type AvatarCallHandle, type AvatarCallProps, type AvatarCallStatus, AvatarSessionClient, AvatarVideoFit, DEFAULT_AVATAR_UNSTABLE_STALL_MS, type RecordingPlaybackAsset, RecordingPlayer, SessionLifecycleRoomBridgeProps, useAvatarCall, useCharacterTools };
|
package/dist/react.js
CHANGED
|
@@ -3,6 +3,7 @@ import { useRef, useState, useEffect, useCallback, useMemo, createElement, Fragm
|
|
|
3
3
|
import { useRoomContext, useConnectionState, useLocalParticipant, useTranscriptions, RoomAudioRenderer, LiveKitRoom, useMaybeRoomContext, useVoiceAssistant, VideoTrack, useChat } from '@livekit/components-react';
|
|
4
4
|
import { ConnectionState, isRemoteTrack, VideoQuality, ConnectionQuality, RoomEvent, TrackEvent, Track, ConnectionError, ConnectionErrorReason, DisconnectReason, createLocalVideoTrack, Room } from 'livekit-client';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
7
|
|
|
7
8
|
// ../client/src/react/use-character-tools.ts
|
|
8
9
|
var invocationSchema = z.object({
|
|
@@ -2119,15 +2120,22 @@ var AVATAR_VIDEO_LIVE_WRAP = "absolute inset-0 z-20 size-full transition-opacity
|
|
|
2119
2120
|
var AVATAR_VIDEO_BADGE = "absolute top-2 right-2 z-30 inline-flex items-center gap-1.5 rounded-md bg-black/55 px-1.5 py-0.5 font-mono text-[10px] text-white/85 backdrop-blur-sm";
|
|
2120
2121
|
var AVATAR_VIDEO_BADGE_DOT = "size-1.5 rounded-full bg-emerald-400";
|
|
2121
2122
|
var RECORDED_MEDIA_MODES = ["audio", "video", "audio_video"];
|
|
2122
|
-
var recordingModeSchema = z.enum(["off", ...RECORDED_MEDIA_MODES]).describe("Server-owned recording policy; omitted means off.
|
|
2123
|
+
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.");
|
|
2123
2124
|
var RECORDING_STATUSES = ["pending", "recording", "processing", "ready", "failed", "expired"];
|
|
2124
2125
|
z.enum(RECORDING_STATUSES);
|
|
2126
|
+
var recordingParticipantSchema = z.object({
|
|
2127
|
+
participantIdentity: z.string().min(1).max(160),
|
|
2128
|
+
role: z.enum(["user", "avatar"])
|
|
2129
|
+
}).strict();
|
|
2125
2130
|
var recordingMetadataSchema = z.object({
|
|
2126
2131
|
sessionId: z.string().min(1),
|
|
2127
2132
|
recordingId: z.string().min(1),
|
|
2128
|
-
mode:
|
|
2133
|
+
mode: z.enum(RECORDED_MEDIA_MODES),
|
|
2129
2134
|
createdAt: z.string().datetime({ offset: true }),
|
|
2130
|
-
retainedUntil: z.string().datetime({ offset: true })
|
|
2135
|
+
retainedUntil: z.string().datetime({ offset: true }),
|
|
2136
|
+
participant: recordingParticipantSchema.optional(),
|
|
2137
|
+
mediaStartedAt: z.string().datetime({ offset: true }).optional(),
|
|
2138
|
+
mediaEndedAt: z.string().datetime({ offset: true }).optional()
|
|
2131
2139
|
});
|
|
2132
2140
|
var recordingArtifactSchema = z.discriminatedUnion("status", [
|
|
2133
2141
|
recordingMetadataSchema.extend({ status: z.enum(["pending", "recording", "processing", "expired"]) }).strict(),
|
|
@@ -2434,6 +2442,8 @@ z.object({
|
|
|
2434
2442
|
}).strict();
|
|
2435
2443
|
z.object({
|
|
2436
2444
|
recording: recordingArtifactSchema.optional(),
|
|
2445
|
+
recording_mode: recordingModeSchema.optional(),
|
|
2446
|
+
recordings: z.array(recordingArtifactSchema).max(2).optional(),
|
|
2437
2447
|
connection_history: connectionHistoryGrantSchema.optional(),
|
|
2438
2448
|
status: z.literal("ready").default("ready"),
|
|
2439
2449
|
session_id: z.string().min(1),
|
|
@@ -2454,6 +2464,11 @@ var RTA_LIFECYCLE_TOPIC = "rta.lifecycle";
|
|
|
2454
2464
|
var RTA_TURN_INSTRUCTIONS_ATTR = "rta.turn_instructions";
|
|
2455
2465
|
var RTA_CLOSING_TURN_ATTR = "rta.closing_turn";
|
|
2456
2466
|
var RTA_TURN_ID_ATTR = "rta.turn_id";
|
|
2467
|
+
var RTA_RETRY_OF_TURN_ID_ATTR = "rta.retry_of_turn_id";
|
|
2468
|
+
var RTA_INPUT_SOURCE_VERSION_ATTR = "rta.input_source_version";
|
|
2469
|
+
var RTA_OBSERVED_INPUT_SOURCE_ATTR = "rta.observed_input_source";
|
|
2470
|
+
var RTA_DECLARED_INPUT_SOURCE_ATTR = "rta.declared_input_source";
|
|
2471
|
+
var RTA_INPUT_SOURCE_DECLARATION_SCOPE_ATTR = "rta.input_source_declaration_scope";
|
|
2457
2472
|
var sessionEndReasonSchema = z.enum([
|
|
2458
2473
|
"user_ended",
|
|
2459
2474
|
"session_cap",
|
|
@@ -3394,6 +3409,11 @@ var DEFAULT_CREDITS_LOW_LEAD_SECONDS = 300;
|
|
|
3394
3409
|
function positive(value, fallbackSeconds) {
|
|
3395
3410
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallbackSeconds;
|
|
3396
3411
|
}
|
|
3412
|
+
function validateInputSource(value) {
|
|
3413
|
+
if (value !== void 0 && value !== "text" && value !== "client_stt") {
|
|
3414
|
+
throw new TypeError('inputSource must be "text" or "client_stt"');
|
|
3415
|
+
}
|
|
3416
|
+
}
|
|
3397
3417
|
function useRealtimeSession(input) {
|
|
3398
3418
|
const {
|
|
3399
3419
|
session,
|
|
@@ -3451,7 +3471,8 @@ function useRealtimeSession(input) {
|
|
|
3451
3471
|
const turnSenderRef = useRef(null);
|
|
3452
3472
|
const dataPublisherRef = useRef(null);
|
|
3453
3473
|
const lastTurnRef = useRef(null);
|
|
3454
|
-
const
|
|
3474
|
+
const turnSequenceRef = useRef(0);
|
|
3475
|
+
const [, setClockTick] = useState(0);
|
|
3455
3476
|
const endsAt = endsAtFrom({
|
|
3456
3477
|
serverStartedAtUnixMs: serverClock?.startedAtUnixMs ?? null,
|
|
3457
3478
|
maxSessionSeconds: serverClock?.maxSessionSeconds ?? null
|
|
@@ -3473,8 +3494,8 @@ function useRealtimeSession(input) {
|
|
|
3473
3494
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
3474
3495
|
} catch {
|
|
3475
3496
|
}
|
|
3476
|
-
return `t-${Date.now()}-${
|
|
3477
|
-
}, [
|
|
3497
|
+
return `t-${Date.now()}-${++turnSequenceRef.current}`;
|
|
3498
|
+
}, []);
|
|
3478
3499
|
const onLifecycleData = useCallback((frame) => {
|
|
3479
3500
|
const parsed = lifecycleServerFrameSchema.safeParse(frame);
|
|
3480
3501
|
if (!parsed.success) return;
|
|
@@ -3574,8 +3595,8 @@ function useRealtimeSession(input) {
|
|
|
3574
3595
|
if (gw === "open" || gw === "delivering") stayConnected();
|
|
3575
3596
|
}
|
|
3576
3597
|
const turnInfo = lastTurnRef.current;
|
|
3577
|
-
if (turnInfo && now - turnInfo.sentAt >= turnTimeoutMs) {
|
|
3578
|
-
|
|
3598
|
+
if (turnInfo && turnInfo.sentAt !== null && now - turnInfo.sentAt >= turnTimeoutMs) {
|
|
3599
|
+
turnInfo.sentAt = null;
|
|
3579
3600
|
cbRef.current.onTurnTimeout?.({ turnId: turnInfo.id });
|
|
3580
3601
|
}
|
|
3581
3602
|
setClockTick((value) => value + 1);
|
|
@@ -3604,6 +3625,7 @@ function useRealtimeSession(input) {
|
|
|
3604
3625
|
}, [phaseKind, lifecycle.phase, lifecycle.attempt]);
|
|
3605
3626
|
useEffect(() => {
|
|
3606
3627
|
if (phaseKind === "ended") {
|
|
3628
|
+
lastTurnRef.current = null;
|
|
3607
3629
|
if (!endedFiredRef.current) {
|
|
3608
3630
|
endedFiredRef.current = true;
|
|
3609
3631
|
const inner2 = lifecycle.phase.kind === "ended" ? lifecycle.phase.reason : void 0;
|
|
@@ -3640,23 +3662,47 @@ function useRealtimeSession(input) {
|
|
|
3640
3662
|
setGraceWindow({ kind: "closed" });
|
|
3641
3663
|
return { ok: true };
|
|
3642
3664
|
}, []);
|
|
3643
|
-
const
|
|
3665
|
+
const sendResolvedTurn = useCallback(async (text, attributes, retryOfTurnId) => {
|
|
3644
3666
|
const trimmed = text.trim();
|
|
3645
3667
|
const sender = turnSenderRef.current;
|
|
3646
3668
|
if (!sender || !trimmed) return;
|
|
3647
3669
|
const turnId = newTurnId();
|
|
3648
|
-
|
|
3670
|
+
const outgoing = { ...attributes, [RTA_TURN_ID_ATTR]: turnId };
|
|
3671
|
+
if (retryOfTurnId) outgoing[RTA_RETRY_OF_TURN_ID_ATTR] = retryOfTurnId;
|
|
3672
|
+
lastTurnRef.current = { text: trimmed, attributes: { ...outgoing }, id: turnId, sentAt: Date.now() };
|
|
3649
3673
|
lifecycle.markActivity();
|
|
3650
|
-
|
|
3651
|
-
await sender(trimmed, attributes ? { attributes } : void 0);
|
|
3674
|
+
await sender(trimmed, { attributes: outgoing });
|
|
3652
3675
|
}, [lifecycle, newTurnId]);
|
|
3676
|
+
const sendInput = useCallback(async (text, opts, adapterSource) => {
|
|
3677
|
+
const turnSource = opts?.inputSource;
|
|
3678
|
+
validateInputSource(turnSource);
|
|
3679
|
+
const declaredSource = turnSource ?? adapterSource;
|
|
3680
|
+
const attributes = {
|
|
3681
|
+
[RTA_INPUT_SOURCE_VERSION_ATTR]: "1",
|
|
3682
|
+
[RTA_OBSERVED_INPUT_SOURCE_ATTR]: "text"
|
|
3683
|
+
};
|
|
3684
|
+
if (declaredSource !== void 0) {
|
|
3685
|
+
attributes[RTA_DECLARED_INPUT_SOURCE_ATTR] = declaredSource;
|
|
3686
|
+
attributes[RTA_INPUT_SOURCE_DECLARATION_SCOPE_ATTR] = turnSource !== void 0 ? "turn" : "adapter";
|
|
3687
|
+
}
|
|
3688
|
+
if (opts?.instructions) attributes[RTA_TURN_INSTRUCTIONS_ATTR] = opts.instructions;
|
|
3689
|
+
await sendResolvedTurn(text, attributes);
|
|
3690
|
+
}, [sendResolvedTurn]);
|
|
3691
|
+
const sendTurn = useCallback((text, opts) => sendInput(text, opts), [sendInput]);
|
|
3692
|
+
const createTranscriptSender = useCallback((opts) => {
|
|
3693
|
+
const source = opts?.inputSource;
|
|
3694
|
+
validateInputSource(source);
|
|
3695
|
+
const boundSource = source ?? "client_stt";
|
|
3696
|
+
return (text, turnOpts) => sendInput(text, turnOpts, boundSource);
|
|
3697
|
+
}, [sendInput]);
|
|
3653
3698
|
const retryTurn = useCallback(() => {
|
|
3654
3699
|
const last = lastTurnRef.current;
|
|
3655
3700
|
if (!last) return;
|
|
3656
|
-
void
|
|
3657
|
-
}, [
|
|
3701
|
+
void sendResolvedTurn(last.text, last.attributes, last.id).catch(() => void 0);
|
|
3702
|
+
}, [sendResolvedTurn]);
|
|
3658
3703
|
const end = useCallback((reason) => {
|
|
3659
3704
|
if (reason) lastLabeledEndReasonRef.current = reason;
|
|
3705
|
+
lastTurnRef.current = null;
|
|
3660
3706
|
requestGracefulClose();
|
|
3661
3707
|
lifecycle.reset();
|
|
3662
3708
|
}, [lifecycle, requestGracefulClose]);
|
|
@@ -3723,6 +3769,7 @@ function useRealtimeSession(input) {
|
|
|
3723
3769
|
requestGracefulClose,
|
|
3724
3770
|
extend,
|
|
3725
3771
|
sendTurn,
|
|
3772
|
+
createTranscriptSender,
|
|
3726
3773
|
retryTurn,
|
|
3727
3774
|
end,
|
|
3728
3775
|
behavior,
|
|
@@ -3745,6 +3792,7 @@ function useRealtimeSession(input) {
|
|
|
3745
3792
|
requestGracefulClose,
|
|
3746
3793
|
extend,
|
|
3747
3794
|
sendTurn,
|
|
3795
|
+
createTranscriptSender,
|
|
3748
3796
|
retryTurn,
|
|
3749
3797
|
end,
|
|
3750
3798
|
behavior,
|
|
@@ -3921,4 +3969,224 @@ function createProxyClient(options) {
|
|
|
3921
3969
|
};
|
|
3922
3970
|
}
|
|
3923
3971
|
|
|
3924
|
-
|
|
3972
|
+
// ../browser/src/recording-playback.ts
|
|
3973
|
+
function recordingTimeline(recordings) {
|
|
3974
|
+
if (new Set(recordings.map((recording) => recording.sessionId)).size > 1) throw new Error("Recordings belong to different sessions");
|
|
3975
|
+
if (new Set(recordings.map((recording) => recording.recordingId)).size !== recordings.length) throw new Error("Duplicate recording assets");
|
|
3976
|
+
const participants = recordings.filter((recording) => recording.participant && recording.status === "ready");
|
|
3977
|
+
if (new Set(participants.map((recording) => recording.participant?.role)).size !== participants.length) throw new Error("Duplicate participant recordings");
|
|
3978
|
+
const entries = participants.map((recording) => {
|
|
3979
|
+
if (recording.status !== "ready" || !recording.mediaStartedAt || !recording.mediaEndedAt || recording.durationMs === null) {
|
|
3980
|
+
throw new Error("Recording media timing is unavailable");
|
|
3981
|
+
}
|
|
3982
|
+
const start = Date.parse(recording.mediaStartedAt);
|
|
3983
|
+
const end = Math.min(Date.parse(recording.mediaEndedAt), start + recording.durationMs);
|
|
3984
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) throw new Error("Recording media timing is invalid");
|
|
3985
|
+
return { recording, start, end };
|
|
3986
|
+
});
|
|
3987
|
+
if (!entries.length) return null;
|
|
3988
|
+
const originMs = Math.min(...entries.map((entry) => entry.start));
|
|
3989
|
+
return {
|
|
3990
|
+
originMs,
|
|
3991
|
+
durationMs: Math.max(...entries.map((entry) => entry.end)) - originMs,
|
|
3992
|
+
entries: entries.map(({ recording, start, end }) => ({ recording, startMs: start - originMs, endMs: end - originMs }))
|
|
3993
|
+
};
|
|
3994
|
+
}
|
|
3995
|
+
function recordingPositions(timeline, positionMs) {
|
|
3996
|
+
return timeline.entries.map((entry) => ({
|
|
3997
|
+
recordingId: entry.recording.recordingId,
|
|
3998
|
+
active: positionMs >= entry.startMs && positionMs < entry.endMs,
|
|
3999
|
+
timeSeconds: Math.max(0, Math.min(positionMs, entry.endMs) - entry.startMs) / 1e3
|
|
4000
|
+
}));
|
|
4001
|
+
}
|
|
4002
|
+
function exhausted(element, seconds) {
|
|
4003
|
+
return Number.isFinite(element.duration) && seconds >= element.duration || element.ended && seconds >= element.currentTime;
|
|
4004
|
+
}
|
|
4005
|
+
function RecordingPlayer({ assets, className }) {
|
|
4006
|
+
const timeline = useMemo(() => {
|
|
4007
|
+
try {
|
|
4008
|
+
return recordingTimeline(assets.map((asset) => asset.recording));
|
|
4009
|
+
} catch {
|
|
4010
|
+
return null;
|
|
4011
|
+
}
|
|
4012
|
+
}, [assets]);
|
|
4013
|
+
const media = useRef(/* @__PURE__ */ new Map());
|
|
4014
|
+
const position = useRef(0);
|
|
4015
|
+
const anchor = useRef(null);
|
|
4016
|
+
const [displayPosition, setDisplayPosition] = useState(0);
|
|
4017
|
+
const [playing, setPlaying] = useState(false);
|
|
4018
|
+
const [buffering, setBuffering] = useState(false);
|
|
4019
|
+
const [error, setError] = useState("");
|
|
4020
|
+
const sourceKey = assets.map((asset) => `${asset.recording.recordingId}:${asset.url}`).join("|");
|
|
4021
|
+
useEffect(() => {
|
|
4022
|
+
if (!timeline) return;
|
|
4023
|
+
const sessionId = timeline.entries[0].recording.sessionId;
|
|
4024
|
+
if (anchor.current?.sessionId === sessionId) {
|
|
4025
|
+
position.current = Math.min(timeline.durationMs, Math.max(0, position.current + anchor.current.originMs - timeline.originMs));
|
|
4026
|
+
} else if (anchor.current) {
|
|
4027
|
+
position.current = 0;
|
|
4028
|
+
setPlaying(false);
|
|
4029
|
+
}
|
|
4030
|
+
anchor.current = { sessionId, originMs: timeline.originMs };
|
|
4031
|
+
setDisplayPosition(position.current);
|
|
4032
|
+
let cancelled = false;
|
|
4033
|
+
let frame = 0;
|
|
4034
|
+
let last = performance.now();
|
|
4035
|
+
let painted = last;
|
|
4036
|
+
const starting = /* @__PURE__ */ new Set();
|
|
4037
|
+
const stopMedia = () => {
|
|
4038
|
+
for (const element of media.current.values()) element.pause();
|
|
4039
|
+
};
|
|
4040
|
+
const fail = () => {
|
|
4041
|
+
if (cancelled) return;
|
|
4042
|
+
stopMedia();
|
|
4043
|
+
setPlaying(false);
|
|
4044
|
+
setError("Playback is unavailable. Refresh access and try again.");
|
|
4045
|
+
};
|
|
4046
|
+
const update = (now) => {
|
|
4047
|
+
if (cancelled) return;
|
|
4048
|
+
const proposed = Math.min(timeline.durationMs, position.current + (playing ? now - last : 0));
|
|
4049
|
+
last = now;
|
|
4050
|
+
const states = recordingPositions(timeline, proposed);
|
|
4051
|
+
const waiting = playing && states.some((state) => {
|
|
4052
|
+
const element = media.current.get(state.recordingId);
|
|
4053
|
+
return state.active && (!element || !exhausted(element, state.timeSeconds) && (element.readyState < 2 || element.seeking));
|
|
4054
|
+
});
|
|
4055
|
+
setBuffering(waiting);
|
|
4056
|
+
if (!waiting) position.current = proposed;
|
|
4057
|
+
for (const state of recordingPositions(timeline, position.current)) {
|
|
4058
|
+
const element = media.current.get(state.recordingId);
|
|
4059
|
+
if (!element) continue;
|
|
4060
|
+
if (!state.active || exhausted(element, state.timeSeconds)) {
|
|
4061
|
+
element.pause();
|
|
4062
|
+
continue;
|
|
4063
|
+
}
|
|
4064
|
+
if (element.readyState >= 1 && Math.abs(element.currentTime - state.timeSeconds) > 0.08) {
|
|
4065
|
+
element.currentTime = state.timeSeconds;
|
|
4066
|
+
}
|
|
4067
|
+
if (!playing || waiting) {
|
|
4068
|
+
element.pause();
|
|
4069
|
+
continue;
|
|
4070
|
+
}
|
|
4071
|
+
if (element.paused && !starting.has(state.recordingId)) {
|
|
4072
|
+
starting.add(state.recordingId);
|
|
4073
|
+
void element.play().catch((cause) => {
|
|
4074
|
+
if (!(cause instanceof Error && cause.name === "AbortError")) fail();
|
|
4075
|
+
}).finally(() => {
|
|
4076
|
+
starting.delete(state.recordingId);
|
|
4077
|
+
});
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
if (now - painted >= 100 || !playing || position.current >= timeline.durationMs) {
|
|
4081
|
+
setDisplayPosition(position.current);
|
|
4082
|
+
painted = now;
|
|
4083
|
+
}
|
|
4084
|
+
if (position.current >= timeline.durationMs) {
|
|
4085
|
+
stopMedia();
|
|
4086
|
+
setPlaying(false);
|
|
4087
|
+
}
|
|
4088
|
+
frame = requestAnimationFrame(update);
|
|
4089
|
+
};
|
|
4090
|
+
if (playing) frame = requestAnimationFrame(update);
|
|
4091
|
+
else {
|
|
4092
|
+
stopMedia();
|
|
4093
|
+
setBuffering(false);
|
|
4094
|
+
}
|
|
4095
|
+
return () => {
|
|
4096
|
+
cancelled = true;
|
|
4097
|
+
cancelAnimationFrame(frame);
|
|
4098
|
+
stopMedia();
|
|
4099
|
+
};
|
|
4100
|
+
}, [timeline, playing, sourceKey]);
|
|
4101
|
+
const activeIds = new Set(timeline ? recordingPositions(timeline, displayPosition).filter((state) => state.active).map((state) => state.recordingId) : []);
|
|
4102
|
+
const seek = (value) => {
|
|
4103
|
+
position.current = value;
|
|
4104
|
+
setDisplayPosition(value);
|
|
4105
|
+
if (timeline) for (const state of recordingPositions(timeline, value)) {
|
|
4106
|
+
const element = media.current.get(state.recordingId);
|
|
4107
|
+
if (!element) continue;
|
|
4108
|
+
if (element.readyState >= 1) element.currentTime = state.timeSeconds;
|
|
4109
|
+
if (!state.active) element.pause();
|
|
4110
|
+
}
|
|
4111
|
+
};
|
|
4112
|
+
const toggle = () => {
|
|
4113
|
+
setError("");
|
|
4114
|
+
if (playing) {
|
|
4115
|
+
setPlaying(false);
|
|
4116
|
+
return;
|
|
4117
|
+
}
|
|
4118
|
+
if (!timeline) return;
|
|
4119
|
+
if (position.current >= timeline.durationMs) seek(0);
|
|
4120
|
+
for (const state of recordingPositions(timeline, position.current)) {
|
|
4121
|
+
const element = media.current.get(state.recordingId);
|
|
4122
|
+
if (state.active && element && !exhausted(element, state.timeSeconds)) {
|
|
4123
|
+
if (element.readyState >= 1) element.currentTime = state.timeSeconds;
|
|
4124
|
+
void element.play().catch((cause) => {
|
|
4125
|
+
if (cause instanceof Error && cause.name === "AbortError") return;
|
|
4126
|
+
for (const current of media.current.values()) current.pause();
|
|
4127
|
+
setPlaying(false);
|
|
4128
|
+
setError("Your browser could not play this recording. Try again or download the original.");
|
|
4129
|
+
});
|
|
4130
|
+
}
|
|
4131
|
+
}
|
|
4132
|
+
setPlaying(true);
|
|
4133
|
+
};
|
|
4134
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
4135
|
+
/* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 240px), 1fr))", gap: 12 }, children: assets.map(({ recording, url }) => {
|
|
4136
|
+
if (!recording.participant) return null;
|
|
4137
|
+
const label = recording.participant.role === "user" ? "User" : "Character";
|
|
4138
|
+
const ref = (element) => {
|
|
4139
|
+
if (element) media.current.set(recording.recordingId, element);
|
|
4140
|
+
else media.current.delete(recording.recordingId);
|
|
4141
|
+
};
|
|
4142
|
+
const onError = () => {
|
|
4143
|
+
for (const current of media.current.values()) current.pause();
|
|
4144
|
+
setPlaying(false);
|
|
4145
|
+
setError("A recording could not load. Refresh access and try again.");
|
|
4146
|
+
};
|
|
4147
|
+
return recording.mode !== "audio" ? /* @__PURE__ */ jsxs("figure", { hidden: !activeIds.has(recording.recordingId), style: { margin: 0 }, children: [
|
|
4148
|
+
/* @__PURE__ */ jsx("figcaption", { children: label }),
|
|
4149
|
+
/* @__PURE__ */ jsx(
|
|
4150
|
+
"video",
|
|
4151
|
+
{
|
|
4152
|
+
ref,
|
|
4153
|
+
src: url,
|
|
4154
|
+
playsInline: true,
|
|
4155
|
+
preload: "auto",
|
|
4156
|
+
onError,
|
|
4157
|
+
hidden: !activeIds.has(recording.recordingId),
|
|
4158
|
+
style: { width: "100%", maxHeight: 360, objectFit: "contain" }
|
|
4159
|
+
}
|
|
4160
|
+
),
|
|
4161
|
+
!activeIds.has(recording.recordingId) ? /* @__PURE__ */ jsx("p", { children: "No recording at this time." }) : null
|
|
4162
|
+
] }, recording.recordingId) : /* @__PURE__ */ jsx("audio", { ref, src: url, preload: "auto", onError, "aria-label": `${label} audio` }, recording.recordingId);
|
|
4163
|
+
}) }),
|
|
4164
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
|
|
4165
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: toggle, disabled: !timeline, style: { minHeight: 44, minWidth: 44 }, children: playing ? "Pause" : "Play" }),
|
|
4166
|
+
/* @__PURE__ */ jsx(
|
|
4167
|
+
"input",
|
|
4168
|
+
{
|
|
4169
|
+
type: "range",
|
|
4170
|
+
"aria-label": "Call playback position",
|
|
4171
|
+
min: 0,
|
|
4172
|
+
max: timeline?.durationMs ?? 0,
|
|
4173
|
+
step: 100,
|
|
4174
|
+
value: displayPosition,
|
|
4175
|
+
"aria-valuetext": `${Math.floor(displayPosition / 1e3)} seconds`,
|
|
4176
|
+
disabled: !timeline,
|
|
4177
|
+
onChange: (event) => seek(Number(event.currentTarget.value)),
|
|
4178
|
+
style: { minHeight: 44, flex: 1 }
|
|
4179
|
+
}
|
|
4180
|
+
),
|
|
4181
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
4182
|
+
Math.floor(displayPosition / 1e3),
|
|
4183
|
+
" / ",
|
|
4184
|
+
Math.ceil((timeline?.durationMs ?? 0) / 1e3),
|
|
4185
|
+
" s"
|
|
4186
|
+
] })
|
|
4187
|
+
] }),
|
|
4188
|
+
/* @__PURE__ */ jsx("p", { role: "status", children: error || (!timeline ? "Media timing is unavailable. Individual recordings can still be downloaded." : buffering ? "Buffering\u2026" : "") })
|
|
4189
|
+
] });
|
|
4190
|
+
}
|
|
4191
|
+
|
|
4192
|
+
export { AdaptivePlayoutController, AvatarCall, AvatarVideoSurface, DEFAULT_APPROACHING_END_LEAD_SECONDS, DEFAULT_AVATAR_PLAYOUT_DELAY_SECONDS, DEFAULT_AVATAR_UNSTABLE_STALL_MS, DEFAULT_CREDITS_LOW_LEAD_SECONDS, DEFAULT_GOVERNOR_CONFIG, DEFAULT_GRACE_CEILING_SECONDS, DEFAULT_GRACE_WINDOW_LEAD_SECONDS, DEFAULT_IDLE_SECONDS, DEFAULT_IDLE_WARN_LEAD_SECONDS, DEFAULT_TURN_TIMEOUT_SECONDS, MAX_RECONNECT_ATTEMPTS, MAX_SESSION_INSTRUCTIONS_CHARS, MIC_LEASE_ENDED_TIMEOUT_MS, NETWORK_QUALITY_POLICY, RECONNECT_BACKOFF_MS, RealtimeAvatarCapacityError, RealtimeAvatarLiveKitRoom, RecordingPlayer, SessionLifecycleRoomBridge, capacityErrorFromBusy, capacityStateFromGrant, createProxyClient, knownBehaviorStates, mapTurnState, readInboundRtp, sessionBehaviorSchema, sessionClipSchema, shouldReplayPendingTurn, splitCallTranscript, useAvatarAdaptivePlayoutDelay, useAvatarCall, useAvatarCamera, useAvatarPlayoutDelay, useAvatarQualityGovernor, useCallTranscript, useCharacterTools, useLiveKitAvatarGrant, useMicLease, useRealtimeSession, useReleaseMicLeaseOnTrackEnded, useSessionLifecycle };
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const recordingModeSchema: z.ZodEnum<{
|
|
4
|
+
audio: "audio";
|
|
5
|
+
video: "video";
|
|
6
|
+
audio_video: "audio_video";
|
|
7
|
+
off: "off";
|
|
8
|
+
participants: "participants";
|
|
9
|
+
}>;
|
|
10
|
+
type RecordingMode = z.infer<typeof recordingModeSchema>;
|
|
11
|
+
declare const recordingArtifactStatusSchema: z.ZodEnum<{
|
|
12
|
+
ready: "ready";
|
|
13
|
+
pending: "pending";
|
|
14
|
+
recording: "recording";
|
|
15
|
+
processing: "processing";
|
|
16
|
+
failed: "failed";
|
|
17
|
+
expired: "expired";
|
|
18
|
+
}>;
|
|
19
|
+
type RecordingArtifactStatus = z.infer<typeof recordingArtifactStatusSchema>;
|
|
20
|
+
declare const recordingParticipantSchema: z.ZodObject<{
|
|
21
|
+
participantIdentity: z.ZodString;
|
|
22
|
+
role: z.ZodEnum<{
|
|
23
|
+
user: "user";
|
|
24
|
+
avatar: "avatar";
|
|
25
|
+
}>;
|
|
26
|
+
}, z.core.$strict>;
|
|
27
|
+
type RecordingParticipant = z.infer<typeof recordingParticipantSchema>;
|
|
28
|
+
declare const recordingArtifactSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
29
|
+
sessionId: z.ZodString;
|
|
30
|
+
recordingId: z.ZodString;
|
|
31
|
+
mode: z.ZodEnum<{
|
|
32
|
+
audio: "audio";
|
|
33
|
+
video: "video";
|
|
34
|
+
audio_video: "audio_video";
|
|
35
|
+
}>;
|
|
36
|
+
createdAt: z.ZodString;
|
|
37
|
+
retainedUntil: z.ZodString;
|
|
38
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
39
|
+
participantIdentity: z.ZodString;
|
|
40
|
+
role: z.ZodEnum<{
|
|
41
|
+
user: "user";
|
|
42
|
+
avatar: "avatar";
|
|
43
|
+
}>;
|
|
44
|
+
}, z.core.$strict>>;
|
|
45
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
46
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
47
|
+
status: z.ZodEnum<{
|
|
48
|
+
pending: "pending";
|
|
49
|
+
recording: "recording";
|
|
50
|
+
processing: "processing";
|
|
51
|
+
expired: "expired";
|
|
52
|
+
}>;
|
|
53
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
54
|
+
sessionId: z.ZodString;
|
|
55
|
+
recordingId: z.ZodString;
|
|
56
|
+
mode: z.ZodEnum<{
|
|
57
|
+
audio: "audio";
|
|
58
|
+
video: "video";
|
|
59
|
+
audio_video: "audio_video";
|
|
60
|
+
}>;
|
|
61
|
+
createdAt: z.ZodString;
|
|
62
|
+
retainedUntil: z.ZodString;
|
|
63
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
64
|
+
participantIdentity: z.ZodString;
|
|
65
|
+
role: z.ZodEnum<{
|
|
66
|
+
user: "user";
|
|
67
|
+
avatar: "avatar";
|
|
68
|
+
}>;
|
|
69
|
+
}, z.core.$strict>>;
|
|
70
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
71
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
72
|
+
status: z.ZodLiteral<"ready">;
|
|
73
|
+
mediaType: z.ZodEnum<{
|
|
74
|
+
"audio/mp4": "audio/mp4";
|
|
75
|
+
"video/mp4": "video/mp4";
|
|
76
|
+
}>;
|
|
77
|
+
sizeBytes: z.ZodNumber;
|
|
78
|
+
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
79
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
80
|
+
sessionId: z.ZodString;
|
|
81
|
+
recordingId: z.ZodString;
|
|
82
|
+
mode: z.ZodEnum<{
|
|
83
|
+
audio: "audio";
|
|
84
|
+
video: "video";
|
|
85
|
+
audio_video: "audio_video";
|
|
86
|
+
}>;
|
|
87
|
+
createdAt: z.ZodString;
|
|
88
|
+
retainedUntil: z.ZodString;
|
|
89
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
90
|
+
participantIdentity: z.ZodString;
|
|
91
|
+
role: z.ZodEnum<{
|
|
92
|
+
user: "user";
|
|
93
|
+
avatar: "avatar";
|
|
94
|
+
}>;
|
|
95
|
+
}, z.core.$strict>>;
|
|
96
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
97
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
98
|
+
status: z.ZodLiteral<"failed">;
|
|
99
|
+
errorCode: z.ZodEnum<{
|
|
100
|
+
recording_failed: "recording_failed";
|
|
101
|
+
recording_unavailable: "recording_unavailable";
|
|
102
|
+
}>;
|
|
103
|
+
}, z.core.$strict>], "status">;
|
|
104
|
+
type RecordingArtifact = z.infer<typeof recordingArtifactSchema>;
|
|
105
|
+
declare const listRecordingsQuerySchema: z.ZodObject<{
|
|
106
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
107
|
+
limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
108
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
109
|
+
}, z.core.$strict>;
|
|
110
|
+
type ListRecordingsQuery = Partial<z.infer<typeof listRecordingsQuerySchema>>;
|
|
111
|
+
declare const listRecordingsResponseSchema: z.ZodObject<{
|
|
112
|
+
data: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
113
|
+
sessionId: z.ZodString;
|
|
114
|
+
recordingId: z.ZodString;
|
|
115
|
+
mode: z.ZodEnum<{
|
|
116
|
+
audio: "audio";
|
|
117
|
+
video: "video";
|
|
118
|
+
audio_video: "audio_video";
|
|
119
|
+
}>;
|
|
120
|
+
createdAt: z.ZodString;
|
|
121
|
+
retainedUntil: z.ZodString;
|
|
122
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
123
|
+
participantIdentity: z.ZodString;
|
|
124
|
+
role: z.ZodEnum<{
|
|
125
|
+
user: "user";
|
|
126
|
+
avatar: "avatar";
|
|
127
|
+
}>;
|
|
128
|
+
}, z.core.$strict>>;
|
|
129
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
130
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
131
|
+
status: z.ZodEnum<{
|
|
132
|
+
pending: "pending";
|
|
133
|
+
recording: "recording";
|
|
134
|
+
processing: "processing";
|
|
135
|
+
expired: "expired";
|
|
136
|
+
}>;
|
|
137
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
138
|
+
sessionId: z.ZodString;
|
|
139
|
+
recordingId: z.ZodString;
|
|
140
|
+
mode: z.ZodEnum<{
|
|
141
|
+
audio: "audio";
|
|
142
|
+
video: "video";
|
|
143
|
+
audio_video: "audio_video";
|
|
144
|
+
}>;
|
|
145
|
+
createdAt: z.ZodString;
|
|
146
|
+
retainedUntil: z.ZodString;
|
|
147
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
148
|
+
participantIdentity: z.ZodString;
|
|
149
|
+
role: z.ZodEnum<{
|
|
150
|
+
user: "user";
|
|
151
|
+
avatar: "avatar";
|
|
152
|
+
}>;
|
|
153
|
+
}, z.core.$strict>>;
|
|
154
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
155
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
156
|
+
status: z.ZodLiteral<"ready">;
|
|
157
|
+
mediaType: z.ZodEnum<{
|
|
158
|
+
"audio/mp4": "audio/mp4";
|
|
159
|
+
"video/mp4": "video/mp4";
|
|
160
|
+
}>;
|
|
161
|
+
sizeBytes: z.ZodNumber;
|
|
162
|
+
durationMs: z.ZodNullable<z.ZodNumber>;
|
|
163
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
164
|
+
sessionId: z.ZodString;
|
|
165
|
+
recordingId: z.ZodString;
|
|
166
|
+
mode: z.ZodEnum<{
|
|
167
|
+
audio: "audio";
|
|
168
|
+
video: "video";
|
|
169
|
+
audio_video: "audio_video";
|
|
170
|
+
}>;
|
|
171
|
+
createdAt: z.ZodString;
|
|
172
|
+
retainedUntil: z.ZodString;
|
|
173
|
+
participant: z.ZodOptional<z.ZodObject<{
|
|
174
|
+
participantIdentity: z.ZodString;
|
|
175
|
+
role: z.ZodEnum<{
|
|
176
|
+
user: "user";
|
|
177
|
+
avatar: "avatar";
|
|
178
|
+
}>;
|
|
179
|
+
}, z.core.$strict>>;
|
|
180
|
+
mediaStartedAt: z.ZodOptional<z.ZodString>;
|
|
181
|
+
mediaEndedAt: z.ZodOptional<z.ZodString>;
|
|
182
|
+
status: z.ZodLiteral<"failed">;
|
|
183
|
+
errorCode: z.ZodEnum<{
|
|
184
|
+
recording_failed: "recording_failed";
|
|
185
|
+
recording_unavailable: "recording_unavailable";
|
|
186
|
+
}>;
|
|
187
|
+
}, z.core.$strict>], "status">>;
|
|
188
|
+
nextCursor: z.ZodNullable<z.ZodString>;
|
|
189
|
+
}, z.core.$strict>;
|
|
190
|
+
type ListRecordingsResponse = z.infer<typeof listRecordingsResponseSchema>;
|
|
191
|
+
declare const recordingAccessResponseSchema: z.ZodObject<{
|
|
192
|
+
recordingId: z.ZodString;
|
|
193
|
+
url: z.ZodString;
|
|
194
|
+
expiresAt: z.ZodString;
|
|
195
|
+
}, z.core.$strict>;
|
|
196
|
+
type RecordingAccessResponse = z.infer<typeof recordingAccessResponseSchema>;
|
|
197
|
+
|
|
198
|
+
export { type ListRecordingsQuery as L, type RecordingArtifact as R, type ListRecordingsResponse as a, type RecordingAccessResponse as b, type RecordingArtifactStatus as c, type RecordingMode as d, type RecordingParticipant as e, listRecordingsResponseSchema as f, recordingArtifactSchema as g, recordingArtifactStatusSchema as h, recordingModeSchema as i, recordingParticipantSchema as j, listRecordingsQuerySchema as l, recordingAccessResponseSchema as r };
|