Skip to content

Commit 73832d3

Browse files
committed
perf: add some comments
1 parent b1f8471 commit 73832d3

2 files changed

Lines changed: 42 additions & 11 deletions

File tree

src/hooks/useResolveFile.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,19 @@ const handleFileOnLoad = (
9494
let jsonFile: Record<string, unknown> | null = null;
9595

9696
const bufferData: ArrayBuffer = e.target.result as ArrayBuffer;
97-
// 注意:第二个 'binary' 参数是无效的,这里要去掉
98-
const uint8Array = new Uint8Array(bufferData);
9997
const regExp = /\.(json|replay|cast|part)(\.mp4|\.json|\.gz)?$/;
10098

99+
/**
100+
* MP4 类型:
101+
* 处理: 直接以 Blob → ObjectURL 作为 videoUrl
102+
* 补充: ArrayBuffer 是原始二进制内存, Uint8Array 是 读取/写入这块内存的视图
103+
*
104+
* gz tar 类型:
105+
* - .replay.gz 为 Gua 产生的录像,需要写入本地磁盘.同时也会存在 .replay.mp4 形式
106+
* - .cast.gz 为字符协议的录像,直接将 ArrayBuffer 转为 ObjectURL
107+
* - .part.gz 为 Gua 的分片录像,也需要直接写入磁盘
108+
*/
109+
101110
/** -------------------- 处理 .tar -------------------- */
102111
if (fileName.includes('.tar')) {
103112
try {
@@ -108,6 +117,9 @@ const handleFileOnLoad = (
108117
const partJson: string = match?.[0] ?? '';
109118
const decompressFileName: string = match?.[1] ?? '';
110119

120+
// .part 是 rdp 的分片形式
121+
// .cast 是 字符协议的
122+
111123
// part 的 JSON:xxx.replay.json
112124
if (partJson === '.replay.json') {
113125
jsonFile = safeParseJson(extractedFile.buffer) ?? jsonFile;
@@ -178,7 +190,6 @@ const handleFileOnLoad = (
178190
break;
179191
}
180192
default:
181-
// 其他文件跳过
182193
break;
183194
}
184195
}
@@ -209,8 +220,10 @@ const handleFileOnLoad = (
209220
switch (processName) {
210221
case 'replay': {
211222
const isGua = fileName.split('.')[2] === 'gz';
223+
212224
if (isGua) {
213225
type = 'gua';
226+
214227
try {
215228
const res = await handleGuaData(
216229
e.currentTarget?.result as ArrayBuffer,
@@ -275,8 +288,14 @@ const handleFileOnLoad = (
275288
/** -------------------- 处理 .mp4 -------------------- */
276289
if (fileName.includes('.mp4')) {
277290
type = 'mp4';
291+
292+
/**
293+
* 完全没必要下面这种写法,可以直接替换为 const videoBlob = new Blob([e.currentTarget.result], { type: "video/mp4" });
294+
* new Blob 本身就可以接收 ArrayBuffer 类型 ArrayBufferView 类型 等,而 Uint8Array 类型本身就归属于 ArrayBufferView
295+
*/
278296
const videoBuffer: Uint8Array = new Uint8Array(e.currentTarget?.result as ArrayBuffer);
279297
const videoBlob: Blob = new Blob([videoBuffer], { type: 'video/mp4' });
298+
280299
videoUrl = URL.createObjectURL(videoBlob);
281300

282301
fileStore.setVideoList({
@@ -312,13 +331,15 @@ const fileParser = (fileInfo: UploadFileInfo, eventOptions: IFileParser): Promis
312331

313332
fileReader.readAsArrayBuffer(file);
314333

334+
// 读取过程
315335
fileReader.onprogress = (e: ProgressEvent<FileReader>) => {
316336
if (e.lengthComputable) {
317337
const percentComplete = Math.round((e.loaded / e.total) * 100);
318338
eventOptions.onProgress({ percent: percentComplete });
319339
}
320340
};
321341

342+
// 读取成功
322343
fileReader.onload = async (e: ProgressEvent<FileReader>) => {
323344
try {
324345
const res = await handleFileOnLoad(e, fileName, eventOptions);
@@ -332,6 +353,7 @@ const fileParser = (fileInfo: UploadFileInfo, eventOptions: IFileParser): Promis
332353
}
333354
};
334355

356+
// 读取失败
335357
fileReader.onerror = () => {
336358
eventOptions.onError();
337359
notification.error({

src/views/guaPlayer/index.vue

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,21 @@ const playerAreaRef = ref<HTMLElement | null>(null);
6666
const scale = ref(0);
6767
const max = ref(100);
6868
const currentPercent = ref(0);
69-
const chunks = ref('');
69+
let chunksArr: string[] = [];
7070
const totalDuration = ref('00:00');
7171
const currentPosition = ref('00:00');
7272
const isPlaying = ref(false);
7373
const isProcessing = ref(false);
7474
const loadingBuffer = ref(false);
7575
const fileDataEndCalled = ref(false);
7676
77+
/**
78+
* @description 计算缩放比
79+
*
80+
* 核心:
81+
* 哪个方向比例更小,就由哪个方向限制缩放,避免该方向溢出;另一方向会留出空白.如果容器更“扁宽”,则宽度限制比例(scaleX 更小);如果更“瘦高”,则高度限制比例(scaleY 更小)
82+
* 设原始画布尺寸为 (W, H),容器尺寸为 (Cw, Ch),统一缩放比例为 s. 约束就是 缩放后尺寸不超过容器 s * W <= Cw; s * H <= Ch 因此 s <= Cw / W 且 s <= Ch / H
83+
*/
7784
const recomputeScale = () => {
7885
if (!display || !display.getDefaultLayer) return;
7986
@@ -134,19 +141,20 @@ const loadResource = async (record: any) => {
134141
el.appendChild(displayElement);
135142
136143
await window.electron.readFile(guaUrl.value);
137-
chunks.value = '';
144+
chunksArr.length = 0;
138145
139146
window.electron.onFileDataChunk(chunk => {
140147
try {
141-
chunks.value += chunk.trim();
148+
// 不进行 trim,避免破坏协议文本边界
149+
chunksArr.push(chunk);
142150
} catch (e) {
143151
console.log(e);
144152
}
145153
});
146154
147155
window.electron.onFileDataEnd(() => {
148156
if (fileDataEndCalled.value) {
149-
chunks.value = '';
157+
chunksArr.length = 0;
150158
return;
151159
}
152160
fileDataEndCalled.value = true;
@@ -164,8 +172,9 @@ const loadResource = async (record: any) => {
164172
}
165173
}
166174
167-
record.connect(chunks.value);
168-
chunks.value = '';
175+
const data = chunksArr.join('');
176+
record.connect(data);
177+
chunksArr.length = 0;
169178
initRecordingEvent(record);
170179
});
171180
@@ -453,15 +462,15 @@ onBeforeUnmount(() => {
453462
tunnel = null;
454463
recording = null;
455464
display = null;
456-
chunks.value = '';
465+
chunksArr.length = 0;
457466
}
458467
459468
delete (window as any).guacamoleKeyHandler;
460469
delete (window as any).guacamoleWheelHandler;
461470
});
462471
463472
onUnmounted(() => {
464-
chunks.value = '';
473+
chunksArr.length = 0;
465474
currentPercent.value = 0;
466475
currentPosition.value = '00:00';
467476
isPlaying.value = false;

0 commit comments

Comments
 (0)