Skip to content

Commit c5f2f0b

Browse files
eehakkinjan-ivar
andauthored
Convert to spec example
Co-authored-by: Jan-Ivar Bruaroey <[email protected]>
1 parent 2b26f8b commit c5f2f0b

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
@@ -2031,48 +2031,57 @@ <h4>Members</h4>
20312031
<section>
20322032
<h3>Example</h3>
20332033
<pre class="example">
2034+
// main.js:
20342035
// Open camera.
20352036
const stream = await navigator.mediaDevices.getUserMedia({video: true});
2036-
const [videoTrack] = stream.getVideoTracks();
2037+
const [track] = stream.getVideoTracks();
2038+
// Do video processing in a worker.
2039+
const worker = new Worker('worker.js');
2040+
worker.postMessage({track}, [track]);
2041+
const {data} = await new Promise(result => worker.onmessage = result);
2042+
const videoElement = document.querySelector('video');
2043+
videoElement.srcObject = new MediaStream([data.track]);
20372044

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

2047-
const canvasContext = document.querySelector('canvas').getContext('2d');
2048-
const videoProcessor = new MediaStreamTrackProcessor({track: videoTrack});
2049-
const videoProcessorReader = videoProcessor.readable.getReader();
2059+
const canvas = new OffscreenCanvas(640, 480);
2060+
const context = canvas.getContext('2d', {desynchronized: true});
20502061

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

0 commit comments

Comments
 (0)