背景
我正在使用Posenet(在此处查看浏览器演示here)进行关键点检测。我已经设置它在WebRTC MediaStream上运行,如下:
客户端:在机器A
的Chrome标签中运行。初始化WebRTC连接并将MediaStream发送到服务器。通过WebRTC的DataChannel实时从服务器接收关键点数据。
服务器:在机器B
的Chrome标签中运行,接收WebRTC流并将相应的MediaStream传递给Posenet。Posenet完成其任务并计算关键点。然后,通过WebRTC的DataChannel将此关键点数据发送回客户端(如果您有更好的想法,我会倾听)。
puppeteer
和Chrome的无头模式来抽象WebRTC的复杂性。
方法
我已经尝试了两种方法,其中我非常偏爱#2
:
方法 #1
在 puppeteer
上下文中运行 @tensorflow/tfjs
(即在无头 Chrome 标签页中)。但是,由于一些 WebGL 错误,我似乎无法让 PoseNet 浏览器演示 在无头模式下工作(尽管在非无头模式下可以工作)。我尝试了以下方法(将 args
传递给 puppeteer.launch()
以启用 WebGL,但我没有任何运气 - 参见 此处 和 此处):
const puppeteer = require('puppeteer');
async function main() {
const browser = await puppeteer.launch({
headless: true,
args: ['--enable-webgl-draft-extensions', '--enable-webgl-image-chromium', '--enable-webgl-swap-chain', '--enable-webgl2-compute-context']
});
const page = await browser.newPage();
await page.goto('https://storage.googleapis.com/tfjs-models/demos/posenet/camera.html', {
waitUntil: 'networkidle2'
});
// Make chromium console calls available to nodejs console
page.on('console', msg => {
for (let i = 0; i < msg.args().length; ++i)
console.log(`${i}: ${msg.args()[i]}`);
});
}
main();
在无头模式下,我收到了这个错误信息。
0: JSHandle:Initialization of backend webgl failed
0: JSHandle:Error: WebGL is not supported on this device
这让我面临一个问题:如何在
puppeteer
中启用WebGL?
方法二
最好的情况是,我想使用@tensorflow/tfjs-node
后端来运行posenet
,以加速计算。因此,我需要将puppeteer
和@tensorflow/tfjs-node
链接起来,使得:
puppeteer-chrome-tab
与客户端使用WebRTC通信,它使得一个Mediastream对象可用于node
。node
接收这个MediaStream并将其传递给posenet
(因此传递给了@tensorflow/tfjs-node
),机器学习魔法就发生了。然后,node
将检测到的关键点传回puppeteer-chrome-tab
,后者使用其RTCDataChannel
将它们传回客户端。
问题
问题在于我似乎无法在node
中访问puppeteer
的MediaStream对象,以将此对象传递给posenet
。我只能访问JSHandles
和ElementHandles
。是否有可能将与句柄相关联的javascript对象传递给node
?具体而言,抛出以下错误:
UnhandledPromiseRejectionWarning: Error: When running in node, pixels must be an HTMLCanvasElement like the one returned by the `canvas` npm package
at NodeJSKernelBackend.fromPixels (/home/work/code/node_modules/@tensorflow/tfjs-node/dist/nodejs_kernel_backend.js:1464:19)
at Engine.fromPixels (/home/work/code/node_modules/@tensorflow/tfjs-core/dist/engine.js:749:29)
at fromPixels_ (/home/work/code/node_modules/@tensorflow/tfjs-core/dist/ops/browser.js:85:28)
at Object.fromPixels (/home/work/code/node_modules/@tensorflow/tfjs-core/dist/ops/operation.js:46:29)
at toInputTensor (/home/work/code/node_modules/@tensorflow-models/posenet/dist/util.js:164:60)
at /home/work/code/node_modules/@tensorflow-models/posenet/dist/util.js:198:27
at /home/work/code/node_modules/@tensorflow/tfjs-core/dist/engine.js:349:22
at Engine.scopedRun (/home/work/code/node_modules/@tensorflow/tfjs-core/dist/engine.js:359:23)
at Engine.tidy (/home/work/code/node_modules/@tensorflow/tfjs-core/dist/engine.js:348:21)
at Object.tidy (/home/work/code/node_modules/@tensorflow/tfjs-core/dist/globals.js:164:28)
记录传递给NodeJSKernelBackend.prototype.fromPixels = function (pixels, numChannels) {..}
的pixels
参数,它被评估为ElementHandle。我知道可以使用puppeteer
的page.evaluate
访问Javascript对象的可序列化属性。但是,如果我想通过调用puppeteer.evaluate(..)
将CanvasRenderingContext2D
的imageData
(使用getImageData()
方法)传递给node
,这意味着需要对整个原始图像进行字符串化,然后在node
的上下文中重新构建它。
node
中访问(只读)来自puppeteer
上下文的对象,而不必通过例如puppeteer.evaluate(..)
的方式?