@dialtribe/react-sdk 0.1.0-alpha.21 → 0.1.0-alpha.23
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/dist/{dialtribe-streamer-D9ulVBVb.d.ts → dialtribe-streamer-DOhD-r_F.d.ts} +8 -3
- package/dist/{dialtribe-streamer-DH23BseY.d.mts → dialtribe-streamer-Do-8Oavc.d.mts} +8 -3
- package/dist/dialtribe-streamer.d.mts +1 -1
- package/dist/dialtribe-streamer.d.ts +1 -1
- package/dist/dialtribe-streamer.js +101 -13
- package/dist/dialtribe-streamer.js.map +1 -1
- package/dist/dialtribe-streamer.mjs +101 -13
- package/dist/dialtribe-streamer.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +101 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +101 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { HelloWorld, HelloWorldProps } from './hello-world.mjs';
|
|
2
2
|
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 } from './dialtribe-player-CNriUtNi.mjs';
|
|
3
|
-
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, l as StreamDiagnostics, 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-
|
|
3
|
+
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, l as StreamDiagnostics, 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-Do-8Oavc.mjs';
|
|
4
4
|
import 'react/jsx-runtime';
|
|
5
5
|
import 'react';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { HelloWorld, HelloWorldProps } from './hello-world.js';
|
|
2
2
|
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 } from './dialtribe-player-CNriUtNi.js';
|
|
3
|
-
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, l as StreamDiagnostics, 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-
|
|
3
|
+
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, l as StreamDiagnostics, 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-DOhD-r_F.js';
|
|
4
4
|
import 'react/jsx-runtime';
|
|
5
5
|
import 'react';
|
package/dist/index.js
CHANGED
|
@@ -2344,8 +2344,11 @@ var WebSocketStreamer = class {
|
|
|
2344
2344
|
* Set up canvas-based rendering pipeline for video streams.
|
|
2345
2345
|
* This allows seamless camera flips by changing the video source
|
|
2346
2346
|
* without affecting MediaRecorder (which records from the canvas).
|
|
2347
|
+
*
|
|
2348
|
+
* This is async to ensure the video is producing frames before returning,
|
|
2349
|
+
* which prevents black initial thumbnails.
|
|
2347
2350
|
*/
|
|
2348
|
-
setupCanvasRendering() {
|
|
2351
|
+
async setupCanvasRendering() {
|
|
2349
2352
|
console.log("\u{1F3A8} Setting up canvas-based rendering for seamless camera flips");
|
|
2350
2353
|
const videoTrack = this.mediaStream.getVideoTracks()[0];
|
|
2351
2354
|
const settings = videoTrack?.getSettings() || {};
|
|
@@ -2363,7 +2366,27 @@ var WebSocketStreamer = class {
|
|
|
2363
2366
|
videoElement.srcObject = this.mediaStream;
|
|
2364
2367
|
videoElement.muted = true;
|
|
2365
2368
|
videoElement.playsInline = true;
|
|
2366
|
-
|
|
2369
|
+
await new Promise((resolve) => {
|
|
2370
|
+
const checkReady = () => {
|
|
2371
|
+
if (videoElement.videoWidth > 0 && videoElement.videoHeight > 0) {
|
|
2372
|
+
console.log(`\u{1F4F9} Video ready: ${videoElement.videoWidth}x${videoElement.videoHeight}`);
|
|
2373
|
+
resolve();
|
|
2374
|
+
} else {
|
|
2375
|
+
requestAnimationFrame(checkReady);
|
|
2376
|
+
}
|
|
2377
|
+
};
|
|
2378
|
+
videoElement.addEventListener("loadeddata", () => {
|
|
2379
|
+
checkReady();
|
|
2380
|
+
}, { once: true });
|
|
2381
|
+
videoElement.play().catch((e) => {
|
|
2382
|
+
console.warn("Video autoplay warning:", e);
|
|
2383
|
+
resolve();
|
|
2384
|
+
});
|
|
2385
|
+
setTimeout(() => {
|
|
2386
|
+
console.warn("\u26A0\uFE0F Video ready timeout - continuing anyway");
|
|
2387
|
+
resolve();
|
|
2388
|
+
}, 2e3);
|
|
2389
|
+
});
|
|
2367
2390
|
const frameRate = settings.frameRate || 30;
|
|
2368
2391
|
const stream = canvas.captureStream(frameRate);
|
|
2369
2392
|
const audioTracks = this.mediaStream.getAudioTracks();
|
|
@@ -2386,13 +2409,28 @@ var WebSocketStreamer = class {
|
|
|
2386
2409
|
lastVideoWidth: 0,
|
|
2387
2410
|
lastVideoHeight: 0
|
|
2388
2411
|
};
|
|
2412
|
+
if (videoElement.videoWidth > 0 && videoElement.videoHeight > 0) {
|
|
2413
|
+
const vw = videoElement.videoWidth;
|
|
2414
|
+
const vh = videoElement.videoHeight;
|
|
2415
|
+
const cw = canvas.width;
|
|
2416
|
+
const ch = canvas.height;
|
|
2417
|
+
const scale = Math.min(cw / vw, ch / vh);
|
|
2418
|
+
const sw = vw * scale;
|
|
2419
|
+
const sh = vh * scale;
|
|
2420
|
+
const sx = (cw - sw) / 2;
|
|
2421
|
+
const sy = (ch - sh) / 2;
|
|
2422
|
+
ctx.fillStyle = "#000";
|
|
2423
|
+
ctx.fillRect(0, 0, cw, ch);
|
|
2424
|
+
ctx.drawImage(videoElement, sx, sy, sw, sh);
|
|
2425
|
+
console.log("\u{1F5BC}\uFE0F Drew first frame synchronously to prevent black thumbnail");
|
|
2426
|
+
}
|
|
2389
2427
|
const state = this.canvasState;
|
|
2390
2428
|
const renderFrame = () => {
|
|
2391
2429
|
if (!this.canvasState || state !== this.canvasState) return;
|
|
2392
2430
|
const { ctx: ctx2, canvas: canvas2, videoElement: videoElement2 } = state;
|
|
2393
2431
|
if (videoElement2.paused) {
|
|
2394
|
-
|
|
2395
|
-
|
|
2432
|
+
videoElement2.play().catch(() => {
|
|
2433
|
+
});
|
|
2396
2434
|
}
|
|
2397
2435
|
const canvasWidth = canvas2.width;
|
|
2398
2436
|
const canvasHeight = canvas2.height;
|
|
@@ -2527,7 +2565,7 @@ Please check encoder server logs and DATABASE_URL configuration.`
|
|
|
2527
2565
|
});
|
|
2528
2566
|
console.log("\u2705 WebSocket connected");
|
|
2529
2567
|
this.setupWebSocketHandlers();
|
|
2530
|
-
const streamToRecord = this.isVideo ? this.setupCanvasRendering() : this.mediaStream;
|
|
2568
|
+
const streamToRecord = this.isVideo ? await this.setupCanvasRendering() : this.mediaStream;
|
|
2531
2569
|
const recorderOptions = getMediaRecorderOptions(this.isVideo);
|
|
2532
2570
|
this.mimeType = recorderOptions.mimeType;
|
|
2533
2571
|
this.mediaRecorder = new MediaRecorder(streamToRecord, recorderOptions);
|
|
@@ -2605,20 +2643,70 @@ Please check encoder server logs and DATABASE_URL configuration.`
|
|
|
2605
2643
|
/**
|
|
2606
2644
|
* Replace the video track for camera flips.
|
|
2607
2645
|
*
|
|
2608
|
-
* When using canvas-based rendering (video streams), this
|
|
2609
|
-
*
|
|
2646
|
+
* When using canvas-based rendering (video streams), this preloads the new
|
|
2647
|
+
* camera in a temporary video element, waits for it to be ready, then swaps
|
|
2648
|
+
* it in. This ensures continuous frame output with no gaps.
|
|
2610
2649
|
*
|
|
2611
2650
|
* @param newVideoTrack - The new video track from the flipped camera
|
|
2651
|
+
* @returns Promise that resolves when the swap is complete
|
|
2612
2652
|
*/
|
|
2613
|
-
replaceVideoTrack(newVideoTrack) {
|
|
2653
|
+
async replaceVideoTrack(newVideoTrack) {
|
|
2614
2654
|
console.log("\u{1F504} Replacing video track");
|
|
2615
2655
|
if (this.canvasState) {
|
|
2616
|
-
console.log("\u{1F3A8} Using canvas-based swap (
|
|
2656
|
+
console.log("\u{1F3A8} Using canvas-based swap with preloading (no frame gaps)");
|
|
2617
2657
|
const audioTracks = this.mediaStream.getAudioTracks();
|
|
2618
2658
|
const newStream = new MediaStream([newVideoTrack, ...audioTracks]);
|
|
2659
|
+
const preloadVideo = document.createElement("video");
|
|
2660
|
+
preloadVideo.srcObject = newStream;
|
|
2661
|
+
preloadVideo.muted = true;
|
|
2662
|
+
preloadVideo.playsInline = true;
|
|
2663
|
+
await new Promise((resolve, reject) => {
|
|
2664
|
+
const timeout = setTimeout(() => {
|
|
2665
|
+
console.warn("\u26A0\uFE0F Video preload timeout - switching anyway");
|
|
2666
|
+
if (preloadVideo.paused) {
|
|
2667
|
+
preloadVideo.play().catch(() => {
|
|
2668
|
+
});
|
|
2669
|
+
}
|
|
2670
|
+
resolve();
|
|
2671
|
+
}, 3e3);
|
|
2672
|
+
const checkFullyReady = () => {
|
|
2673
|
+
if (preloadVideo.videoWidth > 0 && preloadVideo.videoHeight > 0 && !preloadVideo.paused) {
|
|
2674
|
+
clearTimeout(timeout);
|
|
2675
|
+
console.log(`\u{1F4F9} New camera ready and playing: ${preloadVideo.videoWidth}x${preloadVideo.videoHeight}`);
|
|
2676
|
+
resolve();
|
|
2677
|
+
return true;
|
|
2678
|
+
}
|
|
2679
|
+
return false;
|
|
2680
|
+
};
|
|
2681
|
+
preloadVideo.addEventListener("loadeddata", () => {
|
|
2682
|
+
preloadVideo.play().then(() => {
|
|
2683
|
+
requestAnimationFrame(() => {
|
|
2684
|
+
if (!checkFullyReady()) {
|
|
2685
|
+
const pollPlaying = setInterval(() => {
|
|
2686
|
+
if (checkFullyReady()) {
|
|
2687
|
+
clearInterval(pollPlaying);
|
|
2688
|
+
}
|
|
2689
|
+
}, 50);
|
|
2690
|
+
setTimeout(() => clearInterval(pollPlaying), 2e3);
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
}).catch((e) => {
|
|
2694
|
+
console.warn("Video preload play warning:", e);
|
|
2695
|
+
checkFullyReady();
|
|
2696
|
+
});
|
|
2697
|
+
}, { once: true });
|
|
2698
|
+
preloadVideo.addEventListener("error", (e) => {
|
|
2699
|
+
clearTimeout(timeout);
|
|
2700
|
+
reject(new Error(`Video preload failed: ${e}`));
|
|
2701
|
+
}, { once: true });
|
|
2702
|
+
preloadVideo.play().catch(() => {
|
|
2703
|
+
});
|
|
2704
|
+
});
|
|
2705
|
+
const oldVideoElement = this.canvasState.videoElement;
|
|
2706
|
+
this.canvasState.videoElement = preloadVideo;
|
|
2619
2707
|
this.mediaStream.getVideoTracks().forEach((track) => track.stop());
|
|
2620
|
-
|
|
2621
|
-
|
|
2708
|
+
oldVideoElement.pause();
|
|
2709
|
+
oldVideoElement.srcObject = null;
|
|
2622
2710
|
this.mediaStream = newStream;
|
|
2623
2711
|
this.invalidateScalingCache();
|
|
2624
2712
|
const settings = newVideoTrack.getSettings();
|
|
@@ -2682,7 +2770,7 @@ Please check encoder server logs and DATABASE_URL configuration.`
|
|
|
2682
2770
|
let streamToRecord = this.mediaStream;
|
|
2683
2771
|
if (this.isVideo) {
|
|
2684
2772
|
this.cleanupCanvasRendering();
|
|
2685
|
-
streamToRecord = this.setupCanvasRendering();
|
|
2773
|
+
streamToRecord = await this.setupCanvasRendering();
|
|
2686
2774
|
console.log("\u{1F3A8} Canvas rendering recreated for new stream");
|
|
2687
2775
|
}
|
|
2688
2776
|
const recorderOptions = getMediaRecorderOptions(this.isVideo);
|
|
@@ -3658,7 +3746,7 @@ function DialtribeStreamer({
|
|
|
3658
3746
|
console.log("\u{1F4F7} Got new camera stream:", newFacingMode);
|
|
3659
3747
|
const newVideoTrack = newStream.getVideoTracks()[0];
|
|
3660
3748
|
if (newVideoTrack) {
|
|
3661
|
-
streamer.replaceVideoTrack(newVideoTrack);
|
|
3749
|
+
await streamer.replaceVideoTrack(newVideoTrack);
|
|
3662
3750
|
}
|
|
3663
3751
|
const updatedStream = streamer.getMediaStream();
|
|
3664
3752
|
setMediaStream(updatedStream);
|