提高视频帧率
This commit is contained in:
@@ -41,19 +41,14 @@ export default {
|
||||
methods: {
|
||||
createPlayer(url) {
|
||||
if (!url) {
|
||||
console.error('❌ 播放地址为空');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否是 WebSocket URL
|
||||
if (!url.startsWith('ws://') && !url.startsWith('wss://')) {
|
||||
console.error('❌ JpegPlayer 只支持 WebSocket URL');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🎬 创建 JPEG WebSocket 播放器');
|
||||
console.log('📺 WebSocket URL:', url);
|
||||
|
||||
// 关闭旧连接
|
||||
if (this.ws) {
|
||||
this.ws.close();
|
||||
@@ -67,7 +62,6 @@ export default {
|
||||
this.ws.binaryType = 'arraybuffer';
|
||||
|
||||
this.ws.onopen = () => {
|
||||
console.log('✅ WebSocket 连接已建立');
|
||||
this.lastFrameTime = Date.now();
|
||||
};
|
||||
|
||||
@@ -76,11 +70,10 @@ export default {
|
||||
};
|
||||
|
||||
this.ws.onerror = (error) => {
|
||||
console.error('❌ WebSocket 错误:', error);
|
||||
// 静默处理错误
|
||||
};
|
||||
|
||||
this.ws.onclose = () => {
|
||||
console.log('⚠️ WebSocket 连接已关闭');
|
||||
this.isPlay = false;
|
||||
};
|
||||
},
|
||||
@@ -95,39 +88,46 @@ export default {
|
||||
this.latency = now - this.lastFrameTime;
|
||||
this.lastFrameTime = now;
|
||||
|
||||
// 将 ArrayBuffer 转换为 Blob
|
||||
const blob = new Blob([data], { type: 'image/jpeg' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
// 创建图片对象
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
// 调整 canvas 尺寸
|
||||
if (this.canvas.width !== img.width || this.canvas.height !== img.height) {
|
||||
this.canvas.width = img.width;
|
||||
this.canvas.height = img.height;
|
||||
console.log('📐 Canvas 尺寸:', img.width, 'x', img.height);
|
||||
}
|
||||
|
||||
// 绘制图片
|
||||
this.ctx.drawImage(img, 0, 0);
|
||||
// 使用 createImageBitmap 实现更快的解码(如果浏览器支持)
|
||||
if (window.createImageBitmap) {
|
||||
const blob = new Blob([data], { type: 'image/jpeg' });
|
||||
createImageBitmap(blob).then(imageBitmap => {
|
||||
// 只在尺寸变化时调整 canvas
|
||||
if (this.canvas.width !== imageBitmap.width || this.canvas.height !== imageBitmap.height) {
|
||||
this.canvas.width = imageBitmap.width;
|
||||
this.canvas.height = imageBitmap.height;
|
||||
}
|
||||
|
||||
// 直接绘制 imageBitmap(比 Image 对象更快)
|
||||
this.ctx.drawImage(imageBitmap, 0, 0);
|
||||
imageBitmap.close(); // 释放内存
|
||||
}).catch(() => {
|
||||
// 静默处理错误
|
||||
});
|
||||
} else {
|
||||
// 降级方案:使用传统的 Image 对象
|
||||
const blob = new Blob([data], { type: 'image/jpeg' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const img = new Image();
|
||||
|
||||
// 释放 URL
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
// 只在前几帧输出日志
|
||||
if (this.frameCount <= 3 || this.frameCount % 100 === 0) {
|
||||
console.log(`📹 接收帧 #${this.frameCount}: ${data.byteLength} bytes, 分辨率: ${img.width}x${img.height}`);
|
||||
}
|
||||
};
|
||||
img.onerror = () => {
|
||||
console.error('❌ 图片解码失败');
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
img.src = url;
|
||||
img.onload = () => {
|
||||
if (this.canvas.width !== img.width || this.canvas.height !== img.height) {
|
||||
this.canvas.width = img.width;
|
||||
this.canvas.height = img.height;
|
||||
}
|
||||
this.ctx.drawImage(img, 0, 0);
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
img.onerror = () => {
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
img.src = url;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 处理帧数据失败:', error);
|
||||
// 静默处理错误
|
||||
}
|
||||
},
|
||||
|
||||
@@ -147,8 +147,7 @@ export default {
|
||||
this.fpsTimer = null;
|
||||
}
|
||||
|
||||
// 清空 canvas
|
||||
if (this.ctx) {
|
||||
if (this.ctx && this.canvas) {
|
||||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user