Claude Skills Guide

Building a Chrome extension to adjust webcam settings opens up powerful possibilities for developers and power users who need fine-grained control over their camera inputs. While modern video conferencing platforms provide basic settings, they rarely offer the depth of control that professionals require. This guide walks you through creating a functional webcam settings adjuster extension using the MediaDevices API and Chrome’s extension capabilities.

Understanding the Webcam Access API

Chrome provides access to webcam and microphone through the MediaDevices API, part of the WebRTC specification. Before building your extension, you need to understand how to enumerate devices and request media streams with specific constraints.

The core method for accessing the webcam is navigator.mediaDevices.getUserMedia(). This method accepts a constraints object that lets you specify resolution, frame rate, and device selection. For a settings adjuster, you’ll need to work with both the constraints and the underlying track settings.

Here’s how to request a basic video stream:

async function getWebcamStream() {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: {
        width: { ideal: 1280 },
        height: { ideal: 720 },
        frameRate: { ideal: 30 }
      }
    });
    return stream;
  } catch (error) {
    console.error('Webcam access denied:', error);
    throw error;
  }
}

Enumerating Available Devices

Before adjusting settings, your extension should discover all available video input devices. The navigator.mediaDevices.enumerateDevices() method returns an array of MediaDeviceInfo objects.

async function getVideoDevices() {
  const devices = await navigator.mediaDevices.enumerateDevices();
  return devices.filter(device => device.kind === 'videoinput');
}

This returns devices with properties like deviceId, label, and groupId. The label property only populates after user permission has been granted, so you’ll need to request camera access before displaying meaningful device names.

Implementing Real-Time Settings Adjustment

The MediaStreamTrack object exposes applyConstraints() method, which allows dynamic adjustment of video properties without restarting the stream. This is the foundation of your settings adjuster.

async function adjustBrightness(track, value) {
  // Brightness is typically handled via CSS filters on the video element
  const videoElement = document.getElementById('preview');
  videoElement.style.filter = `brightness(${value})`;
}

async function applyVideoConstraints(track, constraints) {
  try {
    await track.applyConstraints(constraints);
    return true;
  } catch (error) {
    console.error('Constraint application failed:', error);
    return false;
  }
}

Note that not all constraints are supported across all devices. Chrome handles certain adjustments like brightness and contrast through CSS filters on the video element itself, while others like resolution and frame rate go through the track constraints.

Building the Extension Popup UI

Your extension needs a popup interface for users to adjust settings. Create a popup.html with sliders for various parameters:

<!DOCTYPE html>
<html>
<head>
  <style>
    body { width: 320px; padding: 16px; font-family: system-ui; }
    .control-group { margin-bottom: 16px; }
    label { display: block; margin-bottom: 4px; font-weight: 500; }
    input[type="range"] { width: 100%; }
    .value-display { float: right; font-weight: normal; }
  </style>
</head>
<body>
  <h2>Webcam Settings</h2>
  
  <div class="control-group">
    <label>Brightness <span id="brightness-val" class="value-display">100%</span></label>
    <input type="range" id="brightness" min="50" max="150" value="100">
  </div>
  
  <div class="control-group">
    <label>Contrast <span id="contrast-val" class="value-display">100%</span></label>
    <input type="range" id="contrast" min="50" max="150" value="100">
  </div>
  
  <div class="control-group">
    <label>Resolution</label>
    <select id="resolution">
      <option value="640x480">640 x 480</option>
      <option value="1280x720" selected>1280 x 720</option>
      <option value="1920x1080">1920 x 1080</option>
    </select>
  </div>
  
  <video id="preview" autoplay playsinline style="width: 100%;"></video>
  
  <script src="popup.js"></script>
</body>
</html>

Managing Background Processing

For a truly useful extension, consider implementing a background script that can apply settings to any page using the webcam. This requires the activeTab and scripting permissions in your manifest.

// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'applySettings') {
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      chrome.tabs.sendMessage(tabs[0].id, {
        type: 'UPDATE_FILTERS',
        settings: message.settings
      });
    });
  }
});

The content script then listens for these messages and applies CSS filters to all video elements on the page:

// content.js
chrome.runtime.onMessage.addListener((message) => {
  if (message.type === 'UPDATE_FILTERS') {
    const videos = document.querySelectorAll('video');
    const filterString = `brightness(${message.settings.brightness}%) 
                          contrast(${message.settings.contrast}%)`;
    videos.forEach(video => {
      video.style.filter = filterString;
    });
  }
});

Extension Manifest Configuration

Your manifest.json needs appropriate permissions to access the webcam and inject scripts:

{
  "manifest_version": 3,
  "name": "Webcam Settings Adjuster",
  "version": "1.0",
  "permissions": [
    "activeTab",
    "scripting",
    "navigator.mediaDevices"
  ],
  "host_permissions": [
    "<all_urls>"
  ],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "48": "icon.png"
    }
  }
}

Handling Device Changes

Users frequently connect and disconnect webcams. Your extension should listen for device change events to maintain functionality:

navigator.mediaDevices.ondevicechange = async (event) => {
  const devices = await navigator.mediaDevices.enumerateDevices();
  const videoDevices = devices.filter(d => d.kind === 'videoinput');
  console.log('Available cameras:', videoDevices.length);
  
  // Notify user or update UI accordingly
  chrome.runtime.sendMessage({
    action: 'devicesChanged',
    devices: videoDevices.map(d => d.label)
  });
};

Limitations and Browser Support

Not all webcam settings can be controlled programmatically. Most consumer webcatches support resolution and frame rate adjustments through constraints, but advanced features like manual focus, white balance, and exposure compensation vary significantly between devices. The CSS filter approach for brightness and contrast provides consistent results across all browsers since it processes the rendered video output rather than the raw camera stream.

Chrome’s implementation of the MediaDevices API is more complete than Firefox or Safari, making it the ideal target for this type of extension. Always provide fallback controls or clear messaging when certain features are unavailable.

Building a webcam settings adjuster demonstrates the intersection of extension development and web APIs. The techniques covered here—MediaDevices enumeration, constraint application, CSS video filtering, and cross-context messaging—apply broadly to other camera-related projects.

Built by theluckystrike — More at zovo.one