· deepdives · 6 min read
Unleashing Creativity: How to Use the Shape Detection API for Interactive Art Projects
A practical guide to integrating the Shape Detection API into web-based art installations. Learn setup, code patterns, creative project ideas, performance optimizations, and privacy considerations to build interactive artworks that respond to faces, barcodes, and other detected shapes.

Why the Shape Detection API matters for interactive art
The Shape Detection API (an experimental set of browser APIs) lets web apps detect real-world features such as faces and barcodes directly from images or camera streams. For artists and creative technologists this is incredibly useful: instead of manually designing triggers, your artwork can react to people, objects, or printed markers in the environment.
Use cases in art installations:
- Reactive portraits that change style when a face is detected
- Generative visuals mapped to the position and expression of a viewer
- Barcode-triggered scenes or soundscapes in scavenger hunts
- Multi-user interactions where each detected face spawns a new particle system
Before building, note that the API is still considered experimental and has different levels of browser support. Always feature-detect and provide fallbacks. See the overview on MDN and web.dev for current compatibility notes: Shape Detection API - MDN, Shape Detection on web.dev.
Quick API primer
The Shape Detection suite includes detectors like BarcodeDetector and FaceDetector (availability varies by browser). The common flow is:
- Acquire image data (camera via
getUserMedia()or an image / canvas). - Instantiate a detector.
- Call
detect()on frames and get detection boxes/landmarks. - Map detections to visuals, sound, or interaction logic.
Useful references:
getUserMedia(camera): MDN getUserMediaBarcodeDetectordocs: MDN BarcodeDetectorOffscreenCanvasfor background rendering: MDN OffscreenCanvas
Minimal live webcam + detection loop (template)
Below is a compact pattern you can build from. It detects faces (if supported) on a live video feed and draws detection boxes on a canvas overlay.
// feature detection
const hasFaceDetector = 'FaceDetector' in window;
// acquire camera
const video = document.createElement('video');
video.autoplay = true;
video.playsInline = true; // for mobile
async function startCamera() {
const stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: 'user' },
audio: false,
});
video.srcObject = stream;
await video.play();
}
// create detector if available
let faceDetector;
if (hasFaceDetector) {
faceDetector = new FaceDetector({ fastMode: true, maxDetectedFaces: 4 });
}
const canvas = document.querySelector('#overlay');
const ctx = canvas.getContext('2d');
function resizeCanvasToVideo() {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
}
async function detectLoop() {
if (video.readyState >= 2) {
resizeCanvasToVideo();
// read image from video
if (faceDetector) {
try {
const faces = await faceDetector.detect(video);
// clear
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw and map visuals
faces.forEach(face => {
const { width, height, top, left } = face.boundingBox;
ctx.strokeStyle = 'rgba(0,255,200,0.9)';
ctx.lineWidth = 4;
ctx.strokeRect(left, top, width, height);
// spawn particles or modify shader uniforms here
// spawnParticlesAt(left + width/2, top + height/2, face.landmarks)
});
} catch (e) {
console.error('Detection error:', e);
}
}
}
requestAnimationFrame(detectLoop);
}
await startCamera();
requestAnimationFrame(detectLoop);Notes:
- Detection can be expensive. Use
fastModeand limitmaxDetectedFaceswhere supported. - Throttle detection frequency if full-frame every frame is unnecessary (e.g., run every 100ms).
Creative patterns - mapping detection to art
Below are patterns you can use to make the detection information produce expressive results.
Spatial influence: Map bounding box center to emitter positions. Each detected face spawns a particle emitter whose color, spread, and speed are based on face size (distance) and movement velocity.
Expression-driven style: If your face detector exposes landmarks (eyes, mouth), derive features like mouth openness or eye position to control brush size, filter intensity, or the amplitude of generative noise.
Marker-triggered scenes: Use
BarcodeDetectorto detect barcodes/QR codes printed on cards. Each code can map to a unique scene or audio loop. This is perfect for gallery interactions where visitors present printed tokens.Multi-user choreography: Track multiple faces and assign each a persistent identity (via spatial proximity over frames). Let each identity control separate layers of the composition.
Generative audio: Convert detection parameters (position, size, rotation) into MIDI/OSC messages to control external synths or WebAudio nodes for synchronous audio-visual pieces.
Example: Barcode-triggered scene switch
if ('BarcodeDetector' in window) {
const barcodeDetector = new BarcodeDetector({
formats: ['qr_code', 'ean_13'],
});
async function checkFrameForBarcode() {
const barcodes = await barcodeDetector.detect(video);
if (barcodes.length) {
// pick first barcode and use rawValue to switch scenes
const code = barcodes[0].rawValue;
activateSceneForCode(code);
}
}
setInterval(checkFrameForBarcode, 400); // throttle
}Performance and reliability tips
- Feature-detect and fallback: Not all browsers implement these detectors. Provide fallback strategies such as manual marker recognition via canvas pixel processing, or ML-based detection using TensorFlow.js or OpenCV.js.
- Use OffscreenCanvas in workers: Offload heavy drawing and detection pre-processing to a worker using
OffscreenCanvasto keep the UI responsive. See MDN OffscreenCanvas. - Reduce resolution: Run detection on a downsized copy of the frame; map results back to the full-size canvas.
- Throttle detection frequency: You rarely need 60 detections/sec for art. 6–15 fps is often fine.
- Limit concurrency: Keep
maxDetectedFaceslow and preferfastModeif available. - GPU-friendly drawing: When rendering complex visuals, use WebGL. Shaders can efficiently render particle systems driven by detection data.
Privacy, consent, and ethics
Face and camera-based interactions involve sensitive data. Follow best practices:
- Always ask for permission and explain how the camera feed will be used.
- Avoid sending raw camera data to remote servers unless strictly necessary; if you must, disclose it and secure transmission.
- If the installation stores or logs detection-derived data (e.g., counts, metadata), inform participants and give opt-out options.
- Consider on-device processing and ephemeral data retention.
Respect local laws and platform policies regarding biometric processing.
Advanced patterns and hybrids
- Combine Shape Detection with ARCore/ARKit WebXR when available for more accurate world understanding.
- Use detection outputs to drive shader uniforms in WebGL - for example, pass normalized bounding-box centers and sizes into fragment shaders to create face-indexed distortions.
- Hybrid ML: Use the Shape Detection API for light-weight detection and upgrade to a heavier ML model (TensorFlow.js) for advanced pose or expression recognition when needed.
Example project: “Reactive Portrait Wall” (step-by-step)
Idea: A gallery wall of portrait canvases that come alive when visitors stand in front of them. Each face detected spawns a painterly brushstroke effect and a resonant note.
Steps:
- Set up a multi-camera kiosk or a single wide-angle camera capturing the audience.
- Use
FaceDetectorto find faces and track bounding boxes over frames. - For each tracked face, instantiate a render layer (WebGL or canvas) and a WebAudio oscillator.
- Map face properties to visual parameters:
- Face size -> brush scale (distance)
- Movement velocity -> noise amplitude
- Mouth openness (if landmarks available) -> color saturation or audio filter
- Use a particle system for paint strokes; spawn particles on face movement.
- Provide a calibration mode so the artist can choose mapping ranges and color palettes.
This project scales well: a single camera can drive many virtual canvases using layer masks and individualized shader parameters.
Fallbacks and alternatives
If FaceDetector or BarcodeDetector aren’t available:
- Barcode fallback: use a client-side library like jsQR or
zxing-jsfor QR/barcode detection. - Face fallback: use TensorFlow.js models (e.g., BlazeFace / FaceMesh) or OpenCV.js for detection and landmarks.
Be honest in the UI: indicate when the platform supports a native detector vs. when a slower JS fallback is active.
Final recommendations and resources
- Prototype quickly using a small detector loop and incremental visuals. Detection outputs are best when used as expressive controls rather than precise measurements.
- Profile for performance early. Expensive detector calls and heavy drawing can quickly degrade interactivity.
- Document privacy behavior and provide visible controls to disable camera features.
Further reading and references:
- Shape Detection API - MDN: https://developer.mozilla.org/en-US/docs/Web/API/Shape_Detection_API
- BarcodeDetector - MDN: https://developer.mozilla.org/en-US/docs/Web/API/BarcodeDetector
- getUserMedia - MDN: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
- Shape Detection overview on web.dev: https://web.dev/shape-detection/
Happy building - let the people and objects in the real world become brushes and instruments in your next interactive artwork.



