@midscene/visualizer 0.17.5 → 0.17.6-beta-20250607054355.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/dist/es/component/player.js +93 -7
- package/dist/es/index.js +3 -0
- package/dist/index.js +1 -1
- package/dist/lib/component/player.js +92 -7
- package/dist/lib/index.js +5 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +4 -4
|
@@ -15,6 +15,10 @@ var __spreadValues = (a, b) => {
|
|
|
15
15
|
}
|
|
16
16
|
return a;
|
|
17
17
|
};
|
|
18
|
+
var __publicField = (obj, key, value) => {
|
|
19
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
20
|
+
return value;
|
|
21
|
+
};
|
|
18
22
|
var __async = (__this, __arguments, generator) => {
|
|
19
23
|
return new Promise((resolve, reject) => {
|
|
20
24
|
var fulfilled = (value) => {
|
|
@@ -50,6 +54,7 @@ import { mouseLoading, mousePointer } from "../utils";
|
|
|
50
54
|
import {
|
|
51
55
|
CaretRightOutlined,
|
|
52
56
|
DownloadOutlined,
|
|
57
|
+
ExportOutlined,
|
|
53
58
|
LoadingOutlined
|
|
54
59
|
} from "@ant-design/icons";
|
|
55
60
|
import { Spin, Tooltip } from "antd";
|
|
@@ -120,6 +125,49 @@ const downloadReport = (content) => {
|
|
|
120
125
|
a.download = "midscene_report.html";
|
|
121
126
|
a.click();
|
|
122
127
|
};
|
|
128
|
+
class RecordingSession {
|
|
129
|
+
constructor(canvas) {
|
|
130
|
+
__publicField(this, "canvas");
|
|
131
|
+
__publicField(this, "mediaRecorder", null);
|
|
132
|
+
__publicField(this, "chunks");
|
|
133
|
+
__publicField(this, "recording", false);
|
|
134
|
+
this.canvas = canvas;
|
|
135
|
+
this.chunks = [];
|
|
136
|
+
}
|
|
137
|
+
start() {
|
|
138
|
+
const stream = this.canvas.captureStream(60);
|
|
139
|
+
const mediaRecorder = new MediaRecorder(stream, {
|
|
140
|
+
mimeType: "video/webm"
|
|
141
|
+
});
|
|
142
|
+
mediaRecorder.ondataavailable = (event) => {
|
|
143
|
+
if (event.data.size > 0) {
|
|
144
|
+
this.chunks.push(event.data);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
this.mediaRecorder = mediaRecorder;
|
|
148
|
+
this.recording = true;
|
|
149
|
+
return this.mediaRecorder.start();
|
|
150
|
+
}
|
|
151
|
+
stop() {
|
|
152
|
+
var _a;
|
|
153
|
+
if (!this.recording || !this.mediaRecorder) {
|
|
154
|
+
console.warn("not recording");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.mediaRecorder.onstop = () => {
|
|
158
|
+
const blob = new Blob(this.chunks, { type: "video/webm" });
|
|
159
|
+
const url = URL.createObjectURL(blob);
|
|
160
|
+
const a = document.createElement("a");
|
|
161
|
+
a.href = url;
|
|
162
|
+
a.download = "midscene_replay.webm";
|
|
163
|
+
a.click();
|
|
164
|
+
URL.revokeObjectURL(url);
|
|
165
|
+
};
|
|
166
|
+
(_a = this.mediaRecorder) == null ? void 0 : _a.stop();
|
|
167
|
+
this.recording = false;
|
|
168
|
+
this.mediaRecorder = null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
123
171
|
function Player(props) {
|
|
124
172
|
var _a;
|
|
125
173
|
const [titleText, setTitleText] = useState("");
|
|
@@ -133,6 +181,9 @@ function Player(props) {
|
|
|
133
181
|
const pointerSprite = useRef(null);
|
|
134
182
|
const spinningPointerSprite = useRef(null);
|
|
135
183
|
const [replayMark, setReplayMark] = useState(0);
|
|
184
|
+
const triggerReplay = () => {
|
|
185
|
+
setReplayMark(Date.now());
|
|
186
|
+
};
|
|
136
187
|
const windowContentContainer = useMemo(() => {
|
|
137
188
|
const container = new PIXI.Container();
|
|
138
189
|
return container;
|
|
@@ -448,6 +499,21 @@ function Player(props) {
|
|
|
448
499
|
insightMarkContainer.y = 0;
|
|
449
500
|
windowContentContainer.addChild(insightMarkContainer);
|
|
450
501
|
});
|
|
502
|
+
const [isRecording, setIsRecording] = useState(false);
|
|
503
|
+
const recorderSessionRef = useRef(null);
|
|
504
|
+
const handleExport = () => {
|
|
505
|
+
if (recorderSessionRef.current) {
|
|
506
|
+
console.warn("recorderSession exists");
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
if (!app.canvas) {
|
|
510
|
+
console.warn("canvas is not initialized");
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
recorderSessionRef.current = new RecordingSession(app.canvas);
|
|
514
|
+
setIsRecording(true);
|
|
515
|
+
triggerReplay();
|
|
516
|
+
};
|
|
451
517
|
const play = () => {
|
|
452
518
|
let cancelFn;
|
|
453
519
|
Promise.resolve(
|
|
@@ -470,7 +536,7 @@ function Player(props) {
|
|
|
470
536
|
yield repaintImage();
|
|
471
537
|
yield updateCamera(__spreadValues({}, basicCameraState));
|
|
472
538
|
const totalDuration = scripts.reduce((acc, item) => {
|
|
473
|
-
return acc + item.duration + (item.insightCameraDuration
|
|
539
|
+
return acc + item.duration + (item.camera && item.insightCameraDuration ? item.insightCameraDuration : 0);
|
|
474
540
|
}, 0);
|
|
475
541
|
const progressUpdateInterval = 200;
|
|
476
542
|
const startTime = performance.now();
|
|
@@ -486,6 +552,9 @@ function Player(props) {
|
|
|
486
552
|
}
|
|
487
553
|
};
|
|
488
554
|
frame(updateProgress);
|
|
555
|
+
if (recorderSessionRef.current) {
|
|
556
|
+
recorderSessionRef.current.start();
|
|
557
|
+
}
|
|
489
558
|
for (const index in scripts) {
|
|
490
559
|
const item = scripts[index];
|
|
491
560
|
setTitleText(item.title || "");
|
|
@@ -542,6 +611,11 @@ function Player(props) {
|
|
|
542
611
|
stop();
|
|
543
612
|
}
|
|
544
613
|
}
|
|
614
|
+
if (recorderSessionRef.current) {
|
|
615
|
+
recorderSessionRef.current.stop();
|
|
616
|
+
recorderSessionRef.current = null;
|
|
617
|
+
setIsRecording(false);
|
|
618
|
+
}
|
|
545
619
|
}))().catch((e) => {
|
|
546
620
|
console.error("player error", e);
|
|
547
621
|
})
|
|
@@ -554,7 +628,7 @@ function Player(props) {
|
|
|
554
628
|
Promise.resolve(
|
|
555
629
|
(() => __async(this, null, function* () {
|
|
556
630
|
yield init();
|
|
557
|
-
|
|
631
|
+
triggerReplay();
|
|
558
632
|
}))()
|
|
559
633
|
);
|
|
560
634
|
return () => {
|
|
@@ -578,7 +652,7 @@ function Player(props) {
|
|
|
578
652
|
if (canReplayNow) {
|
|
579
653
|
const listener = (event) => {
|
|
580
654
|
if (event.key === " ") {
|
|
581
|
-
|
|
655
|
+
triggerReplay();
|
|
582
656
|
}
|
|
583
657
|
};
|
|
584
658
|
window.addEventListener("keydown", listener);
|
|
@@ -594,7 +668,7 @@ function Player(props) {
|
|
|
594
668
|
statusIconElement = /* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(LoadingOutlined, { spin: true, color: "#333" }), size: "default" });
|
|
595
669
|
} else if (mouseOverStatusIcon) {
|
|
596
670
|
statusIconElement = /* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(CaretRightOutlined, { color: "#333" }), size: "default" });
|
|
597
|
-
statusOnClick = () =>
|
|
671
|
+
statusOnClick = () => triggerReplay();
|
|
598
672
|
} else {
|
|
599
673
|
statusIconElement = // <Spin indicator={<CheckCircleOutlined />} size="default" />
|
|
600
674
|
/* @__PURE__ */ jsx(Spin, { indicator: /* @__PURE__ */ jsx(CaretRightOutlined, { color: "#333" }), size: "default" });
|
|
@@ -616,7 +690,7 @@ function Player(props) {
|
|
|
616
690
|
/* @__PURE__ */ jsx("div", { className: "title", children: titleText }),
|
|
617
691
|
/* @__PURE__ */ jsx(Tooltip, { title: subTitleText, children: /* @__PURE__ */ jsx("div", { className: "subtitle", children: subTitleText }) })
|
|
618
692
|
] }),
|
|
619
|
-
/* @__PURE__ */ jsx(
|
|
693
|
+
isRecording ? null : /* @__PURE__ */ jsx(
|
|
620
694
|
"div",
|
|
621
695
|
{
|
|
622
696
|
className: "status-icon",
|
|
@@ -626,7 +700,7 @@ function Player(props) {
|
|
|
626
700
|
children: statusIconElement
|
|
627
701
|
}
|
|
628
702
|
),
|
|
629
|
-
(props == null ? void 0 : props.reportFileContent) ? /* @__PURE__ */ jsx(
|
|
703
|
+
(props == null ? void 0 : props.reportFileContent) ? /* @__PURE__ */ jsx(Tooltip, { title: "Download Report", children: /* @__PURE__ */ jsx(
|
|
630
704
|
"div",
|
|
631
705
|
{
|
|
632
706
|
className: "status-icon",
|
|
@@ -635,7 +709,19 @@ function Player(props) {
|
|
|
635
709
|
onClick: () => downloadReport(props.reportFileContent),
|
|
636
710
|
children: /* @__PURE__ */ jsx(DownloadOutlined, { color: "#333" })
|
|
637
711
|
}
|
|
638
|
-
) : null
|
|
712
|
+
) }) : null,
|
|
713
|
+
/* @__PURE__ */ jsx(Tooltip, { title: isRecording ? "Generating..." : "Export Video", children: /* @__PURE__ */ jsx(
|
|
714
|
+
"div",
|
|
715
|
+
{
|
|
716
|
+
className: "status-icon",
|
|
717
|
+
onClick: isRecording ? void 0 : handleExport,
|
|
718
|
+
style: {
|
|
719
|
+
opacity: isRecording ? 0.5 : 1,
|
|
720
|
+
cursor: isRecording ? "not-allowed" : "pointer"
|
|
721
|
+
},
|
|
722
|
+
children: isRecording ? /* @__PURE__ */ jsx(Spin, { size: "default", percent: progressString }) : /* @__PURE__ */ jsx(ExportOutlined, {})
|
|
723
|
+
}
|
|
724
|
+
) })
|
|
639
725
|
] }) }) })
|
|
640
726
|
] });
|
|
641
727
|
}
|
package/dist/es/index.js
CHANGED
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
getPlaceholderForType,
|
|
40
40
|
blankResult
|
|
41
41
|
} from "./component/playground/playground-utils";
|
|
42
|
+
import { timeStr, filterBase64Value } from "./utils";
|
|
42
43
|
export {
|
|
43
44
|
Blackboard,
|
|
44
45
|
ContextPreview,
|
|
@@ -55,6 +56,7 @@ export {
|
|
|
55
56
|
blankResult,
|
|
56
57
|
checkServerStatus,
|
|
57
58
|
colorForName,
|
|
59
|
+
filterBase64Value,
|
|
58
60
|
formatErrorMessage,
|
|
59
61
|
generateAnimationScripts,
|
|
60
62
|
getPlaceholderForType,
|
|
@@ -66,6 +68,7 @@ export {
|
|
|
66
68
|
requestPlaygroundServer,
|
|
67
69
|
staticAgentFromContext,
|
|
68
70
|
timeCostStrElement,
|
|
71
|
+
timeStr,
|
|
69
72
|
useEnvConfig,
|
|
70
73
|
useServerValid,
|
|
71
74
|
useStaticPageAgent
|