@dialtribe/react-sdk 0.1.0-alpha.19 → 0.1.0-alpha.21

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.
@@ -203,13 +203,33 @@ declare class WebSocketStreamer {
203
203
  private onBytesUpdate?;
204
204
  private onStateChange?;
205
205
  private onError?;
206
+ private canvasState;
206
207
  constructor(options: WebSocketStreamerOptions);
208
+ /**
209
+ * Calculate scaled dimensions for fitting video into canvas.
210
+ * @param mode - "contain" fits video inside canvas, "cover" fills canvas (cropping)
211
+ */
212
+ private calculateScaledDimensions;
213
+ /**
214
+ * Invalidate cached scaling dimensions (call when video source changes)
215
+ */
216
+ private invalidateScalingCache;
207
217
  /**
208
218
  * Validate stream key format
209
219
  * Stream keys must follow format: {tierCode}{foreignId}_{randomKey}
210
220
  * Tier codes: a (audio shared), b (audio VIP), v (video shared), w (video VIP)
211
221
  */
212
222
  private validateStreamKeyFormat;
223
+ /**
224
+ * Set up canvas-based rendering pipeline for video streams.
225
+ * This allows seamless camera flips by changing the video source
226
+ * without affecting MediaRecorder (which records from the canvas).
227
+ */
228
+ private setupCanvasRendering;
229
+ /**
230
+ * Clean up canvas rendering resources
231
+ */
232
+ private cleanupCanvasRendering;
213
233
  /**
214
234
  * Build WebSocket URL from stream key
215
235
  */
@@ -226,43 +246,37 @@ declare class WebSocketStreamer {
226
246
  * Get total bytes sent
227
247
  */
228
248
  getBytesSent(): number;
249
+ /**
250
+ * Get the current source media stream.
251
+ * This may change after replaceVideoTrack() is called.
252
+ */
253
+ getMediaStream(): MediaStream;
229
254
  /**
230
255
  * Get current diagnostics
231
256
  */
232
257
  private getDiagnostics;
233
258
  /**
234
- * Prepare for a hot-swap by stopping the MediaRecorder
235
- * Call this BEFORE requesting a new camera stream on iOS
236
- * This prevents iOS Safari from interfering with the active MediaRecorder
259
+ * Replace the video track for camera flips.
237
260
  *
238
- * IMPORTANT: This is async because we must wait for the MediaRecorder's 'stop'
239
- * event to fire BEFORE proceeding. Otherwise there's a race condition where
240
- * the stop event fires after isHotSwapping is set to false, causing the
241
- * WebSocket to close unexpectedly.
242
- */
243
- prepareForHotSwap(): Promise<void>;
244
- /**
245
- * Cancel a prepared hot-swap (e.g., if camera switch failed)
246
- * Restarts the MediaRecorder with the existing stream
261
+ * When using canvas-based rendering (video streams), this updates the video
262
+ * element source. The canvas continues drawing, and MediaRecorder is unaffected.
263
+ *
264
+ * @param newVideoTrack - The new video track from the flipped camera
247
265
  */
248
- cancelHotSwap(): void;
266
+ replaceVideoTrack(newVideoTrack: MediaStreamTrack): void;
249
267
  /**
250
- * Complete the hot-swap with a new media stream
251
- * Call this AFTER successfully obtaining a new camera stream
268
+ * Replace the audio track in the current MediaStream without stopping MediaRecorder.
252
269
  *
253
- * Note: Errors are thrown to the caller, not sent to onError callback
254
- * This allows the caller to handle camera flip failures gracefully
270
+ * @param newAudioTrack - The new audio track
255
271
  */
256
- completeHotSwap(newMediaStream: MediaStream): void;
272
+ replaceAudioTrack(newAudioTrack: MediaStreamTrack): void;
257
273
  /**
258
- * Update the media stream (e.g., when flipping camera)
259
- * This keeps the WebSocket connection alive while swapping the media source
260
- *
261
- * Note: On iOS, prefer using prepareForHotSwap() + completeHotSwap() to avoid
262
- * issues where getUserMedia interferes with the active MediaRecorder.
274
+ * Update the media stream (e.g., when switching devices from settings)
275
+ * This keeps the WebSocket connection alive while swapping the media source.
276
+ * Restarts the MediaRecorder with the new stream.
263
277
  *
264
- * Note: Errors are thrown to the caller, not sent to onError callback
265
- * This allows the caller to handle camera flip failures gracefully
278
+ * Note: For camera flips, prefer replaceVideoTrack() which doesn't restart MediaRecorder.
279
+ * Note: Errors are thrown to the caller, not sent to onError callback.
266
280
  */
267
281
  updateMediaStream(newMediaStream: MediaStream): Promise<void>;
268
282
  /**
@@ -203,13 +203,33 @@ declare class WebSocketStreamer {
203
203
  private onBytesUpdate?;
204
204
  private onStateChange?;
205
205
  private onError?;
206
+ private canvasState;
206
207
  constructor(options: WebSocketStreamerOptions);
208
+ /**
209
+ * Calculate scaled dimensions for fitting video into canvas.
210
+ * @param mode - "contain" fits video inside canvas, "cover" fills canvas (cropping)
211
+ */
212
+ private calculateScaledDimensions;
213
+ /**
214
+ * Invalidate cached scaling dimensions (call when video source changes)
215
+ */
216
+ private invalidateScalingCache;
207
217
  /**
208
218
  * Validate stream key format
209
219
  * Stream keys must follow format: {tierCode}{foreignId}_{randomKey}
210
220
  * Tier codes: a (audio shared), b (audio VIP), v (video shared), w (video VIP)
211
221
  */
212
222
  private validateStreamKeyFormat;
223
+ /**
224
+ * Set up canvas-based rendering pipeline for video streams.
225
+ * This allows seamless camera flips by changing the video source
226
+ * without affecting MediaRecorder (which records from the canvas).
227
+ */
228
+ private setupCanvasRendering;
229
+ /**
230
+ * Clean up canvas rendering resources
231
+ */
232
+ private cleanupCanvasRendering;
213
233
  /**
214
234
  * Build WebSocket URL from stream key
215
235
  */
@@ -226,43 +246,37 @@ declare class WebSocketStreamer {
226
246
  * Get total bytes sent
227
247
  */
228
248
  getBytesSent(): number;
249
+ /**
250
+ * Get the current source media stream.
251
+ * This may change after replaceVideoTrack() is called.
252
+ */
253
+ getMediaStream(): MediaStream;
229
254
  /**
230
255
  * Get current diagnostics
231
256
  */
232
257
  private getDiagnostics;
233
258
  /**
234
- * Prepare for a hot-swap by stopping the MediaRecorder
235
- * Call this BEFORE requesting a new camera stream on iOS
236
- * This prevents iOS Safari from interfering with the active MediaRecorder
259
+ * Replace the video track for camera flips.
237
260
  *
238
- * IMPORTANT: This is async because we must wait for the MediaRecorder's 'stop'
239
- * event to fire BEFORE proceeding. Otherwise there's a race condition where
240
- * the stop event fires after isHotSwapping is set to false, causing the
241
- * WebSocket to close unexpectedly.
242
- */
243
- prepareForHotSwap(): Promise<void>;
244
- /**
245
- * Cancel a prepared hot-swap (e.g., if camera switch failed)
246
- * Restarts the MediaRecorder with the existing stream
261
+ * When using canvas-based rendering (video streams), this updates the video
262
+ * element source. The canvas continues drawing, and MediaRecorder is unaffected.
263
+ *
264
+ * @param newVideoTrack - The new video track from the flipped camera
247
265
  */
248
- cancelHotSwap(): void;
266
+ replaceVideoTrack(newVideoTrack: MediaStreamTrack): void;
249
267
  /**
250
- * Complete the hot-swap with a new media stream
251
- * Call this AFTER successfully obtaining a new camera stream
268
+ * Replace the audio track in the current MediaStream without stopping MediaRecorder.
252
269
  *
253
- * Note: Errors are thrown to the caller, not sent to onError callback
254
- * This allows the caller to handle camera flip failures gracefully
270
+ * @param newAudioTrack - The new audio track
255
271
  */
256
- completeHotSwap(newMediaStream: MediaStream): void;
272
+ replaceAudioTrack(newAudioTrack: MediaStreamTrack): void;
257
273
  /**
258
- * Update the media stream (e.g., when flipping camera)
259
- * This keeps the WebSocket connection alive while swapping the media source
260
- *
261
- * Note: On iOS, prefer using prepareForHotSwap() + completeHotSwap() to avoid
262
- * issues where getUserMedia interferes with the active MediaRecorder.
274
+ * Update the media stream (e.g., when switching devices from settings)
275
+ * This keeps the WebSocket connection alive while swapping the media source.
276
+ * Restarts the MediaRecorder with the new stream.
263
277
  *
264
- * Note: Errors are thrown to the caller, not sent to onError callback
265
- * This allows the caller to handle camera flip failures gracefully
278
+ * Note: For camera flips, prefer replaceVideoTrack() which doesn't restart MediaRecorder.
279
+ * Note: Errors are thrown to the caller, not sent to onError callback.
266
280
  */
267
281
  updateMediaStream(newMediaStream: MediaStream): Promise<void>;
268
282
  /**
@@ -1,4 +1,4 @@
1
1
  export { A as ApiClientConfig, h as AudioWaveform, B as Broadcast, C as CDN_DOMAIN, d as DIALTRIBE_API_BASE, c as DialtribeClient, a as DialtribeContextValue, i as DialtribeOverlay, k as DialtribeOverlayMode, j as DialtribeOverlayProps, e as DialtribePlayer, g as DialtribePlayerErrorBoundary, f as DialtribePlayerProps, D as DialtribeProvider, b as DialtribeProviderProps, E as ENDPOINTS, H as HTTP_STATUS, q as HttpStatusCode, L as LoadingSpinner, m as TranscriptData, l as TranscriptSegment, T as TranscriptWord, o as buildBroadcastCdnUrl, p as buildBroadcastS3KeyPrefix, n as formatTime, u as useDialtribe, r as useDialtribeOptional } from './dialtribe-player-CNriUtNi.mjs';
2
- export { j as DEFAULT_ENCODER_SERVER_URL, D as DialtribeStreamer, a as DialtribeStreamerProps, M as MediaConstraintsOptions, O as OpenDialtribeStreamerPopupOptions, P as PopupDimensions, w as PopupFallbackMode, f as StreamKeyDisplay, g as StreamKeyDisplayProps, h as StreamKeyInput, i as StreamKeyInputProps, e as StreamingControlState, c as StreamingControls, d as StreamingControlsProps, S as StreamingPreview, b as StreamingPreviewProps, t as UseDialtribeStreamerLauncherOptions, v as UseDialtribeStreamerLauncherReturn, U as UseDialtribeStreamerPopupReturn, W as WebSocketStreamer, k as WebSocketStreamerOptions, r as calculatePopupDimensions, o as checkBrowserCompatibility, m as getMediaConstraints, n as getMediaRecorderOptions, q as openBroadcastPopup, p as openDialtribeStreamerPopup, s as useDialtribeStreamerLauncher, u as useDialtribeStreamerPopup } from './dialtribe-streamer-Bb6LLFG2.mjs';
2
+ export { j as DEFAULT_ENCODER_SERVER_URL, D as DialtribeStreamer, a as DialtribeStreamerProps, M as MediaConstraintsOptions, O as OpenDialtribeStreamerPopupOptions, P as PopupDimensions, w as PopupFallbackMode, f as StreamKeyDisplay, g as StreamKeyDisplayProps, h as StreamKeyInput, i as StreamKeyInputProps, e as StreamingControlState, c as StreamingControls, d as StreamingControlsProps, S as StreamingPreview, b as StreamingPreviewProps, t as UseDialtribeStreamerLauncherOptions, v as UseDialtribeStreamerLauncherReturn, U as UseDialtribeStreamerPopupReturn, W as WebSocketStreamer, k as WebSocketStreamerOptions, r as calculatePopupDimensions, o as checkBrowserCompatibility, m as getMediaConstraints, n as getMediaRecorderOptions, q as openBroadcastPopup, p as openDialtribeStreamerPopup, s as useDialtribeStreamerLauncher, u as useDialtribeStreamerPopup } from './dialtribe-streamer-DH23BseY.mjs';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
@@ -1,4 +1,4 @@
1
1
  export { A as ApiClientConfig, h as AudioWaveform, B as Broadcast, C as CDN_DOMAIN, d as DIALTRIBE_API_BASE, c as DialtribeClient, a as DialtribeContextValue, i as DialtribeOverlay, k as DialtribeOverlayMode, j as DialtribeOverlayProps, e as DialtribePlayer, g as DialtribePlayerErrorBoundary, f as DialtribePlayerProps, D as DialtribeProvider, b as DialtribeProviderProps, E as ENDPOINTS, H as HTTP_STATUS, q as HttpStatusCode, L as LoadingSpinner, m as TranscriptData, l as TranscriptSegment, T as TranscriptWord, o as buildBroadcastCdnUrl, p as buildBroadcastS3KeyPrefix, n as formatTime, u as useDialtribe, r as useDialtribeOptional } from './dialtribe-player-CNriUtNi.js';
2
- export { j as DEFAULT_ENCODER_SERVER_URL, D as DialtribeStreamer, a as DialtribeStreamerProps, M as MediaConstraintsOptions, O as OpenDialtribeStreamerPopupOptions, P as PopupDimensions, w as PopupFallbackMode, f as StreamKeyDisplay, g as StreamKeyDisplayProps, h as StreamKeyInput, i as StreamKeyInputProps, e as StreamingControlState, c as StreamingControls, d as StreamingControlsProps, S as StreamingPreview, b as StreamingPreviewProps, t as UseDialtribeStreamerLauncherOptions, v as UseDialtribeStreamerLauncherReturn, U as UseDialtribeStreamerPopupReturn, W as WebSocketStreamer, k as WebSocketStreamerOptions, r as calculatePopupDimensions, o as checkBrowserCompatibility, m as getMediaConstraints, n as getMediaRecorderOptions, q as openBroadcastPopup, p as openDialtribeStreamerPopup, s as useDialtribeStreamerLauncher, u as useDialtribeStreamerPopup } from './dialtribe-streamer-jxyxtG7Z.js';
2
+ export { j as DEFAULT_ENCODER_SERVER_URL, D as DialtribeStreamer, a as DialtribeStreamerProps, M as MediaConstraintsOptions, O as OpenDialtribeStreamerPopupOptions, P as PopupDimensions, w as PopupFallbackMode, f as StreamKeyDisplay, g as StreamKeyDisplayProps, h as StreamKeyInput, i as StreamKeyInputProps, e as StreamingControlState, c as StreamingControls, d as StreamingControlsProps, S as StreamingPreview, b as StreamingPreviewProps, t as UseDialtribeStreamerLauncherOptions, v as UseDialtribeStreamerLauncherReturn, U as UseDialtribeStreamerPopupReturn, W as WebSocketStreamer, k as WebSocketStreamerOptions, r as calculatePopupDimensions, o as checkBrowserCompatibility, m as getMediaConstraints, n as getMediaRecorderOptions, q as openBroadcastPopup, p as openDialtribeStreamerPopup, s as useDialtribeStreamerLauncher, u as useDialtribeStreamerPopup } from './dialtribe-streamer-D9ulVBVb.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';