如何检测何时不支持 `canvas.captureStream()`?
How to detect when `canvas.captureStream()` is not supported?
It is known that iOS Safari does not support canvas.captureStream()
to (e.g.) pipe its content into a video element, see this demo 在 iOS Safari 中不工作。
但是,canvas.captureStream()
在 iOS Safari 中是一个有效的功能,正确地 returns 和 CanvasCaptureMediaStreamTrack
,它只是没有按预期运行。为了检测不支持 canvas.captureStream
的浏览器,做一个测试 typeof canvas.captureStream === 'function'
很容易,但至少对于 iOS Safari,我们不能依赖它。我们也不能依赖返回值的类型。
如何写JavaScript检测当前浏览器是否有效支持canvas.captureStream()
?
没有 iOS 在这里测试它,但根据对您链接到的问题的评论,captureStream()
实际上有效,HTMLVideoElement 对该 MediaStream 的读取无效。这就是您真正想要测试的内容。
根据那里的消息,视频甚至 都不会 加载视频(即元数据设置正确,我不希望发生 [=13 这样的事件=] 触发,但如果触发,那么测试就非常简单:检查视频是否能够播放这样的 MediaStream。
function testReadingOfCanvasCapturedStream() {
// first check the DOM API is available
if( !testSupportOfCanvasCapureStream() ) {
return Promise.resolve(false);
}
// create a test canvas
const canvas = document.createElement("canvas");
// we need to init a context on the canvas
const ctx = canvas.getContext("2d");
const stream = canvas.captureStream();
const vid = document.createElement("video");
vid.muted = true;
vid.playsInline = true;
vid.srcObject = stream;
let supports = false;
// Safari needs we draw on the canvas
// asynchronously after we requested the MediaStream
setTimeout(() => ctx.fillRect(0,0,5,5));
// if it failed, .play() would be enough
// but according to the comments on the issue, it isn't
return vid.play()
.then(() => supports = true)
.finally(() => {
// clean
stream.getTracks().forEach(track => track.stop());
return supports;
});
}
function testSupportOfCanvasCapureStream() {
return "function" === typeof HTMLCanvasElement.prototype.captureStream;
}
testReadingOfCanvasCapturedStream()
.then(supports => console.log(supports));
但是如果视频可以播放,但是没有画图,那我们就得再深入一点,看看视频画了什么。为此,我们将在 canvas 上绘制一些颜色,等待视频加载并在 canvas 上重新绘制,然后再检查 canvas 上的框架颜色:
async function testReadingOfCanvasCapturedStream() {
// first check the DOM API is available
if( !testSupportOfCanvasCapureStream() ) {
return false;
}
// create a test canvas
const canvas = document.createElement("canvas");
// we need to init a context on the canvas
const ctx = canvas.getContext("2d");
const stream = canvas.captureStream();
const clean = () => stream.getTracks().forEach(track => track.stop());
const vid = document.createElement("video");
vid.muted = true;
vid.srcObject = stream;
// Safari needs we draw on the canvas
// asynchronously after we requested the MediaStream
setTimeout(() => {
// we draw in a well knwown color
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0,300,150);
});
try {
await vid.play();
}
catch(e) {
// failed to load, no need to go deeper
// it's not supported
clean();
return false;
}
// here we should have our canvas painted on the video
// let's keep this image on the video
await vid.pause();
// now draw it back on the canvas
ctx.clearRect(0,0,300,150);
ctx.drawImage(vid,0,0);
const pixel_data = ctx.getImageData(5,5,1,1).data;
const red_channel = pixel_data[0];
clean();
return red_channel > 0; // it has red
}
function testSupportOfCanvasCapureStream() {
return "function" === typeof HTMLCanvasElement.prototype.captureStream;
}
testReadingOfCanvasCapturedStream()
.then(supports => console.log(supports));
It is known that iOS Safari does not support canvas.captureStream()
to (e.g.) pipe its content into a video element, see this demo 在 iOS Safari 中不工作。
但是,canvas.captureStream()
在 iOS Safari 中是一个有效的功能,正确地 returns 和 CanvasCaptureMediaStreamTrack
,它只是没有按预期运行。为了检测不支持 canvas.captureStream
的浏览器,做一个测试 typeof canvas.captureStream === 'function'
很容易,但至少对于 iOS Safari,我们不能依赖它。我们也不能依赖返回值的类型。
如何写JavaScript检测当前浏览器是否有效支持canvas.captureStream()
?
没有 iOS 在这里测试它,但根据对您链接到的问题的评论,captureStream()
实际上有效,HTMLVideoElement 对该 MediaStream 的读取无效。这就是您真正想要测试的内容。
根据那里的消息,视频甚至 都不会 加载视频(即元数据设置正确,我不希望发生 [=13 这样的事件=] 触发,但如果触发,那么测试就非常简单:检查视频是否能够播放这样的 MediaStream。
function testReadingOfCanvasCapturedStream() {
// first check the DOM API is available
if( !testSupportOfCanvasCapureStream() ) {
return Promise.resolve(false);
}
// create a test canvas
const canvas = document.createElement("canvas");
// we need to init a context on the canvas
const ctx = canvas.getContext("2d");
const stream = canvas.captureStream();
const vid = document.createElement("video");
vid.muted = true;
vid.playsInline = true;
vid.srcObject = stream;
let supports = false;
// Safari needs we draw on the canvas
// asynchronously after we requested the MediaStream
setTimeout(() => ctx.fillRect(0,0,5,5));
// if it failed, .play() would be enough
// but according to the comments on the issue, it isn't
return vid.play()
.then(() => supports = true)
.finally(() => {
// clean
stream.getTracks().forEach(track => track.stop());
return supports;
});
}
function testSupportOfCanvasCapureStream() {
return "function" === typeof HTMLCanvasElement.prototype.captureStream;
}
testReadingOfCanvasCapturedStream()
.then(supports => console.log(supports));
但是如果视频可以播放,但是没有画图,那我们就得再深入一点,看看视频画了什么。为此,我们将在 canvas 上绘制一些颜色,等待视频加载并在 canvas 上重新绘制,然后再检查 canvas 上的框架颜色:
async function testReadingOfCanvasCapturedStream() {
// first check the DOM API is available
if( !testSupportOfCanvasCapureStream() ) {
return false;
}
// create a test canvas
const canvas = document.createElement("canvas");
// we need to init a context on the canvas
const ctx = canvas.getContext("2d");
const stream = canvas.captureStream();
const clean = () => stream.getTracks().forEach(track => track.stop());
const vid = document.createElement("video");
vid.muted = true;
vid.srcObject = stream;
// Safari needs we draw on the canvas
// asynchronously after we requested the MediaStream
setTimeout(() => {
// we draw in a well knwown color
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0,300,150);
});
try {
await vid.play();
}
catch(e) {
// failed to load, no need to go deeper
// it's not supported
clean();
return false;
}
// here we should have our canvas painted on the video
// let's keep this image on the video
await vid.pause();
// now draw it back on the canvas
ctx.clearRect(0,0,300,150);
ctx.drawImage(vid,0,0);
const pixel_data = ctx.getImageData(5,5,1,1).data;
const red_channel = pixel_data[0];
clean();
return red_channel > 0; // it has red
}
function testSupportOfCanvasCapureStream() {
return "function" === typeof HTMLCanvasElement.prototype.captureStream;
}
testReadingOfCanvasCapturedStream()
.then(supports => console.log(supports));