WebCodecs Codec Support Testing Methodology

Sam Bhattacharyya
Sam Bhattacharyya January 15, 2025
Research

Overview

The codec compatibility dataset powering WebCodecs Fundamentals is collected through real-world browser testing across thousands of users visiting free.upscaler.video. This page documents the complete methodology for data collection, processing, and publication to enable reproducibility and independent verification by standards bodies and academic researchers.

Current Dataset Version: 1.0 (encode support only) Collection Period: January 2–14, 2026 Version 2.0 Status: In progress (adds decode support testing)

Data Collection Method

Background Testing

When users visit free.upscaler.video, a lightweight background worker silently tests codec support:

View Testing Implementation Code
/**
 * Test a single video codec string for both encode AND decode support
 */
async function testCodec(codecString) {
    try {
        if (!self.VideoEncoder || !self.VideoDecoder) {
            return {
                string: codecString,
                supported: false,
                encode: false,
                decode: false,
                error: 'WebCodecs not available'
            };
        }

        const encodeConfig = {
            codec: codecString,
            width: 640,
            height: 360,
            bitrate: 500000,
            framerate: 30
        };

        const decodeConfig = {
            codec: codecString
        };

        // Test both encode and decode
        const [encodeResult, decodeResult] = await Promise.all([
            self.VideoEncoder.isConfigSupported(encodeConfig),
            self.VideoDecoder.isConfigSupported(decodeConfig)
        ]);

        const encodeSupported = encodeResult.supported || false;
        const decodeSupported = decodeResult.supported || false;

        return {
            string: codecString,
            supported: encodeSupported,  // Backward compat
            encode: encodeSupported,
            decode: decodeSupported
        };
    } catch (error) {
        return {
            string: codecString,
            supported: false,
            encode: false,
            decode: false,
            error: error.message
        };
    }
}

/**
 * Test a single audio codec string for both encode AND decode support
 */
async function testAudioCodec(codecString) {
    try {
        if (!self.AudioEncoder || !self.AudioDecoder) {
            return {
                string: codecString,
                supported: false,
                encode: false,
                decode: false,
                error: 'AudioEncoder/AudioDecoder not available'
            };
        }

        const encodeConfig = {
            codec: codecString,
            numberOfChannels: 2,
            sampleRate: 44100
        };

        const decodeConfig = {
            codec: codecString,
            numberOfChannels: 2,
            sampleRate: 44100,
            description: new Uint8Array(20)
        };

        const [encodeResult, decodeResult] = await Promise.all([
            self.AudioEncoder.isConfigSupported(encodeConfig),
            self.AudioDecoder.isConfigSupported(decodeConfig)
        ]);

        const encodeSupported = encodeResult.supported || false;
        const decodeSupported = decodeResult.supported || false;

        return {
            string: codecString,
            supported: encodeSupported,  // Backward compat
            encode: encodeSupported,
            decode: decodeSupported
        };
    } catch (error) {
        return {
            string: codecString,
            supported: false,
            encode: false,
            decode: false,
            error: error.message
        };
    }
}

// Results submitted to collection API (URL not disclosed for security)

Codec String Generation

The 1,087 codec strings tested are programmatically generated based on official codec specifications, ensuring comprehensive coverage of real-world variants.

Generation Method:

Each codec family has a dedicated generator that produces all valid codec strings according to their respective specifications:

Audio Codecs (18 total): Based on the W3C WebCodecs Audio Codec Registry

The generators are combined via generate-codec-list.js to produce the canonical list used in testing.

Codec Families Tested

Video Codecs (1,069 total):

Audio Codecs (18 total):

Download Full List:

Test Configuration

Each codec is tested with standardized parameters:

Video Encode:

{
  codec: codecString,
  width: 640,
  height: 360,
  bitrate: 500000,
  framerate: 30
}

Resolution Selection Rationale: 360p (640×360) was chosen as a conservative baseline that fits within the constraints of all tested codec levels. While a more comprehensive approach would test multiple resolutions, we assume that if a codec variant is supported, 360p will not exceed its capabilities. This assumption is reasonable because:

Video Decode:

{
  codec: codecString
}

Audio Encode:

{
  codec: codecString,
  numberOfChannels: 2,
  sampleRate: 44100
}

Audio Decode:

{
  codec: codecString,
  numberOfChannels: 2,
  sampleRate: 44100,
  description: new Uint8Array(20)  // Required for certain codecs
}

Audio Description Field: Some audio codecs (notably Vorbis and FLAC) require a description field in the decoder configuration for proper testing. A dummy 20-byte Uint8Array is provided to all audio decode tests to satisfy this requirement. While this doesn’t represent actual codec-specific data, it allows the isConfigSupported() API to correctly determine whether the browser supports the codec string.

Data Submitted

Each test session submits:

Test Metadata:

Results per Codec:

Sample Payload

{
  "testMetadata": {
    "timestamp": "2025-01-16T12:34:56.789Z",
    "userAgent": "Mozilla/5.0...",
    "browser": "Chrome",
    "platform": "Win32",
    "source": "free-upscaler-background"
  },
  "results": [
    {
      "string": "avc1.420034",
      "supported": true,
      "encode": true,
      "decode": true
    },
    {
      "string": "av01.0.08M.08",
      "supported": false,
      "encode": false,
      "decode": true
    }
    // ... 300+ more results
  ]
}

Data Processing Pipeline

The complete data pipeline from collection to publication consists of five stages:

1. Client-Side Collection

Each test session generates a JSON payload containing:

Payloads are submitted via HTTP POST to the collection API endpoint.

2. Server-Side Storage

The collection API receives submissions and:

Implementation Note: For convenience and cost efficiency, the data collection uses the backend infrastructure and S3 storage from the author’s commercial product (katana.video).

Storage format: Individual JSON files per session, stored as:

s3://bucket/codec-test-results/YYYY-MM-DD/timestamp_uuid.json

3. Local Synchronization

Test result files are synced from S3 to local storage for batch processing:

aws s3 sync s3://bucket/codec-test-results/ ./s3-results/

This creates a local mirror of all test sessions in the s3-results/ directory.

4. Aggregation and Analysis

Multiple Python scripts process the synchronized data:

a. Raw CSV Generation (generate-csv.py)

b. Statistical Aggregation (aggregate-codecs.py)

c. Platform Normalization

Raw platform identifiers from navigator.platform are normalized:

{
  'Win32': 'Windows', 'Win64': 'Windows',
  'MacIntel': 'macOS',
  'iPhone': 'iOS', 'iPad': 'iOS',
  'Linux armv8l': 'Android', 'Android': 'Android',
  'Linux x86_64': 'Linux'
}

5. Publication

a. Interactive Codec Registry (generate-registry-page.py)

b. Individual Codec Pages (generate-codec-pages.py)

c. Dataset Download Package

Dataset Statistics

As of the latest update:

Privacy & Ethics

Backward Compatibility

The dataset maintains backward compatibility:

Limitations

Questions?

For questions about the methodology or dataset, please open an issue or contact sam@webcodecsfundamentals.org.