@xmaxai/sdk 1.0.1 → 1.0.2
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/CHANGELOG.md +10 -2
- package/README.md +9 -5
- package/dist/{chunk-V4NR6CPP.js → chunk-F567ONBH.js} +7 -184
- package/dist/chunk-F567ONBH.js.map +1 -0
- package/dist/{chunk-LCPC56BK.js → chunk-TFGYBN3Q.js} +493 -136
- package/dist/chunk-TFGYBN3Q.js.map +1 -0
- package/dist/index.cjs +30 -272
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +369 -8
- package/dist/index.d.ts +369 -8
- package/dist/index.js +1003 -9
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +9 -271
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +1 -3
- package/dist/react/index.d.ts +1 -3
- package/dist/react/index.js +6 -26
- package/dist/react/index.js.map +1 -1
- package/dist/{rtc-manager-gYDkADGw.d.ts → rtc-manager-DnQoznIg.d.cts} +2 -17
- package/dist/{rtc-manager-gYDkADGw.d.cts → rtc-manager-DnQoznIg.d.ts} +2 -17
- package/dist/video-file-stream-4TAGKL2Q.js +3 -0
- package/dist/{video-file-stream-K7GQMIJ5.js.map → video-file-stream-4TAGKL2Q.js.map} +1 -1
- package/package.json +1 -6
- package/dist/chunk-4YHBCQ2C.js +0 -432
- package/dist/chunk-4YHBCQ2C.js.map +0 -1
- package/dist/chunk-LCPC56BK.js.map +0 -1
- package/dist/chunk-V4NR6CPP.js.map +0 -1
- package/dist/chunk-VLJZ56PT.js +0 -997
- package/dist/chunk-VLJZ56PT.js.map +0 -1
- package/dist/experimental/index.cjs +0 -3897
- package/dist/experimental/index.cjs.map +0 -1
- package/dist/experimental/index.d.cts +0 -2
- package/dist/experimental/index.d.ts +0 -2
- package/dist/experimental/index.js +0 -5
- package/dist/experimental/index.js.map +0 -1
- package/dist/index-Cw8C8LbO.d.ts +0 -367
- package/dist/index-Dg1ElHAj.d.cts +0 -367
- package/dist/video-file-stream-K7GQMIJ5.js +0 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/i18n/en-US.ts","../src/i18n/zh-CN.ts","../src/i18n/api-error-codes.ts","../src/i18n/index.ts","../src/rtc/publish-fps.ts","../src/shared/reference-video-size.ts","../src/rtc/capture-crop.ts","../src/rtc/canvas-frame-draw.ts","../src/rtc/capture-host.ts","../src/rtc/video-frame-rate.ts","../src/rtc/video-file-stream.ts"],"names":["width","height"],"mappings":"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","file":"chunk-TFGYBN3Q.js","sourcesContent":["export const enUS = {\n 'errors.apiKeyEmpty': 'apiKey cannot be empty',\n 'errors.baseUrlEmpty': 'baseUrl is required — pass XMAX_OPEN_API_PRODUCTION_BASE_URL for production',\n 'errors.modelEmpty': 'model cannot be empty',\n 'errors.invalidJson': 'Response is not valid JSON',\n 'errors.invalidPayload': 'Response payload is invalid',\n 'errors.requestFailed': 'Request failed',\n 'errors.requestRetry': 'Request failed. Please try again later.',\n 'errors.requestTimeout': 'Request timeout',\n 'errors.invalidFile': 'file must be a File',\n 'errors.invalidFileType': 'invalid file type: {type}',\n 'errors.sessionJoinInfoIncomplete': 'session does not contain complete RTC join info',\n 'errors.sessionUidMissing': 'session does not contain sessionUid',\n 'errors.refImageMissing': 'missing reference image',\n 'errors.captureStreamUnsupported': 'captureStream is not supported in this browser',\n 'errors.videoTrackMissing': 'failed to create video track from file',\n 'errors.imageTrackMissing': 'failed to create video track from image file',\n 'errors.imageLoadFailed': 'failed to load image — try again after selecting the file',\n 'errors.invalidMediaFileType': 'unsupported media file type: {type}',\n 'errors.videoPlaybackFailed': 'failed to start video playback — try again after selecting the file',\n 'errors.rtcNotJoined': 'Please join the RTC room first',\n 'errors.rtcNotJoinedForMessaging': 'Please join the RTC room before sending events',\n\n 'rtc.alreadyInRoom': 'RTC is already in the target room. Skip duplicate join.',\n 'rtc.joiningRoom': 'Joining RTC room',\n 'rtc.joinSuccess': 'RTC joinRoom succeeded',\n 'rtc.roomUsers': 'Current room users: {users}',\n 'rtc.localVideoAlreadyPublished': 'Local video is already published',\n 'rtc.localVideoPublished': 'Local video capture started and stream published',\n 'rtc.externalVideoPublished': 'External video stream published',\n 'rtc.localVideoStopped': 'Local video publishing stopped',\n 'rtc.leaveRoomError': 'Error occurred during RTC leaveRoom',\n 'rtc.engineDestroyed': 'RTC engine destroyed',\n 'rtc.roomEventSent': 'RTC event sent',\n 'rtc.remotePlayerRefreshed': 'Remote video player refreshed: {userId}',\n 'rtc.remotePlayerRefreshFailed': 'Failed to refresh remote video player',\n 'rtc.userJoined': 'User joined RTC room: {userId}',\n 'rtc.userLeft': 'User left RTC room: {userId}',\n 'rtc.connectionStateChanged': 'RTC connection state changed',\n 'rtc.userPublished': 'User published stream: {userId}',\n 'rtc.userUnpublished': 'User unpublished stream: {userId}',\n 'rtc.seiReceived': 'Remote SEI received: {userId}',\n 'rtc.error': 'RTC error: {code}',\n 'rtc.captureSizeSet': 'Local video capture size set: {width} x {height}',\n 'rtc.encoderPreferenceSet': 'Video encoder preference set to H.264',\n 'rtc.encoderPreferenceFailed': 'Failed to set video encoder preference',\n 'rtc.remoteWaitSei': 'Remote video is waiting for SEI gate: {userId}',\n 'rtc.remoteContainerNotReady': 'Remote video container is not ready. Skip binding.',\n 'rtc.remotePlayerBound': 'Remote video player bound: {userId}',\n 'rtc.remoteOutputStalled': 'Remote output stalled for 15s; attempting to recover generation',\n 'rtc.sendSeiFailed': 'Failed to send SEI. The browser or encoder config may not support it.',\n 'rtc.seiUnsupported': 'H.264 is not supported. SEI gate will be disabled and output will not be blocked.',\n 'rtc.seiGateFallback': 'SEI gate timed out — showing remote output',\n 'rtc.getCodecsFailed': 'Failed to get supported codecs. SEI gate will be disabled and output will not be blocked.',\n} as const\n","export const zhCN = {\n 'errors.apiKeyEmpty': 'apiKey 不能为空',\n 'errors.baseUrlEmpty': 'baseUrl 为必填项 — 生产环境请传入 XMAX_OPEN_API_PRODUCTION_BASE_URL',\n 'errors.modelEmpty': 'model 不能为空',\n 'errors.invalidJson': '响应不是有效的 JSON',\n 'errors.invalidPayload': '响应数据格式不正确',\n 'errors.requestFailed': '请求失败',\n 'errors.requestRetry': '请求失败,请稍后再试',\n 'errors.requestTimeout': '请求超时',\n 'errors.invalidFile': 'file 必须是 File 类型',\n 'errors.invalidFileType': '文件类型不正确:{type}',\n 'errors.sessionJoinInfoIncomplete': 'session 缺少完整的 RTC 进房信息',\n 'errors.sessionUidMissing': 'session 缺少 sessionUid',\n 'errors.refImageMissing': '缺少参考图',\n 'errors.captureStreamUnsupported': '当前浏览器不支持 captureStream',\n 'errors.videoTrackMissing': '未能从视频文件创建 video track',\n 'errors.imageTrackMissing': '未能从图片文件创建 video track',\n 'errors.imageLoadFailed': '图片无法加载,请重新选择文件后再试',\n 'errors.invalidMediaFileType': '不支持的媒体文件类型:{type}',\n 'errors.videoPlaybackFailed': '视频无法开始播放,请重新选择文件后再试',\n 'errors.rtcNotJoined': '请先成功加入 RTC 房间',\n 'errors.rtcNotJoinedForMessaging': '请先成功加入 RTC 房间后再发送事件',\n\n 'rtc.alreadyInRoom': 'RTC 已在目标房间中,跳过重复进房',\n 'rtc.joiningRoom': '准备加入 RTC 房间',\n 'rtc.joinSuccess': 'RTC joinRoom 成功',\n 'rtc.roomUsers': '当前房间用户: {users}',\n 'rtc.localVideoAlreadyPublished': '本地视频已处于发布状态',\n 'rtc.localVideoPublished': '已开启本地视频采集并发布视频流',\n 'rtc.externalVideoPublished': '已发布自定义视频流',\n 'rtc.localVideoStopped': '已停止本地视频发布',\n 'rtc.leaveRoomError': 'RTC leaveRoom 过程中出现异常',\n 'rtc.engineDestroyed': 'RTC 引擎已销毁',\n 'rtc.roomEventSent': '已发送 RTC 事件',\n 'rtc.remotePlayerRefreshed': '已刷新远端视频播放器: {userId}',\n 'rtc.remotePlayerRefreshFailed': '刷新远端视频播放器失败',\n 'rtc.userJoined': '用户加入 RTC 房间: {userId}',\n 'rtc.userLeft': '用户离开 RTC 房间: {userId}',\n 'rtc.connectionStateChanged': 'RTC 连接状态变化',\n 'rtc.userPublished': '用户发布流: {userId}',\n 'rtc.userUnpublished': '用户取消发布流: {userId}',\n 'rtc.seiReceived': '收到远端 SEI: {userId}',\n 'rtc.error': 'RTC 错误: {code}',\n 'rtc.captureSizeSet': '已设置本地视频采集尺寸: {width} x {height}',\n 'rtc.encoderPreferenceSet': '已设置视频编码偏好为 H.264',\n 'rtc.encoderPreferenceFailed': '设置视频编码偏好失败',\n 'rtc.remoteWaitSei': '远端视频等待 SEI 放行: {userId}',\n 'rtc.remoteContainerNotReady': '远端视频容器未就绪,跳过绑定',\n 'rtc.remotePlayerBound': '已绑定远端视频播放器: {userId}',\n 'rtc.remoteOutputStalled': '远端输出超过 15 秒无新帧,尝试恢复生成任务',\n 'rtc.sendSeiFailed': '发送 SEI 失败,当前浏览器或编码配置可能不支持该能力',\n 'rtc.seiUnsupported': '当前环境不支持 H.264,SEI gate 将不会生效,output 将不再被拦截',\n 'rtc.seiGateFallback': 'SEI 门控超时,已显示远端输出',\n 'rtc.getCodecsFailed': '获取浏览器编解码支持失败,SEI gate 将不会生效,output 将不再被拦截',\n} as const\n","import type { SDKLocale } from './index'\n\n/**\n * Open API business error codes (46xxx) mapped to user-facing messages.\n * Source: Open API v1 error code tables. Codes not listed here fall back to the\n * backend `message` when present, otherwise a generic retry message for Open\n * API endpoints (see `errors.requestRetry`).\n */\ntype LocalizedMessage = Record<SDKLocale, string>\n\n/** 46006–46010 are internal capacity/permission failures; surfaced as a single overload hint. */\nconst SYSTEM_OVERLOADED: LocalizedMessage = {\n 'zh-CN': '当前使用人数过多,请稍后再试',\n 'en-US': 'The system is currently overloaded. Please retry after some time.',\n}\n\nexport const API_ERROR_MESSAGES: Record<string, LocalizedMessage> = {\n '46001': { 'zh-CN': 'X-Api-Key 不能为空', 'en-US': 'X-Api-Key cannot be empty' },\n '46002': { 'zh-CN': '无效的用户 API Key', 'en-US': 'Invalid user API Key' },\n '46003': { 'zh-CN': 'model 不能为空', 'en-US': 'model cannot be empty' },\n '46004': { 'zh-CN': 'sessionUid 不能为空', 'en-US': 'sessionUid cannot be empty' },\n '46005': { 'zh-CN': '模型类型不存在', 'en-US': 'Model type does not exist' },\n '46006': SYSTEM_OVERLOADED,\n '46007': SYSTEM_OVERLOADED,\n '46008': SYSTEM_OVERLOADED,\n '46009': SYSTEM_OVERLOADED,\n '46010': SYSTEM_OVERLOADED,\n '46012': { 'zh-CN': '会话不存在', 'en-US': 'Session does not exist' },\n '46013': { 'zh-CN': '会话不属于当前用户', 'en-US': 'Session does not belong to the current user' },\n '46014': { 'zh-CN': '会话已关闭', 'en-US': 'Session has been closed' },\n '46015': { 'zh-CN': '会话已超时', 'en-US': 'Session has timed out' },\n '46018': { 'zh-CN': '临时 API Key 已过期', 'en-US': 'Temporary API Key has expired' },\n '46019': {\n 'zh-CN': '临时 API Key 已达到积分上限',\n 'en-US': 'Temporary API Key has reached its points limit',\n },\n '46021': {\n 'zh-CN': '临时 API Key 不允许再创建临时 API Key',\n 'en-US': 'A temporary API Key cannot create another temporary API Key',\n },\n \n}\n\n/** Resolve a business error code to a localized message, or `undefined` if unmapped. */\nexport function resolveApiErrorMessage(\n code: string | number | null | undefined,\n locale: SDKLocale,\n): string | undefined {\n if (code === null || code === undefined) return undefined\n const entry = API_ERROR_MESSAGES[String(code)]\n if (!entry) return undefined\n return entry[locale] ?? entry['en-US']\n}\n","import { enUS } from './en-US'\nimport { zhCN } from './zh-CN'\n\nexport type SDKLocale = 'en-US' | 'zh-CN'\n\nexport { API_ERROR_MESSAGES, resolveApiErrorMessage } from './api-error-codes'\n\nexport type SDKMessages = Record<string, string>\n\nexport type SDKI18n = {\n locale: SDKLocale\n t: (key: string, params?: Record<string, string | number | boolean | null | undefined>) => string\n}\n\nfunction formatTemplate(\n template: string,\n params?: Record<string, string | number | boolean | null | undefined>,\n): string {\n if (!params) return template\n return template.replace(/\\{(\\w+)\\}/g, (_, rawKey: string) => {\n const value = params[rawKey]\n return value === null || value === undefined ? '' : String(value)\n })\n}\n\nexport function getDefaultMessages(locale: SDKLocale): SDKMessages {\n return locale === 'zh-CN' ? (zhCN as SDKMessages) : (enUS as SDKMessages)\n}\n\nexport function createSDKI18n(input?: {\n locale?: SDKLocale\n messages?: Record<string, string>\n t?: SDKI18n['t']\n}): SDKI18n {\n const locale = input?.locale ?? 'en-US'\n\n if (typeof input?.t === 'function') {\n return { locale, t: input.t }\n }\n\n const base = getDefaultMessages(locale)\n const merged: SDKMessages = { ...base, ...(input?.messages ?? {}) }\n\n return {\n locale,\n t: (key, params) => {\n const template = merged[key] ?? key\n return formatTemplate(template, params)\n },\n }\n}\n","/** Max viewport width treated as mobile H5 (matches app `useIsMobile`). */\nexport const MOBILE_PUBLISH_MAX_WIDTH_PX = 768\n\nexport const RTC_PUBLISH_FPS_WEB = 30\n\nexport const RTC_PUBLISH_FPS_MOBILE = 24\n\nexport type ResolveRtcPublishFpsOptions = {\n /** When set, skips viewport detection. */\n mobile?: boolean\n /** Explicit fps override. */\n fps?: number\n /** Upload/file publish — use detail encoding and higher max bitrate. */\n highQuality?: boolean\n}\n\nexport function isMobilePublishEnvironment(): boolean {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {\n return false\n }\n return window.matchMedia(`(max-width: ${MOBILE_PUBLISH_MAX_WIDTH_PX}px)`).matches\n}\n\nexport function resolveRtcPublishFps(options: ResolveRtcPublishFpsOptions = {}): number {\n if (typeof options.fps === 'number' && Number.isFinite(options.fps) && options.fps > 0) {\n return options.fps\n }\n const mobile = options.mobile ?? isMobilePublishEnvironment()\n return mobile ? RTC_PUBLISH_FPS_MOBILE : RTC_PUBLISH_FPS_WEB\n}\n\nexport function resolveRtcPublishFrameIntervalS(options?: ResolveRtcPublishFpsOptions): number {\n return 1 / resolveRtcPublishFps(options)\n}\n\n/** Web @ 30fps — use {@link resolveRtcPublishFrameIntervalS} when mobile-aware. */\nexport const RTC_PUBLISH_FRAME_INTERVAL_S = 1 / RTC_PUBLISH_FPS_WEB\n\nexport const RTC_PUBLISH_FRAME_INTERVAL_MS = 1000 / RTC_PUBLISH_FPS_WEB\n\n/** Tolerance when comparing media-time deltas (seconds). */\nexport const MEDIA_TIME_EPSILON_S = 0.001\n\n/** Media time jumped backward beyond this threshold — treat as loop/seek reset. */\nexport const MEDIA_TIME_LOOP_JUMP_S = 0.05\n","/** UI preview frames are fixed 16:9 per design; session `size` is separate (see resolveUploadVideoSize). */\nexport const PREVIEW_CONTAINER_ASPECT_RATIO = 16 / 9\n\n/** CSS `aspect-ratio` string for a session target size — keeps UI layout aligned with passed `size`. */\nexport function resolvePreviewAspectRatio(size: [number, number]): string {\n return `${size[0]} / ${size[1]}`\n}\n\n/** Default landscape session size under the 832 rule (16:9). */\nexport const DEFAULT_SESSION_TARGET_SIZE: [number, number] = [1472, 832]\n\nconst UPLOAD_VIDEO_BASE = 832\nconst UPLOAD_SIZE_ALIGN = 32\nconst MAX_LANDSCAPE_ASPECT = 16 / 9\nconst MAX_PORTRAIT_HEIGHT_RATIO = 16 / 9\n\nfunction alignToSizeMultiple(value: number): number {\n return Math.max(UPLOAD_SIZE_ALIGN, Math.round(value / UPLOAD_SIZE_ALIGN) * UPLOAD_SIZE_ALIGN)\n}\n\nfunction makeEven(value: number): number {\n const rounded = Math.max(2, Math.round(value))\n return rounded % 2 === 0 ? rounded : rounded - 1\n}\n\n/**\n * Upload publish size — keep source resolution (even dimensions for H.264).\n * Avoids canvas downscale blur; camera path still uses {@link resolveUploadVideoSize}.\n */\nexport function resolveUploadPublishSize(sourceWidth: number, sourceHeight: number): [number, number] {\n if (sourceWidth <= 0 || sourceHeight <= 0) {\n return DEFAULT_SESSION_TARGET_SIZE\n }\n return [makeEven(sourceWidth), makeEven(sourceHeight)]\n}\n\n/**\n * Adaptive RTC encode/session size — mirrors iOS `rtcVideoSize(for:)`.\n * Keeps the base width and scales height for wide sources; tall sources use the full base size.\n */\nexport function resolveAdaptiveRtcVideoSize(\n sourceWidth: number,\n sourceHeight: number,\n baseSize: [number, number] = DEFAULT_SESSION_TARGET_SIZE,\n): [number, number] {\n if (sourceWidth <= 0 || sourceHeight <= 0) {\n return baseSize\n }\n\n const [baseWidth, baseHeight] = baseSize\n const sourceAspectRatio = sourceHeight / sourceWidth\n const baseAspectRatio = baseHeight / baseWidth\n\n if (sourceAspectRatio >= baseAspectRatio) {\n return [baseWidth, baseHeight]\n }\n\n const adaptiveHeight = Math.max(\n UPLOAD_SIZE_ALIGN,\n Math.round(baseWidth * sourceAspectRatio),\n )\n return [baseWidth, makeEven(adaptiveHeight)]\n}\n\n/**\n * Session video size (camera + upload): scale from base edge 832, cap at 9:16 or 16:9.\n * Portrait keeps width at 832; landscape keeps height at 832; the other edge is 32-aligned.\n */\nexport function resolveUploadVideoSize(sourceWidth: number, sourceHeight: number): [number, number] {\n if (sourceWidth <= 0 || sourceHeight <= 0) {\n return DEFAULT_SESSION_TARGET_SIZE\n }\n\n if (sourceWidth === sourceHeight) {\n return [UPLOAD_VIDEO_BASE, UPLOAD_VIDEO_BASE]\n }\n\n const aspect = sourceWidth / sourceHeight\n\n if (sourceHeight > sourceWidth) {\n const width = UPLOAD_VIDEO_BASE\n let height = alignToSizeMultiple(width / aspect)\n const maxHeight = alignToSizeMultiple(width * MAX_PORTRAIT_HEIGHT_RATIO)\n if (height > maxHeight) {\n height = maxHeight\n }\n return [width, height]\n }\n\n const height = UPLOAD_VIDEO_BASE\n let width = alignToSizeMultiple(height * aspect)\n const maxWidth = alignToSizeMultiple(height * MAX_LANDSCAPE_ASPECT)\n if (width > maxWidth) {\n width = maxWidth\n }\n return [width, height]\n}\n\nexport function resolveSessionTargetSize(input: {\n localVideoSize?: { width: number; height: number } | null\n overrideSize?: [number, number]\n}): [number, number] {\n if (input.overrideSize) {\n return input.overrideSize\n }\n\n if (input.localVideoSize?.width && input.localVideoSize?.height) {\n return [input.localVideoSize.width, input.localVideoSize.height]\n }\n\n return DEFAULT_SESSION_TARGET_SIZE\n}\n","export type CropRect = {\n x: number\n y: number\n width: number\n height: number\n}\n\n/** Center-crop source to target aspect (same rule as upload video pipeline). */\nexport function computeCenterCropRect(\n sourceWidth: number,\n sourceHeight: number,\n targetAspect: number,\n): CropRect {\n const sourceAspect = sourceWidth / sourceHeight\n\n if (sourceAspect > targetAspect) {\n const height = sourceHeight\n const width = sourceHeight * targetAspect\n return {\n x: (sourceWidth - width) / 2,\n y: 0,\n width,\n height,\n }\n }\n\n const width = sourceWidth\n const height = sourceWidth / targetAspect\n return {\n x: 0,\n y: (sourceHeight - height) / 2,\n width,\n height,\n }\n}\n","import { computeCenterCropRect } from './capture-crop'\n\nexport function drawSourceCenterCrop(\n ctx: CanvasRenderingContext2D,\n source: CanvasImageSource,\n outputWidth: number,\n outputHeight: number,\n sourceWidth: number,\n sourceHeight: number,\n): void {\n ctx.imageSmoothingEnabled = true\n ctx.imageSmoothingQuality = 'high'\n ctx.clearRect(0, 0, outputWidth, outputHeight)\n\n const crop = computeCenterCropRect(\n sourceWidth,\n sourceHeight,\n outputWidth / outputHeight,\n )\n\n ctx.drawImage(\n source,\n crop.x,\n crop.y,\n crop.width,\n crop.height,\n 0,\n 0,\n outputWidth,\n outputHeight,\n )\n}\n","/** Off-screen host for decode/canvas pipelines. Keep full size for iOS decode; move off-screen instead of near-zero opacity (Windows may stop decoding at opacity ~0). */\nlet captureHostRoot: HTMLDivElement | null = null\n\nconst CAPTURE_VIDEO_STYLE =\n 'position:fixed;left:-10000px;top:0;width:640px;height:480px;opacity:1;pointer-events:none;z-index:-1;'\n\nexport function mountCaptureVideo(videoEl: HTMLVideoElement): void {\n if (!captureHostRoot) {\n captureHostRoot = document.createElement('div')\n captureHostRoot.setAttribute('data-xmax-capture-host', 'true')\n captureHostRoot.style.cssText =\n 'position:fixed;left:0;top:0;width:0;height:0;overflow:hidden;pointer-events:none;z-index:-1;'\n document.body.appendChild(captureHostRoot)\n }\n\n videoEl.setAttribute('playsinline', 'true')\n videoEl.setAttribute('webkit-playsinline', 'true')\n videoEl.style.cssText = CAPTURE_VIDEO_STYLE\n captureHostRoot.appendChild(videoEl)\n}\n","const COMMON_VIDEO_FPS = [24, 25, 30, 48, 50, 60] as const\n\ntype VideoFrameCallbackMetadata = {\n mediaTime: number\n presentedFrames: number\n}\n\ntype VideoWithFrameCallback = HTMLVideoElement & {\n requestVideoFrameCallback?: (\n cb: (now: DOMHighResTimeStamp, metadata: VideoFrameCallbackMetadata) => void,\n ) => number\n}\n\nfunction median(values: number[]): number {\n if (values.length === 0) {\n return 30\n }\n const sorted = [...values].sort((a, b) => a - b)\n const mid = Math.floor(sorted.length / 2)\n if (sorted.length % 2 === 0) {\n return (sorted[mid - 1] + sorted[mid]) / 2\n }\n return sorted[mid]\n}\n\n/** Snap to broadcast fps; prefer the lower candidate when between 30 and 48 to avoid over-pacing. */\nexport function snapToCommonVideoFps(fps: number): number {\n if (!Number.isFinite(fps) || fps <= 0) {\n return 30\n }\n\n const clamped = Math.max(1, Math.min(120, fps))\n let best = 30\n let bestDiff = Infinity\n for (const candidate of COMMON_VIDEO_FPS) {\n const diff = Math.abs(clamped - candidate)\n if (diff < bestDiff || (diff === bestDiff && candidate < best)) {\n bestDiff = diff\n best = candidate\n }\n }\n return best\n}\n\n/** Prefer a common fps not greater than measured — avoids encoder/capture duplicate frames. */\nexport function snapToCommonVideoFpsConservative(fps: number): number {\n if (!Number.isFinite(fps) || fps <= 0) {\n return 30\n }\n\n const snapped = snapToCommonVideoFps(fps)\n if (snapped <= fps + 0.5) {\n return snapped\n }\n\n const lowerCandidates = COMMON_VIDEO_FPS.filter((candidate) => candidate < snapped)\n if (lowerCandidates.length > 0) {\n return lowerCandidates[lowerCandidates.length - 1]\n }\n return snapped\n}\n\nexport type EstimateVideoFrameRateOptions = {\n timeoutMs?: number\n sampleDurationMs?: number\n fallbackFps?: number\n}\n\n/**\n * Measure actual playback fps via presentedFrames over wall time (more reliable than per-frame deltas).\n */\nexport async function estimateVideoFrameRate(\n videoEl: HTMLVideoElement,\n options: EstimateVideoFrameRateOptions = {},\n): Promise<number> {\n const timeoutMs = options.timeoutMs ?? 3000\n const sampleDurationMs = options.sampleDurationMs ?? 900\n const fallbackFps = options.fallbackFps ?? 30\n\n const video = videoEl as VideoWithFrameCallback\n if (!video.requestVideoFrameCallback) {\n return fallbackFps\n }\n\n return new Promise((resolve) => {\n let settled = false\n let startWallMs = 0\n let startPresented = 0\n const deltas: number[] = []\n let lastMediaTime = -1\n\n const finish = (rawFps: number) => {\n if (settled) {\n return\n }\n settled = true\n clearTimeout(timer)\n resolve(snapToCommonVideoFpsConservative(rawFps))\n }\n\n const timer = setTimeout(() => {\n if (startWallMs > 0) {\n finish(fallbackFps)\n return\n }\n if (deltas.length > 0) {\n finish(median(deltas.map((delta) => 1 / delta)))\n return\n }\n finish(fallbackFps)\n }, timeoutMs)\n\n const schedule = () => {\n if (settled) {\n return\n }\n video.requestVideoFrameCallback!((now, metadata) => {\n if (lastMediaTime >= 0) {\n const delta = metadata.mediaTime - lastMediaTime\n if (delta > 0.001 && delta < 0.5) {\n deltas.push(delta)\n }\n }\n lastMediaTime = metadata.mediaTime\n\n if (startWallMs === 0) {\n startWallMs = now\n startPresented = metadata.presentedFrames\n schedule()\n return\n }\n\n const elapsedMs = now - startWallMs\n if (elapsedMs >= sampleDurationMs) {\n const frameCount = metadata.presentedFrames - startPresented\n if (frameCount > 0) {\n finish(frameCount / (elapsedMs / 1000))\n return\n }\n }\n\n schedule()\n })\n }\n\n schedule()\n })\n}\n\nexport function resolveTrackFrameRate(track: MediaStreamTrack, fallback: number): number {\n const settings = track.getSettings?.()\n if (typeof settings?.frameRate === 'number' && settings.frameRate > 0) {\n return snapToCommonVideoFpsConservative(settings.frameRate)\n }\n return snapToCommonVideoFpsConservative(fallback)\n}\n\n/** Encoder ceiling for playback-driven upload — never pace faster than the capture track. */\nexport function resolvePlaybackDrivenEncoderFps(\n track: MediaStreamTrack,\n fallback = 24,\n): number {\n return resolveTrackFrameRate(track, fallback)\n}\n","import { createSDKI18n, type SDKI18n } from '../i18n'\nimport { MEDIA_TIME_EPSILON_S, MEDIA_TIME_LOOP_JUMP_S } from './publish-fps'\nimport { resolveUploadVideoSize } from '../shared/reference-video-size'\nimport type { VideoInputHealth } from '../shared/session-debug'\nimport { drawSourceCenterCrop } from './canvas-frame-draw'\nimport { mountCaptureVideo } from './capture-host'\nimport { estimateVideoFrameRate, resolvePlaybackDrivenEncoderFps } from './video-frame-rate'\n\nconst STALL_CATCHUP_MS = 1500\n\ntype VideoFrameCallbackMetadata = {\n mediaTime: number\n presentedFrames: number\n}\n\ntype VideoWithCaptureStream = HTMLVideoElement & {\n captureStream?: (frameRate?: number) => MediaStream\n mozCaptureStream?: (frameRate?: number) => MediaStream\n}\n\ntype VideoWithFrameCallback = HTMLVideoElement & {\n requestVideoFrameCallback?: (\n cb: (now: DOMHighResTimeStamp, metadata: VideoFrameCallbackMetadata) => void,\n ) => number\n cancelVideoFrameCallback?: (handle: number) => void\n}\n\nexport type VideoFileStreamOptions = {\n loop?: boolean\n muted?: boolean\n playbackRate?: number\n /** Optional fps override; when omitted, fps is measured from the source file. */\n fps?: number\n /** Optional hint; publish fps is still derived from the uploaded file when applicable. */\n mobile?: boolean\n targetSize?: [number, number]\n i18n?: SDKI18n\n onHealthReport?: (health: VideoInputHealth) => void\n healthIntervalMs?: number\n}\n\nexport type VideoFileStream = {\n url: string\n /** Same MediaStream pushed to RTC; bind to preview via srcObject for WYSIWYG. */\n previewStream: MediaStream\n /** Capture-only element; pinned off-screen. */\n videoEl: HTMLVideoElement\n videoTrack: MediaStreamTrack\n /** Measured source fps — encoder ceiling hint only. */\n fps: number\n /** Session publish dimensions (native source size by default). */\n width: number\n height: number\n /** Original media dimensions before scale. */\n sourceWidth: number\n sourceHeight: number\n destroy: () => void\n}\n\nfunction shouldSampleAtMediaTime(lastMediaTimeS: number, mediaTimeS: number): boolean {\n if (!Number.isFinite(mediaTimeS) || mediaTimeS < 0) {\n return false\n }\n if (lastMediaTimeS < 0) {\n return true\n }\n if (mediaTimeS + MEDIA_TIME_LOOP_JUMP_S < lastMediaTimeS) {\n return true\n }\n return mediaTimeS > lastMediaTimeS + MEDIA_TIME_EPSILON_S\n}\n\nasync function applyPublishTrackConstraints(\n track: MediaStreamTrack,\n width: number,\n height: number,\n): Promise<void> {\n if (typeof track.applyConstraints !== 'function') {\n return\n }\n\n try {\n await track.applyConstraints({\n width: { ideal: width, max: width },\n height: { ideal: height, max: height },\n })\n } catch {\n // Some browsers reject exact constraints on captureStream tracks.\n }\n}\n\nexport async function createVideoFileStream(\n fileOrUrl: File | string,\n options: VideoFileStreamOptions = {},\n): Promise<VideoFileStream> {\n const i18n = options.i18n ?? createSDKI18n()\n const isUrl = typeof fileOrUrl === 'string'\n const url = isUrl ? fileOrUrl : URL.createObjectURL(fileOrUrl)\n const videoEl = document.createElement('video')\n\n videoEl.muted = options.muted ?? true\n videoEl.playsInline = true\n\n if (isUrl) {\n videoEl.crossOrigin = 'anonymous'\n }\n videoEl.src = url\n videoEl.loop = options.loop ?? true\n videoEl.autoplay = true\n\n mountCaptureVideo(videoEl)\n\n try {\n videoEl.load()\n await waitForEvent(videoEl, 'loadedmetadata')\n await waitForCanPlay(videoEl)\n } catch (error) {\n if (!isUrl) URL.revokeObjectURL(url)\n throw error\n }\n\n if (typeof options.playbackRate === 'number') {\n videoEl.playbackRate = options.playbackRate\n }\n\n await startVideoPlayback(videoEl, i18n)\n\n const sourceWidth = videoEl.videoWidth || 0\n const sourceHeight = videoEl.videoHeight || 0\n if (!sourceWidth || !sourceHeight) {\n if (!isUrl) URL.revokeObjectURL(url)\n throw new Error(i18n.t('errors.videoTrackMissing'))\n }\n\n const measuredFps = typeof options.fps === 'number' && options.fps > 0\n ? options.fps\n : await estimateVideoFrameRate(videoEl)\n\n const [outputWidth, outputHeight] = options.targetSize\n ?? resolveUploadVideoSize(sourceWidth, sourceHeight)\n\n const canvas = document.createElement('canvas')\n canvas.width = outputWidth\n canvas.height = outputHeight\n const ctx = canvas.getContext('2d')\n if (!ctx) {\n if (!isUrl) URL.revokeObjectURL(url)\n throw new Error(i18n.t('errors.captureStreamUnsupported'))\n }\n\n const captureStreamFn =\n (canvas as HTMLCanvasElement & { captureStream?: (frameRate?: number) => MediaStream }).captureStream\n ?? (canvas as HTMLCanvasElement & { mozCaptureStream?: (frameRate?: number) => MediaStream }).mozCaptureStream\n\n if (!captureStreamFn) {\n if (!isUrl) URL.revokeObjectURL(url)\n throw new Error(i18n.t('errors.captureStreamUnsupported'))\n }\n\n // One canvas redraw per advanced mediaTime — captureStream emits only when canvas changes.\n const previewStream = captureStreamFn.call(canvas)\n const videoTrack = previewStream.getVideoTracks()[0]\n\n if (!videoTrack) {\n if (!isUrl) URL.revokeObjectURL(url)\n throw new Error(i18n.t('errors.videoTrackMissing'))\n }\n\n const publishFps = resolvePlaybackDrivenEncoderFps(videoTrack, measuredFps)\n await applyPublishTrackConstraints(videoTrack, outputWidth, outputHeight)\n\n let destroyed = false\n let lastAdvanceAt = Date.now()\n let lastDrawMediaTimeS = -1\n let videoFrameCallbackId: number | null = null\n let rafId: number | null = null\n\n const drawFrame = () => {\n if (destroyed) {\n return\n }\n drawSourceCenterCrop(\n ctx,\n videoEl,\n outputWidth,\n outputHeight,\n sourceWidth,\n sourceHeight,\n )\n }\n\n const onPlaybackSample = (mediaTimeS: number) => {\n if (destroyed || !shouldSampleAtMediaTime(lastDrawMediaTimeS, mediaTimeS)) {\n return\n }\n lastDrawMediaTimeS = mediaTimeS\n lastAdvanceAt = Date.now()\n drawFrame()\n }\n\n const schedulePlaybackWatch = () => {\n if (destroyed) {\n return\n }\n\n const video = videoEl as VideoWithFrameCallback\n if (video.requestVideoFrameCallback) {\n videoFrameCallbackId = video.requestVideoFrameCallback!((_now, metadata) => {\n onPlaybackSample(metadata.mediaTime)\n schedulePlaybackWatch()\n })\n return\n }\n\n rafId = window.requestAnimationFrame(() => {\n onPlaybackSample(videoEl.currentTime)\n schedulePlaybackWatch()\n })\n }\n\n drawFrame()\n schedulePlaybackWatch()\n\n const ensurePlaying = () => {\n if (destroyed) {\n return\n }\n if (videoEl.ended && videoEl.loop) {\n videoEl.currentTime = 0\n lastDrawMediaTimeS = -1\n }\n if (videoEl.paused) {\n void videoEl.play().catch(() => undefined)\n }\n }\n\n const markAdvance = () => {\n lastAdvanceAt = Date.now()\n }\n\n videoEl.addEventListener('timeupdate', markAdvance)\n videoEl.addEventListener('pause', ensurePlaying)\n videoEl.addEventListener('ended', ensurePlaying)\n videoEl.addEventListener('stalled', ensurePlaying)\n videoEl.addEventListener('waiting', ensurePlaying)\n\n const healthIntervalMs = options.healthIntervalMs ?? 3000\n let healthTimer: ReturnType<typeof setInterval> | null = null\n\n if (options.onHealthReport) {\n const reportHealth = options.onHealthReport\n healthTimer = setInterval(() => {\n ensurePlaying()\n\n const now = Date.now()\n const currentTime = videoEl.currentTime\n const duration = videoEl.duration\n const nearEnd = duration > 0 && currentTime >= duration - 0.2\n const stalled = !videoEl.paused && !videoEl.ended && !nearEnd && now - lastAdvanceAt >= healthIntervalMs\n\n if (stalled && now - lastAdvanceAt >= STALL_CATCHUP_MS) {\n void videoEl.play().catch(() => undefined)\n }\n\n reportHealth({\n currentTime,\n duration,\n paused: videoEl.paused,\n ended: videoEl.ended,\n readyState: videoEl.readyState,\n trackReadyState: videoTrack.readyState,\n trackMuted: videoTrack.muted,\n stalled,\n timeSinceAdvanceMs: now - lastAdvanceAt,\n })\n }, healthIntervalMs)\n }\n\n const destroy = () => {\n destroyed = true\n videoEl.removeEventListener('timeupdate', markAdvance)\n videoEl.removeEventListener('pause', ensurePlaying)\n videoEl.removeEventListener('ended', ensurePlaying)\n videoEl.removeEventListener('stalled', ensurePlaying)\n videoEl.removeEventListener('waiting', ensurePlaying)\n\n const video = videoEl as VideoWithFrameCallback\n if (videoFrameCallbackId !== null) {\n video.cancelVideoFrameCallback?.(videoFrameCallbackId)\n videoFrameCallbackId = null\n }\n if (rafId !== null) {\n window.cancelAnimationFrame(rafId)\n rafId = null\n }\n\n if (healthTimer !== null) {\n clearInterval(healthTimer)\n healthTimer = null\n }\n\n try {\n videoEl.pause()\n } catch {\n }\n\n try {\n videoTrack.stop()\n } catch {\n }\n\n try {\n previewStream.getTracks().forEach((track) => {\n if (track.readyState !== 'ended') {\n track.stop()\n }\n })\n } catch {\n }\n\n try {\n videoEl.remove()\n } catch {\n }\n\n try {\n videoEl.src = ''\n videoEl.load()\n } catch {\n }\n\n if (!isUrl) URL.revokeObjectURL(url)\n }\n\n return {\n url,\n previewStream,\n videoEl,\n videoTrack,\n fps: publishFps,\n width: outputWidth,\n height: outputHeight,\n sourceWidth,\n sourceHeight,\n destroy,\n }\n}\n\nfunction waitForEvent<T extends HTMLElement>(\n el: T,\n eventName: keyof HTMLElementEventMap,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const onOk = () => {\n cleanup()\n resolve()\n }\n\n const onErr = (e: Event) => {\n cleanup()\n // If it's a media error and we can read the code, include it\n const mediaEl = el as unknown as HTMLMediaElement\n const code = mediaEl.error ? mediaEl.error.code : 'unknown'\n const message = mediaEl.error ? mediaEl.error.message : 'no message'\n const src = mediaEl.src || 'unknown src'\n reject(new Error(`failed to load video metadata: ${String(eventName)} (code: ${code}, message: ${message}, src: ${src})`))\n }\n\n const cleanup = () => {\n el.removeEventListener(eventName, onOk as EventListener)\n el.removeEventListener('error', onErr as EventListener)\n }\n\n el.addEventListener(eventName, onOk as EventListener, { once: true })\n el.addEventListener('error', onErr as EventListener, { once: true })\n })\n}\n\nfunction waitForCanPlay(videoEl: HTMLVideoElement): Promise<void> {\n if (videoEl.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {\n return Promise.resolve()\n }\n\n return new Promise((resolve) => {\n const onReady = () => {\n cleanup()\n resolve()\n }\n\n const cleanup = () => {\n videoEl.removeEventListener('canplay', onReady)\n videoEl.removeEventListener('loadeddata', onReady)\n }\n\n videoEl.addEventListener('canplay', onReady, { once: true })\n videoEl.addEventListener('loadeddata', onReady, { once: true })\n })\n}\n\nasync function startVideoPlayback(videoEl: HTMLVideoElement, i18n: SDKI18n): Promise<void> {\n try {\n const playResult = videoEl.play()\n if (playResult && typeof (playResult as Promise<void>).then === 'function') {\n await playResult\n }\n } catch {\n throw new Error(i18n.t('errors.videoPlaybackFailed'))\n }\n\n try {\n await waitForPlaying(videoEl)\n } catch {\n throw new Error(i18n.t('errors.videoPlaybackFailed'))\n }\n\n if (videoEl.paused || videoEl.readyState < HTMLMediaElement.HAVE_CURRENT_DATA) {\n throw new Error(i18n.t('errors.videoPlaybackFailed'))\n }\n}\n\nfunction waitForPlaying(videoEl: HTMLVideoElement): Promise<void> {\n if (!videoEl.paused && videoEl.readyState >= HTMLMediaElement.HAVE_CURRENT_DATA) {\n return Promise.resolve()\n }\n\n return new Promise((resolve, reject) => {\n const onPlaying = () => {\n cleanup()\n resolve()\n }\n\n const onErr = () => {\n cleanup()\n reject(new Error('video playback failed'))\n }\n\n const cleanup = () => {\n videoEl.removeEventListener('playing', onPlaying)\n videoEl.removeEventListener('error', onErr)\n }\n\n videoEl.addEventListener('playing', onPlaying, { once: true })\n videoEl.addEventListener('error', onErr, { once: true })\n })\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -441,13 +441,12 @@ function resolveRtcPublishFps(options = {}) {
|
|
|
441
441
|
function resolveRtcPublishFrameIntervalS(options) {
|
|
442
442
|
return 1 / resolveRtcPublishFps(options);
|
|
443
443
|
}
|
|
444
|
-
exports.MOBILE_PUBLISH_MAX_WIDTH_PX = void 0; exports.RTC_PUBLISH_FPS_WEB = void 0; exports.RTC_PUBLISH_FPS_MOBILE = void 0; exports.
|
|
444
|
+
exports.MOBILE_PUBLISH_MAX_WIDTH_PX = void 0; exports.RTC_PUBLISH_FPS_WEB = void 0; exports.RTC_PUBLISH_FPS_MOBILE = void 0; exports.RTC_PUBLISH_FRAME_INTERVAL_S = void 0; exports.RTC_PUBLISH_FRAME_INTERVAL_MS = void 0; exports.MEDIA_TIME_EPSILON_S = void 0; exports.MEDIA_TIME_LOOP_JUMP_S = void 0;
|
|
445
445
|
var init_publish_fps = __esm({
|
|
446
446
|
"src/rtc/publish-fps.ts"() {
|
|
447
447
|
exports.MOBILE_PUBLISH_MAX_WIDTH_PX = 768;
|
|
448
448
|
exports.RTC_PUBLISH_FPS_WEB = 30;
|
|
449
449
|
exports.RTC_PUBLISH_FPS_MOBILE = 24;
|
|
450
|
-
exports.RTC_PUBLISH_FPS = exports.RTC_PUBLISH_FPS_WEB;
|
|
451
450
|
exports.RTC_PUBLISH_FRAME_INTERVAL_S = 1 / exports.RTC_PUBLISH_FPS_WEB;
|
|
452
451
|
exports.RTC_PUBLISH_FRAME_INTERVAL_MS = 1e3 / exports.RTC_PUBLISH_FPS_WEB;
|
|
453
452
|
exports.MEDIA_TIME_EPSILON_S = 1e-3;
|
|
@@ -627,17 +626,6 @@ function shouldSampleAtMediaTime(lastMediaTimeS, mediaTimeS) {
|
|
|
627
626
|
}
|
|
628
627
|
return mediaTimeS > lastMediaTimeS + exports.MEDIA_TIME_EPSILON_S;
|
|
629
628
|
}
|
|
630
|
-
function sampleCanvasFingerprint(ctx, width, height) {
|
|
631
|
-
const points = [
|
|
632
|
-
[0, 0],
|
|
633
|
-
[Math.max(0, (width >> 1) - 1), Math.max(0, (height >> 1) - 1)],
|
|
634
|
-
[Math.max(0, width - 1), Math.max(0, height - 1)]
|
|
635
|
-
];
|
|
636
|
-
return points.map(([x, y]) => {
|
|
637
|
-
const data = ctx.getImageData(x, y, 1, 1).data;
|
|
638
|
-
return `${data[0]},${data[1]},${data[2]}`;
|
|
639
|
-
}).join("|");
|
|
640
|
-
}
|
|
641
629
|
async function applyPublishTrackConstraints(track, width, height) {
|
|
642
630
|
if (typeof track.applyConstraints !== "function") {
|
|
643
631
|
return;
|
|
@@ -710,12 +698,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
710
698
|
let lastDrawMediaTimeS = -1;
|
|
711
699
|
let videoFrameCallbackId = null;
|
|
712
700
|
let rafId = null;
|
|
713
|
-
const logPublishFrames = options.logPublishFrames ?? false;
|
|
714
|
-
let publishFrameIndex = 0;
|
|
715
|
-
let lastPublishWallMs = 0;
|
|
716
|
-
let lastPublishMediaTimeS = -1;
|
|
717
|
-
let publishFramesInWindow = 0;
|
|
718
|
-
let publishWindowStartMs = 0;
|
|
719
701
|
const drawFrame = () => {
|
|
720
702
|
if (destroyed) {
|
|
721
703
|
return;
|
|
@@ -729,52 +711,13 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
729
711
|
sourceHeight
|
|
730
712
|
);
|
|
731
713
|
};
|
|
732
|
-
const
|
|
733
|
-
if (!logPublishFrames) {
|
|
734
|
-
return;
|
|
735
|
-
}
|
|
736
|
-
publishFrameIndex += 1;
|
|
737
|
-
const wallNowMs = performance.now();
|
|
738
|
-
const wallDeltaMs = lastPublishWallMs > 0 ? wallNowMs - lastPublishWallMs : 0;
|
|
739
|
-
const mediaDeltaS = lastPublishMediaTimeS >= 0 ? mediaTimeS - lastPublishMediaTimeS : 0;
|
|
740
|
-
lastPublishWallMs = wallNowMs;
|
|
741
|
-
lastPublishMediaTimeS = mediaTimeS;
|
|
742
|
-
publishFramesInWindow += 1;
|
|
743
|
-
if (publishWindowStartMs === 0) {
|
|
744
|
-
publishWindowStartMs = wallNowMs;
|
|
745
|
-
}
|
|
746
|
-
const fingerprint = sampleCanvasFingerprint(ctx, outputWidth, outputHeight);
|
|
747
|
-
console.warn("[upload-video \u2192 publishFrame]", {
|
|
748
|
-
frameIndex: publishFrameIndex,
|
|
749
|
-
mediaTimeS: Number(mediaTimeS.toFixed(4)),
|
|
750
|
-
mediaDeltaS: Number(mediaDeltaS.toFixed(4)),
|
|
751
|
-
wallDeltaMs: Number(wallDeltaMs.toFixed(1)),
|
|
752
|
-
effectiveFps: wallDeltaMs > 0 ? Number((1e3 / wallDeltaMs).toFixed(1)) : null,
|
|
753
|
-
presentedFrames,
|
|
754
|
-
size: `${outputWidth}\xD7${outputHeight}`,
|
|
755
|
-
fingerprint
|
|
756
|
-
});
|
|
757
|
-
const windowElapsedMs = wallNowMs - publishWindowStartMs;
|
|
758
|
-
if (windowElapsedMs >= 1e3) {
|
|
759
|
-
console.warn("[upload-video \u2192 publishFps]", {
|
|
760
|
-
framesInLast1s: publishFramesInWindow,
|
|
761
|
-
avgFps: Number((publishFramesInWindow / (windowElapsedMs / 1e3)).toFixed(2)),
|
|
762
|
-
videoCurrentTime: Number(videoEl.currentTime.toFixed(4)),
|
|
763
|
-
videoPaused: videoEl.paused,
|
|
764
|
-
videoReadyState: videoEl.readyState
|
|
765
|
-
});
|
|
766
|
-
publishFramesInWindow = 0;
|
|
767
|
-
publishWindowStartMs = wallNowMs;
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
const onPlaybackSample = (mediaTimeS, presentedFrames) => {
|
|
714
|
+
const onPlaybackSample = (mediaTimeS) => {
|
|
771
715
|
if (destroyed || !shouldSampleAtMediaTime(lastDrawMediaTimeS, mediaTimeS)) {
|
|
772
716
|
return;
|
|
773
717
|
}
|
|
774
718
|
lastDrawMediaTimeS = mediaTimeS;
|
|
775
719
|
lastAdvanceAt = Date.now();
|
|
776
720
|
drawFrame();
|
|
777
|
-
logPublishedFrame(mediaTimeS, presentedFrames);
|
|
778
721
|
};
|
|
779
722
|
const schedulePlaybackWatch = () => {
|
|
780
723
|
if (destroyed) {
|
|
@@ -783,7 +726,7 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
783
726
|
const video = videoEl;
|
|
784
727
|
if (video.requestVideoFrameCallback) {
|
|
785
728
|
videoFrameCallbackId = video.requestVideoFrameCallback((_now, metadata) => {
|
|
786
|
-
onPlaybackSample(metadata.mediaTime
|
|
729
|
+
onPlaybackSample(metadata.mediaTime);
|
|
787
730
|
schedulePlaybackWatch();
|
|
788
731
|
});
|
|
789
732
|
return;
|
|
@@ -794,7 +737,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
794
737
|
});
|
|
795
738
|
};
|
|
796
739
|
drawFrame();
|
|
797
|
-
logPublishedFrame(videoEl.currentTime);
|
|
798
740
|
schedulePlaybackWatch();
|
|
799
741
|
const ensurePlaying = () => {
|
|
800
742
|
if (destroyed) {
|
|
@@ -816,18 +758,6 @@ async function createVideoFileStream(fileOrUrl, options = {}) {
|
|
|
816
758
|
videoEl.addEventListener("ended", ensurePlaying);
|
|
817
759
|
videoEl.addEventListener("stalled", ensurePlaying);
|
|
818
760
|
videoEl.addEventListener("waiting", ensurePlaying);
|
|
819
|
-
if (logPublishFrames) {
|
|
820
|
-
const logPlaybackEvent = (eventName) => {
|
|
821
|
-
console.warn("[upload-video \u2192 playbackEvent]", {
|
|
822
|
-
event: eventName,
|
|
823
|
-
currentTime: Number(videoEl.currentTime.toFixed(4)),
|
|
824
|
-
readyState: videoEl.readyState,
|
|
825
|
-
paused: videoEl.paused
|
|
826
|
-
});
|
|
827
|
-
};
|
|
828
|
-
videoEl.addEventListener("waiting", () => logPlaybackEvent("waiting"));
|
|
829
|
-
videoEl.addEventListener("stalled", () => logPlaybackEvent("stalled"));
|
|
830
|
-
}
|
|
831
761
|
const healthIntervalMs = options.healthIntervalMs ?? 3e3;
|
|
832
762
|
let healthTimer = null;
|
|
833
763
|
if (options.onHealthReport) {
|
|
@@ -1009,148 +939,13 @@ var init_video_file_stream = __esm({
|
|
|
1009
939
|
// src/sdk/client.ts
|
|
1010
940
|
init_i18n();
|
|
1011
941
|
|
|
1012
|
-
// src/shared/browser-toast.ts
|
|
1013
|
-
var TOAST_ROOT_ID = "Xmax-sdk-toast-root";
|
|
1014
|
-
var TOAST_DURATION_MS = 3e3;
|
|
1015
|
-
var toastSeed = 0;
|
|
1016
|
-
var timeoutMap = /* @__PURE__ */ new Map();
|
|
1017
|
-
var elementMap = /* @__PURE__ */ new Map();
|
|
1018
|
-
function ensureToastRoot() {
|
|
1019
|
-
if (typeof document === "undefined") {
|
|
1020
|
-
return null;
|
|
1021
|
-
}
|
|
1022
|
-
let root = document.getElementById(TOAST_ROOT_ID);
|
|
1023
|
-
if (root) {
|
|
1024
|
-
return root;
|
|
1025
|
-
}
|
|
1026
|
-
root = document.createElement("div");
|
|
1027
|
-
root.id = TOAST_ROOT_ID;
|
|
1028
|
-
root.setAttribute("aria-live", "polite");
|
|
1029
|
-
Object.assign(root.style, {
|
|
1030
|
-
position: "fixed",
|
|
1031
|
-
left: "50%",
|
|
1032
|
-
top: "24px",
|
|
1033
|
-
transform: "translateX(-50%)",
|
|
1034
|
-
zIndex: "3000",
|
|
1035
|
-
display: "flex",
|
|
1036
|
-
flexDirection: "column",
|
|
1037
|
-
alignItems: "center",
|
|
1038
|
-
gap: "12px",
|
|
1039
|
-
pointerEvents: "none"
|
|
1040
|
-
});
|
|
1041
|
-
document.body.appendChild(root);
|
|
1042
|
-
return root;
|
|
1043
|
-
}
|
|
1044
|
-
function createIcon(type) {
|
|
1045
|
-
const icon = document.createElement("span");
|
|
1046
|
-
icon.setAttribute("aria-hidden", "true");
|
|
1047
|
-
icon.innerHTML = type === "success" ? '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M10 3L4.5 8.5 2 6" stroke="#4ade80" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>' : '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none"><circle cx="6" cy="6" r="5" stroke="#f87171" stroke-width="1.5"/><path d="M4 4l4 4M8 4L4 8" stroke="#f87171" stroke-width="1.5" stroke-linecap="round"/></svg>';
|
|
1048
|
-
Object.assign(icon.style, {
|
|
1049
|
-
display: "inline-flex",
|
|
1050
|
-
width: "12px",
|
|
1051
|
-
height: "12px",
|
|
1052
|
-
flexShrink: "0"
|
|
1053
|
-
});
|
|
1054
|
-
return icon;
|
|
1055
|
-
}
|
|
1056
|
-
function clearToastTimer(id) {
|
|
1057
|
-
const timer = timeoutMap.get(id);
|
|
1058
|
-
if (timer) {
|
|
1059
|
-
window.clearTimeout(timer);
|
|
1060
|
-
timeoutMap.delete(id);
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
function destroyToast(id) {
|
|
1064
|
-
if (!id) {
|
|
1065
|
-
timeoutMap.forEach((timer) => window.clearTimeout(timer));
|
|
1066
|
-
timeoutMap.clear();
|
|
1067
|
-
elementMap.forEach((element2) => element2.remove());
|
|
1068
|
-
elementMap.clear();
|
|
1069
|
-
const root2 = typeof document !== "undefined" ? document.getElementById(TOAST_ROOT_ID) : null;
|
|
1070
|
-
root2?.remove();
|
|
1071
|
-
return;
|
|
1072
|
-
}
|
|
1073
|
-
clearToastTimer(id);
|
|
1074
|
-
const element = elementMap.get(id);
|
|
1075
|
-
element?.remove();
|
|
1076
|
-
elementMap.delete(id);
|
|
1077
|
-
const root = typeof document !== "undefined" ? document.getElementById(TOAST_ROOT_ID) : null;
|
|
1078
|
-
if (root && !root.childElementCount) {
|
|
1079
|
-
root.remove();
|
|
1080
|
-
}
|
|
1081
|
-
}
|
|
1082
|
-
function showToast(type, message, options) {
|
|
1083
|
-
const root = ensureToastRoot();
|
|
1084
|
-
if (!root) {
|
|
1085
|
-
return "";
|
|
1086
|
-
}
|
|
1087
|
-
const id = options?.key || `toast-${Date.now()}-${++toastSeed}`;
|
|
1088
|
-
clearToastTimer(id);
|
|
1089
|
-
elementMap.get(id)?.remove();
|
|
1090
|
-
const isMobile = typeof window !== "undefined" && window.matchMedia("(max-width: 768px)").matches;
|
|
1091
|
-
const textSize = isMobile ? "12px" : "14px";
|
|
1092
|
-
const toast = document.createElement("div");
|
|
1093
|
-
toast.setAttribute("role", "status");
|
|
1094
|
-
Object.assign(toast.style, {
|
|
1095
|
-
pointerEvents: "auto",
|
|
1096
|
-
display: "flex",
|
|
1097
|
-
alignItems: "center",
|
|
1098
|
-
gap: "12px",
|
|
1099
|
-
minWidth: "240px",
|
|
1100
|
-
padding: "16px",
|
|
1101
|
-
borderRadius: "12px",
|
|
1102
|
-
border: "1px solid rgba(255, 255, 255, 0.20)",
|
|
1103
|
-
background: "rgba(0, 0, 0, 0.80)",
|
|
1104
|
-
boxShadow: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
|
|
1105
|
-
fontFamily: "Rubik, ui-sans-serif, system-ui, sans-serif",
|
|
1106
|
-
fontSize: textSize,
|
|
1107
|
-
fontWeight: "400",
|
|
1108
|
-
lineHeight: "14px"
|
|
1109
|
-
});
|
|
1110
|
-
const content = document.createElement("span");
|
|
1111
|
-
content.textContent = message;
|
|
1112
|
-
Object.assign(content.style, {
|
|
1113
|
-
paddingRight: "0px",
|
|
1114
|
-
textAlign: "center",
|
|
1115
|
-
color: "#ffffff",
|
|
1116
|
-
fontFamily: "Rubik, ui-sans-serif, system-ui, sans-serif",
|
|
1117
|
-
fontSize: textSize,
|
|
1118
|
-
fontWeight: "400",
|
|
1119
|
-
lineHeight: "14px"
|
|
1120
|
-
});
|
|
1121
|
-
toast.appendChild(createIcon(type));
|
|
1122
|
-
toast.appendChild(content);
|
|
1123
|
-
root.appendChild(toast);
|
|
1124
|
-
elementMap.set(id, toast);
|
|
1125
|
-
const timer = window.setTimeout(() => {
|
|
1126
|
-
destroyToast(id);
|
|
1127
|
-
}, options?.duration ?? TOAST_DURATION_MS);
|
|
1128
|
-
timeoutMap.set(id, timer);
|
|
1129
|
-
return id;
|
|
1130
|
-
}
|
|
1131
|
-
var browserToast = {
|
|
1132
|
-
success(message, options) {
|
|
1133
|
-
return showToast("success", message, options);
|
|
1134
|
-
},
|
|
1135
|
-
error(message, options) {
|
|
1136
|
-
return showToast("error", message, options);
|
|
1137
|
-
},
|
|
1138
|
-
destroy(id) {
|
|
1139
|
-
destroyToast(id);
|
|
1140
|
-
}
|
|
1141
|
-
};
|
|
1142
|
-
|
|
1143
942
|
// src/shared/error-utils.ts
|
|
1144
943
|
function notifyError(error, notifier, fallbackMessage) {
|
|
1145
944
|
const resolved = error instanceof Error ? error : Object.assign(new Error(fallbackMessage), { cause: error });
|
|
1146
|
-
if (!resolved.__XmaxNotified) {
|
|
945
|
+
if (!resolved.__XmaxNotified && notifier) {
|
|
1147
946
|
resolved.__XmaxNotified = true;
|
|
1148
947
|
const message = resolved.message || fallbackMessage;
|
|
1149
|
-
|
|
1150
|
-
notifier(message, error);
|
|
1151
|
-
} else if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
1152
|
-
browserToast.error(message);
|
|
1153
|
-
}
|
|
948
|
+
notifier(message, error);
|
|
1154
949
|
}
|
|
1155
950
|
return resolved;
|
|
1156
951
|
}
|
|
@@ -1222,7 +1017,7 @@ var XmaxOpenClient = class {
|
|
|
1222
1017
|
}
|
|
1223
1018
|
throw notifyError(error, this.onError, message);
|
|
1224
1019
|
}
|
|
1225
|
-
/** Stop heartbeat, abort in-flight API requests, and suppress error
|
|
1020
|
+
/** Stop heartbeat, abort in-flight API requests, and suppress error notifications during teardown. */
|
|
1226
1021
|
beginTeardown() {
|
|
1227
1022
|
this.suppressErrorNotification = true;
|
|
1228
1023
|
this.stopHeartbeat();
|
|
@@ -2079,45 +1874,6 @@ var _RtcManager = class _RtcManager {
|
|
|
2079
1874
|
sentFrameRate: this.lastObservedSentFrameRate
|
|
2080
1875
|
});
|
|
2081
1876
|
}
|
|
2082
|
-
/** @deprecated Use {@link ensurePublishedInputBeforeStart}. */
|
|
2083
|
-
async waitForRtcOutboundBeforeStart(options) {
|
|
2084
|
-
const timeoutMs = options?.timeoutMs ?? PUBLISH_READY_TIMEOUT_MS;
|
|
2085
|
-
const publishAgeMs = this.publishStartedAtMs > 0 ? performance.now() - this.publishStartedAtMs : 0;
|
|
2086
|
-
const localFramesPromise = publishAgeMs >= PUBLISH_WARM_SKIP_MS ? Promise.resolve({ ready: true, frameCount: 0, elapsedMs: 0 }) : this.waitForPublishedInputFrames({
|
|
2087
|
-
minFrames: PUBLISH_START_MIN_FRAMES,
|
|
2088
|
-
timeoutMs: PUBLISH_START_FRAME_TIMEOUT_MS
|
|
2089
|
-
});
|
|
2090
|
-
const [, rtcReady] = await Promise.all([
|
|
2091
|
-
localFramesPromise,
|
|
2092
|
-
this.waitForLocalPublishReady({ timeoutMs })
|
|
2093
|
-
]);
|
|
2094
|
-
return rtcReady;
|
|
2095
|
-
}
|
|
2096
|
-
/** @deprecated Use {@link waitForRtcOutboundBeforeStart}. */
|
|
2097
|
-
async waitForPublishedInputFramesBeforeStart() {
|
|
2098
|
-
const waitOptions = this.resolveInputFrameWaitOptions();
|
|
2099
|
-
const waitTasks = [
|
|
2100
|
-
this.waitForLocalPublishReady({ timeoutMs: PUBLISH_READY_TIMEOUT_MS })
|
|
2101
|
-
];
|
|
2102
|
-
if (waitOptions) {
|
|
2103
|
-
waitTasks.push(
|
|
2104
|
-
this.waitForMinPublishDuration(waitOptions.minPublishMs),
|
|
2105
|
-
this.waitForPublishedInputFrames({
|
|
2106
|
-
minFrames: waitOptions.minFrames,
|
|
2107
|
-
timeoutMs: waitOptions.timeoutMs
|
|
2108
|
-
})
|
|
2109
|
-
);
|
|
2110
|
-
}
|
|
2111
|
-
const [rtcResult, ...rest] = await Promise.all(waitTasks);
|
|
2112
|
-
const rtcSend = rtcResult;
|
|
2113
|
-
const frameResult = waitOptions ? rest[1] : { ready: true, frameCount: 0, elapsedMs: 0 };
|
|
2114
|
-
return {
|
|
2115
|
-
...frameResult,
|
|
2116
|
-
rtcSendReady: rtcSend.ready,
|
|
2117
|
-
rtcSendReason: rtcSend.reason,
|
|
2118
|
-
rtcSendElapsedMs: rtcSend.elapsedSincePublishMs
|
|
2119
|
-
};
|
|
2120
|
-
}
|
|
2121
1877
|
async waitForMinPublishDuration(minMs) {
|
|
2122
1878
|
if (minMs <= 0 || this.publishStartedAtMs <= 0) {
|
|
2123
1879
|
return;
|
|
@@ -3612,9 +3368,6 @@ function getFitContentRect(rect, targetSize, fitMode = "contain") {
|
|
|
3612
3368
|
height
|
|
3613
3369
|
};
|
|
3614
3370
|
}
|
|
3615
|
-
function getContentRect(rect, targetSize) {
|
|
3616
|
-
return getFitContentRect(rect, targetSize, "contain");
|
|
3617
|
-
}
|
|
3618
3371
|
function findDragMediaElement(dragSurface) {
|
|
3619
3372
|
const root = dragSurface.parentElement ?? dragSurface;
|
|
3620
3373
|
if (typeof root.querySelector !== "function") {
|
|
@@ -4219,6 +3972,10 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4219
3972
|
this.currentPrompt = "";
|
|
4220
3973
|
this.currentGenerationModel = "";
|
|
4221
3974
|
this.disconnected = false;
|
|
3975
|
+
/** True only after `connect()` bootstrap succeeds — gates `onDisconnect`. */
|
|
3976
|
+
this.sessionEstablished = false;
|
|
3977
|
+
this.disconnectNotified = false;
|
|
3978
|
+
this.pendingDisconnectReason = "client";
|
|
4222
3979
|
this.remoteViewHost = null;
|
|
4223
3980
|
this.dragController = null;
|
|
4224
3981
|
this.dragTrackFitMode = "cover";
|
|
@@ -4232,6 +3989,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4232
3989
|
this.rtc = rtc;
|
|
4233
3990
|
this.reportError = reportError;
|
|
4234
3991
|
this.onRemoteStream = options.onRemoteStream;
|
|
3992
|
+
this.onDisconnect = options.onDisconnect;
|
|
4235
3993
|
this.onPublishPipelineWaitChange = clientOptions?.onPublishPipelineWaitChange;
|
|
4236
3994
|
if (options.remoteElement) {
|
|
4237
3995
|
this.remoteElement = options.remoteElement;
|
|
@@ -4260,7 +4018,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4260
4018
|
}
|
|
4261
4019
|
static async connect(stream, options, clientOptions) {
|
|
4262
4020
|
const sdkI18n = createSDKI18n({});
|
|
4263
|
-
const notifyUserError = clientOptions.onError;
|
|
4021
|
+
const notifyUserError = options.onError ?? clientOptions.onError;
|
|
4264
4022
|
const reportError = (error, fallbackMessage) => {
|
|
4265
4023
|
throw notifyError(error, notifyUserError, fallbackMessage ?? sdkI18n.t("errors.requestFailed"));
|
|
4266
4024
|
};
|
|
@@ -4281,6 +4039,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4281
4039
|
const session = new _RealtimeSession(client, rtc, reportError, options, clientOptions);
|
|
4282
4040
|
try {
|
|
4283
4041
|
await session.bootstrap(stream, options, clientOptions.heartbeatIntervalMs ?? 1e4, prewarmed);
|
|
4042
|
+
session.sessionEstablished = true;
|
|
4284
4043
|
return session;
|
|
4285
4044
|
} catch (error) {
|
|
4286
4045
|
await session.safeDisconnect();
|
|
@@ -4306,11 +4065,11 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4306
4065
|
heartbeatIntervalMs,
|
|
4307
4066
|
(heartbeatSession) => {
|
|
4308
4067
|
if (heartbeatSession.status !== ACTIVE_STATUS) {
|
|
4309
|
-
void this.safeDisconnect();
|
|
4068
|
+
void this.safeDisconnect({ reason: "session_inactive" });
|
|
4310
4069
|
}
|
|
4311
4070
|
},
|
|
4312
4071
|
() => {
|
|
4313
|
-
void this.safeDisconnect();
|
|
4072
|
+
void this.safeDisconnect({ reason: "heartbeat_error" });
|
|
4314
4073
|
}
|
|
4315
4074
|
);
|
|
4316
4075
|
const joinInfo = this.client.getRtcJoinInfo(createdSession);
|
|
@@ -4472,9 +4231,6 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4472
4231
|
this.reportError(error);
|
|
4473
4232
|
}
|
|
4474
4233
|
}
|
|
4475
|
-
async setMode(options) {
|
|
4476
|
-
return this.restart(options);
|
|
4477
|
-
}
|
|
4478
4234
|
async refreshRemoteOutput(options) {
|
|
4479
4235
|
if (!this.remoteVideoContainer) {
|
|
4480
4236
|
return;
|
|
@@ -4548,7 +4304,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4548
4304
|
return;
|
|
4549
4305
|
}
|
|
4550
4306
|
this.disconnected = true;
|
|
4551
|
-
await this.safeDisconnect(options);
|
|
4307
|
+
await this.safeDisconnect({ ...options, reason: "client" });
|
|
4552
4308
|
}
|
|
4553
4309
|
getSessionUid() {
|
|
4554
4310
|
return this.sessionUid;
|
|
@@ -4631,17 +4387,6 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4631
4387
|
mirrored: false,
|
|
4632
4388
|
enabled: true,
|
|
4633
4389
|
onTracks: (tracks) => {
|
|
4634
|
-
const media = this.remoteViewHost?.videoHost?.querySelector("video, canvas");
|
|
4635
|
-
const mediaRect = media?.getBoundingClientRect();
|
|
4636
|
-
const dragRect = dragHost.getBoundingClientRect();
|
|
4637
|
-
console.log("[Xmax] sendTracks", {
|
|
4638
|
-
taskUid: this.taskUid,
|
|
4639
|
-
targetSize: this.sessionTargetSize,
|
|
4640
|
-
fitMode: this.dragTrackFitMode,
|
|
4641
|
-
tracks,
|
|
4642
|
-
dragRect: dragRect ? { w: dragRect.width, h: dragRect.height } : null,
|
|
4643
|
-
mediaRect: mediaRect ? { w: mediaRect.width, h: mediaRect.height, l: mediaRect.left, t: mediaRect.top } : null
|
|
4644
|
-
});
|
|
4645
4390
|
void this.sendTracks(tracks);
|
|
4646
4391
|
}
|
|
4647
4392
|
});
|
|
@@ -4690,7 +4435,20 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4690
4435
|
this.remoteStreamNotifyTimer = null;
|
|
4691
4436
|
}
|
|
4692
4437
|
}
|
|
4438
|
+
emitDisconnect(reason) {
|
|
4439
|
+
if (!this.sessionEstablished || this.disconnectNotified) {
|
|
4440
|
+
return;
|
|
4441
|
+
}
|
|
4442
|
+
this.disconnectNotified = true;
|
|
4443
|
+
try {
|
|
4444
|
+
this.onDisconnect?.(reason);
|
|
4445
|
+
} catch {
|
|
4446
|
+
}
|
|
4447
|
+
}
|
|
4693
4448
|
async safeDisconnect(options) {
|
|
4449
|
+
const reason = options?.reason ?? this.pendingDisconnectReason;
|
|
4450
|
+
this.pendingDisconnectReason = reason;
|
|
4451
|
+
this.disconnected = true;
|
|
4694
4452
|
this.clearRemoteStreamNotifyTimer();
|
|
4695
4453
|
this.lastNotifiedRemoteStream = null;
|
|
4696
4454
|
const activeSessionUid = this.sessionUid;
|
|
@@ -4741,6 +4499,7 @@ var RealtimeSession = class _RealtimeSession {
|
|
|
4741
4499
|
this.hiddenRemoteElement.remove();
|
|
4742
4500
|
this.hiddenRemoteElement = null;
|
|
4743
4501
|
}
|
|
4502
|
+
this.emitDisconnect(reason);
|
|
4744
4503
|
}
|
|
4745
4504
|
};
|
|
4746
4505
|
|
|
@@ -5080,7 +4839,6 @@ exports.createTracksRtcRoomEvent = createTracksRtcRoomEvent;
|
|
|
5080
4839
|
exports.createVideoFileStream = createVideoFileStream;
|
|
5081
4840
|
exports.createXmaxClient = createXmaxClient;
|
|
5082
4841
|
exports.getCameraEnvironmentIssue = getCameraEnvironmentIssue;
|
|
5083
|
-
exports.getContentRect = getContentRect;
|
|
5084
4842
|
exports.getDefaultMessages = getDefaultMessages;
|
|
5085
4843
|
exports.isCameraAccessError = isCameraAccessError;
|
|
5086
4844
|
exports.isImageMediaFile = isImageMediaFile;
|