Skip to content

Commit 7be8095

Browse files
eehakkinjan-ivar
andcommitted
Convert to spec example
Co-authored-by: Jan-Ivar Bruaroey <[email protected]>
1 parent 38d351b commit 7be8095

File tree

1 file changed

+46
-37
lines changed

1 file changed

+46
-37
lines changed

index.html

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2029,48 +2029,57 @@ <h4>Members</h4>
20292029
<section>
20302030
<h3>Example</h3>
20312031
<pre class="example">
2032+
// main.js:
20322033
// Open camera.
20332034
const stream = await navigator.mediaDevices.getUserMedia({video: true});
2034-
const [videoTrack] = stream.getVideoTracks();
2035+
const [track] = stream.getVideoTracks();
2036+
// Do video processing in a worker.
2037+
const worker = new Worker('worker.js');
2038+
worker.postMessage({track}, [track]);
2039+
const {data} = await new Promise(result => worker.onmessage = result);
2040+
const videoElement = document.querySelector('video');
2041+
videoElement.srcObject = new MediaStream([data.track]);
20352042

2036-
// Try to enable background segmentation mask.
2037-
const videoCapabilities = videoTrack.getCapabilities();
2038-
if ((videoCapabilities.backgroundSegmentationMask || []).includes(true)) {
2039-
await videoTrack.applyConstraints({backgroundSegmentationMask: {exact: true}});
2040-
} else {
2041-
// Background segmentation mask is not supported by the platform or
2042-
// by the camera. Consider falling back to some other method.
2043-
}
2043+
// worker.js:
2044+
onmessage = async ({data: {track}}) => {
2045+
// Try to enable background segmentation mask.
2046+
const capabilities = track.getCapabilities();
2047+
if (capabilities.backgroundSegmentationMask?.includes(true)) {
2048+
await track.applyConstraints({backgroundSegmentationMask: {exact: true}});
2049+
} else {
2050+
// Background segmentation mask is not supported by the platform or
2051+
// by the camera. Consider falling back to some other method.
2052+
}
2053+
const trackGenerator = new VideoTrackGenerator();
2054+
self.postMessage({track: trackGenerator.track}, [trackGenerator.track]);
2055+
const {readable} = new MediaStreamTrackProcessor({track});
20442056

2045-
const canvasContext = document.querySelector('canvas').getContext('2d');
2046-
const videoProcessor = new MediaStreamTrackProcessor({track: videoTrack});
2047-
const videoProcessorReader = videoProcessor.readable.getReader();
2057+
const canvas = new OffscreenCanvas(640, 480);
2058+
const context = canvas.getContext('2d', {desynchronized: true});
20482059

2049-
for (;;) {
2050-
const {done, value: videoFrame} = await videoProcessorReader.read();
2051-
if (done)
2052-
break;
2053-
const {backgroundSegmentationMask} = videoFrame.metadata();
2054-
if (backgroundSegmentationMask) {
2055-
// Draw the video frame.
2056-
canvasContext.globalCompositeOperation = 'copy';
2057-
context.drawImage(videoFrame, 0, 0);
2058-
// Draw (or multiply with) the mask.
2059-
// The result is the foreground on black.
2060-
context.globalCompositeOperation = 'multiply';
2061-
canvasContext.drawImage(backgroundSegmentationMask, 0, 0);
2062-
}
2063-
else {
2064-
// Everything is background. Fill with black.
2065-
canvasContext.globalCompositeOperation = 'copy';
2066-
canvasContext.fillStyle = 'black';
2067-
canvasContext.fillRect(
2068-
0,
2069-
0,
2070-
canvasContext.canvas.width,
2071-
canvasContext.canvas.height);
2072-
}
2073-
}
2060+
const transformer = new TransformStream({
2061+
async transform(frame, controller) {
2062+
const {backgroundSegmentationMask} = frame.metadata();
2063+
if (backgroundSegmentationMask) {
2064+
// Draw the video frame.
2065+
context.globalCompositeOperation = 'copy';
2066+
context.drawImage(frame, 0, 0);
2067+
// Draw (or multiply with) the mask.
2068+
// The result is the foreground on black.
2069+
context.globalCompositeOperation = 'multiply';
2070+
context.drawImage(backgroundSegmentationMask, 0, 0);
2071+
} else {
2072+
// Everything is background. Fill with black.
2073+
context.globalCompositeOperation = 'copy';
2074+
context.fillStyle = 'black';
2075+
context.fillRect(0, 0, canvas.width, canvas.height);
2076+
}
2077+
controller.enqueue(new VideoFrame(canvas, {timestamp: frame.timestamp}));
2078+
frame.close();
2079+
}
2080+
});
2081+
await readable.pipeThrough(transformer).pipeTo(trackGenerator.writable);
2082+
};
20742083
</pre>
20752084
</section>
20762085
</section>

0 commit comments

Comments
 (0)