WebCodecs Codec Support Testing Methodology
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:
- Runs after 50ms delay - Ensures no impact on page load performance
- Tests in Web Worker - Completely off the main thread
- 300 random video codecs - Sampled from 1,087 total codec variants
- All 18 audio codecs - Complete coverage of common audio formats
- Both encode and decode - Tests
VideoEncoder,VideoDecoder,AudioEncoder, andAudioDecoder
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:
-
H.264/AVC - RFC 6381 format:
avc1.{profile}{constraint}{level}- 3 profiles (Baseline, Main, High)
- 6 constraint set flags
- 19 levels (1.0 to 6.2)
- Total: 342 variants
-
HEVC/H.265 - ISO/IEC 14496-15 format:
hvc1/hev1.{profile}.{tier}{level}.{constraints}- 2 profiles (Main, Main10)
- 2 tiers (Main, High)
- 21 levels
- Total: 84 variants
-
VP9 - VP9 Codec RFC format:
vp09.{profile}.{level}.{bitDepth}.{chromaSubsampling}- 4 profiles (0-3)
- 7 levels
- Bit depths and chroma subsampling variations
- Total: 210 variants
-
AV1 - AV1 ISOBMFF format:
av01.{profile}.{level}{tier}.{bitDepth}- 3 profiles (Main, High, Professional)
- 24 levels (2.0 to 7.3)
- 2 tiers (Main, High)
- 3 bit depths (8, 10, 12 bit)
- Total: 432 variants
-
VP8 - Simple
vp8identifier- Total: 1 variant
Audio Codecs (18 total): Based on the W3C WebCodecs Audio Codec Registry
-
AAC - MPEG-4 AAC format:
mp4a.40.{objectType}- AAC-LC (mp4a.40.2, mp4a.40.02)
- HE-AAC (mp4a.40.5, mp4a.40.05)
- HE-AACv2 (mp4a.40.29)
- Total: 6 variants
-
PCM - Uncompressed audio
- pcm-u8, pcm-s16, pcm-s24, pcm-s32, pcm-f32
- Total: 5 variants
-
Single-variant codecs: opus, mp3, flac, vorbis, alaw (mp4a.69), ulaw (mp4a.6B)
- Total: 7 codecs
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):
- H.264/AVC - 342 variants
- HEVC/H.265 - 84 variants
- VP8 - 1 variant
- VP9 - 210 variants
- AV1 - 432 variants
Audio Codecs (18 total):
- MP4A (AAC-LC, HE-AAC), Opus, MP3, FLAC, Vorbis, PCM variants, μ-law, A-law
Download Full List:
- codec-list.csv - Machine-readable CSV format (1,087 codecs)
- codec-list.txt - Human-readable text format with categorization
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:
- The lowest H.264 level tested (Level 1.0) supports resolutions far below 360p
- Higher levels (which constitute the majority of variants) support significantly larger resolutions
- No modern codec implementation should support a variant but fail at 360p
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:
- Timestamp (ISO 8601)
- User Agent string
- Browser name (Chrome, Safari, Firefox, Edge)
- Platform (Windows, macOS, Linux, Android, iOS)
- Source identifier (
'free-upscaler-background')
Results per Codec:
- Codec string
- Encode support (boolean)
- Decode support (boolean)
- Error message (if unsupported)
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:
- Test metadata (timestamp, user agent, browser, platform, source identifier)
- Individual codec test results (codec string, encode support, decode support, error messages)
Payloads are submitted via HTTP POST to the collection API endpoint.
2. Server-Side Storage
The collection API receives submissions and:
- Validates payload structure (
testMetadataandresultsarray) - Generates unique identifiers (UUID v4)
- Organizes by date hierarchy (YYYY-MM-DD folder structure)
- Uploads to AWS S3 with AES-256 server-side encryption
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)
- Flattens all test sessions into individual rows (one row per codec test)
- Output:
upscaler-video-codec-dataset-raw.csv(8.5 GB, 45.5M rows) - Schema:
timestamp, user_agent, browser, platform_raw, platform, codec, supported
b. Statistical Aggregation (aggregate-codecs.py)
- Calculates support statistics across three dimensions:
- Global: Overall support percentage across all sessions
- By Browser: Support broken down by browser family (Chrome, Safari, Firefox, Edge)
- By Platform: Support broken down by OS (Windows, macOS, iOS, Android, Linux)
- By Combination: Support for each browser+platform pair (e.g., “Chrome+Windows”)
- Categorizes codecs into families (AVC, HEVC, VP8, VP9, AV1, Audio)
- Output: Individual JSON files per codec and per family in
aggregated/directory
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)
- Generates markdown table with all 1,087 tested codecs
- Color-codes support levels (green: >90%, yellow: 60-90%, red: <60%)
- Published at webcodecsfundamentals.org/datasets/codec-support-table
b. Individual Codec Pages (generate-codec-pages.py)
- Creates detailed support matrices for each codec string
- Shows browser-platform combinations in tabular format
- Published at
webcodecsfundamentals.org/codecs/[codec-string].html
c. Dataset Download Package
- Raw CSV file compressed to ZIP (8.5 GB → 257 MB)
- Includes README.txt with schema documentation
- Published at webcodecsfundamentals.org/upscaler-video-codec-dataset.zip
Dataset Statistics
As of the latest update:
- 45.5+ million codec tests
- 143,000+ unique user sessions
- 1,087 unique codec variants
- 5 major browsers (Chrome, Safari, Firefox, Edge, others)
- 5 platforms (Windows, macOS, Linux, Android, iOS)
Privacy & Ethics
- Fully anonymous - No user identification or tracking
- Silent operation - Zero UI impact
- Minimal resource usage - ~30 kB data transfer
- Open methodology - This page documents our exact approach
Backward Compatibility
The dataset maintains backward compatibility:
- Legacy records -
supportedfield = encode support only - Modern records - Separate
encodeanddecodefields - Graceful degradation - Processing scripts handle both formats
Limitations
- Sample bias - Users of free video tools may skew toward modern browsers
- Random sampling - Each session tests different 300 codecs (not all 1,087)
- WebCodecs only - Doesn’t test MediaRecorder or other encoding APIs
- No hardware detection - Can’t distinguish GPU-accelerated vs software encoding
Questions?
For questions about the methodology or dataset, please open an issue or contact sam@webcodecsfundamentals.org.