Open-Source Video Quality of Experience (QoE) Monitoring Platform
Production-grade video quality monitoring for web video players with comprehensive business and technical metrics, accurate percentile calculations, real-time alerting, and distributed tracing.
Guarantee of p90 request latency of <=30ms for event insgestion under any load
- Overview
- Features
- Architecture
- Quick Start
- Documentation
- Deployment Options
- Metrics & Dashboards
- Contributing
- License
- Support
OpenQoE is a complete, production-ready observability platform for video streaming that helps you:
- Monitor Quality: Track video startup time, rebuffering, errors, and playback quality
- Understand Engagement: Measure watch time, completion rates, and viewer behavior
- Optimize Performance: Identify bottlenecks with P50/P95/P99 percentile analysis
- Alert Proactively: Get notified when quality degrades or business metrics drop
- Scale Globally: Deploy on Cloudflare's edge network or self-host
| Component | Description | Status |
|---|---|---|
| JavaScript SDK | 5 player adapters capturing 24+ event types | β Dash.js Ready / ποΈ Others WIP |
| Go Worker | High-performance OTLP ingestion & processing | β Production Ready |
| Grafana Alloy | Edge telemetry collector & processor | β Production Ready |
| Grafana Dashboards | 4 comprehensive dashboards (58 panels total) | β Production Ready |
| Recording Rules | 25 pre-aggregated metrics for performance | β Production Ready |
| Alert Rules | 18 production-ready alerts | β Production Ready |
| Distributed Tracing | End-to-end tracing with Grafana Tempo | β Production Ready |
| Docker Stack | Self-hosted Mimir + Loki + Tempo + Alloy | β Production Ready |
- β Multi-Player Support: HTML5, Video.js, HLS.js, Dash.js, Shaka Player
- β Dash.js Production Ready: Robust integration for MPEG-DASH
- ποΈ WIP Adapters: Other players are in active development
- β Comprehensive Events: 24+ event types with full context capture
- β Privacy-First: SHA-256 hashing, configurable PII controls
- β Lightweight: ~10KB gzipped per adapter
- β TypeScript: Full type definitions included
- β OTLP Ingestion: Native support for OpenTelemetry protocol
- β High Concurrency: Built with Go for scalable event processing
- β Cardinality Governance: Automatic high-cardinality dimension management
- β Dual Destinations: Self-hosted or Grafana Cloud
- β Health Monitoring: Integrated health and stats endpoints
- β Full OTLP Pipeline: Alloy -> Mimir/Loki/Tempo
- β Distributed Tracing: End-to-end visibility with Tempo
- β 4 Production Dashboards: VOD, Live, Quality, Impact Explorer
- β 18 Alert Rules: Critical quality and performance alerts
- β Self-Hosted: Complete Docker Compose stack (Mimir, Loki, Tempo, Alloy, Grafana)
graph TD
subgraph "Your Application"
SDK[OpenQoE SDK]
P1["Dash.js,HLS.js, HTML5 - Ready"]
P2["Others - WIP"]
P1 -.-> SDK
P2 -.-> SDK
end
SDK -- "HTTPS POST /v2/events" --> Worker[Go Worker]
subgraph "Observability Pipeline"
Worker -- "OTLP" --> Alloy[Grafana Alloy]
Alloy -- "Metrics" --> Mimir[Grafana Mimir]
Alloy -- "Logs" --> Loki[Grafana Loki]
Alloy -- "Traces" --> Tempo[Grafana Tempo]
end
subgraph "Visualization"
Mimir --- Grafana[Grafana]
Loki --- Grafana
Tempo --- Grafana
end
Flow:
- SDK captures events from video players (Dash.js production ready)
- Events batched and sent to Go Worker (
/v2/events) - Worker validates and forwards via OTLP to Grafana Alloy
- Alloy routes data to Mimir (metrics), Loki (logs), and Tempo (traces)
- Grafana visualizes with pre-built dashboards and unified observability
git clone https://github.com/openqoe/openqoe-dev.git
cd openqoe-dev# Start Mimir, Loki, Tempo, Alloy, and Grafana
docker compose up -d
# Verify all services are healthy
docker compose pscd worker
# Install dependencies & build
go mod download
go build -o openqoe-worker
# Configure environment (OTEL_URL=http://localhost:4317)
cp .env.example .env
# Run the worker
./openqoe-worker
# Worker available at http://localhost:8788<script type="module">
import { OpenQoE } from "./sdk/dist/index.js";
const qoe = new OpenQoE({
orgId: "my-org",
playerId: "my-website",
endpointUrl: "http://localhost:8788/v2/events",
});
const player = dashjs.MediaPlayer().create();
player.initialize(videoElement, url, true);
qoe.attachPlayer("dashjs", player, {
videoId: "video-123",
videoTitle: "Production Stream",
});
</script>- Open Grafana: localhost:3000 (admin/admin)
- Navigate to Dashboards β OpenQoE folder
- Explore VOD Monitoring or Impact Explorer
- Use the Explore tab to view distributed traces in Tempo
OpenQoE v2 is ready! π
| Document | Description |
|---|---|
| Deployment Guide | Go Worker and Alloy Setup and deployment |
| API Reference | V2 Event Schemas and OTLP details |
| SDK Integration | Dash.js, HLS.js, HTML5 focus (other players WIP) |
| Architecture | Distributed observability pipeline |
| Production Ready | Production readiness report (Dash.js, HLS.js, HTML5) |
- Open VOD Monitoring dashboard
- Play a video and watch metrics appear in real-time!
That's it! Your video QoE monitoring is now live. π
| Document | Description |
|---|---|
| Architecture Overview | System architecture and component design |
| Technical Specification | Detailed technical specifications |
| Data Model | Event schemas and data structures |
| Production Ready Status | Complete production readiness report |
| Document | Description |
|---|---|
| Observability README | Stack overview, metrics, queries, troubleshooting |
| Dashboard Documentation | Dashboard specifications and panel details |
| Recording Rules | 25 pre-aggregated metrics |
| Alert Rules | 18 production alerts |
| Component | README |
|---|---|
| SDK | sdk/README.md |
| Worker | worker/README.md |
| Examples | examples/README.md |
Best for: On-premise deployments, full control, data sovereignty
# Start complete stack
docker compose up -d
# Configure worker for localhost
cd worker && npm run devIncludes: Mimir (metrics), Loki (logs), Grafana (dashboards)
Docs: Self-Hosted Deployment
Best for: Managed service, zero infrastructure, global scale
# Configure worker in .env
DESTINATION_TYPE=GrafanaCloud
GRAFANA_CLOUD_INSTANCE_ID=123456
GRAFANA_CLOUD_API_KEY=your-api-key
# Run worker
./openqoe-workerDocs: Grafana Cloud Deployment
Best for: Distributed ingestion with on-premise storage
Combine regional Go workers for global ingestion with a central self-hosted observability stack.
Docs: Hybrid Deployment
| Dashboard | Panels | Purpose | Key Metrics |
|---|---|---|---|
| VOD Monitoring | 21 | Real-time VOD quality | VST, rebuffering, completion, quartiles |
| Live Streaming | 11 | Live event monitoring | Concurrent viewers, join time, geographic |
| Quality & Delivery | 12 | Technical deep-dive | Seek latency, dropped frames, ABR |
| Impact Explorer | 14 | Business analysis | Watch time, engagement, revenue |
Business Metrics:
- Total views, completion rate, watch time
- Revenue impact calculations
- Engagement by quartile (25/50/75/100%)
- Content performance comparison
Technical Metrics:
- Video Startup Time (P50/P95/P99 via histograms)
- Rebuffer rate, duration, and frequency
- Seek latency and performance
- Error rates by type and family
- Bitrate distribution and ABR behavior
- Dropped frames and rendering quality
- Resolution distribution (360p-8K)
- Buffer health
Live Streaming:
- Concurrent viewers (real-time)
- Join time (P95)
- Geographic distribution
- Viewer drop detection
OpenQoE uses true histograms (not gauges) for accurate percentile calculations:
# Accurate P95 Video Startup Time
histogram_quantile(0.95,
sum(rate(openqoe_video_startup_seconds_bucket[5m])) by (le)
)
# Using pre-aggregated recording rule (10-50x faster)
openqoe:video_startup_seconds:p95
Histogram buckets configured:
- VST: [0.5, 1, 2, 3, 5, 10, 15, 30] seconds
- Rebuffer Duration: [0.5, 1, 2, 3, 5, 10, 30] seconds
- Seek Latency: [0.1, 0.25, 0.5, 1, 2, 5] seconds
| Player | Adapter | Status |
|---|---|---|
| Dash.js | DashJsAdapter |
β Production Ready |
| HTML5 | HTML5Adapter |
ποΈ Work In Progress |
| Video.js | VideoJsAdapter |
ποΈ Work In Progress |
| HLS.js | HlsJsAdapter |
ποΈ Work In Progress |
| Shaka Player | ShakaAdapter |
ποΈ Work In Progress |
*HTML5 doesn't support quality_change events (no native ABR)
| Event | Description | Business Value |
|---|---|---|
playerready |
Player initialized | Time to interactive |
viewstart |
Video load started | View funnel entry |
playing |
Playback started | Video Startup Time (VST) |
pause |
User paused | Engagement analysis |
seek |
User scrubbed | Navigation behavior |
stall_start |
Buffering started | Rebuffering detection |
stall_end |
Buffering ended | Rebuffer duration |
ended |
Video completed | Completion rate |
error |
Playback error | Error tracking |
quartile |
25/50/75/100% reached | Drop-off analysis |
heartbeat |
Periodic update (10s) | Watch time tracking |
quality_change |
ABR switch | Bitrate adaptation |
openqoe/
βββ build
βΒ Β βββ build.ninja
βΒ Β βββ CMakeCache.txt
βΒ Β βββ CMakeFiles
βΒ Β βΒ Β βββ 3.28.3
βΒ Β βΒ Β βΒ Β βββ CMakeCXXCompiler.cmake
βΒ Β βΒ Β βΒ Β βββ CMakeDetermineCompilerABI_CXX.bin
βΒ Β βΒ Β βΒ Β βββ CMakeSystem.cmake
βΒ Β βΒ Β βΒ Β βββ CompilerIdCXX
βΒ Β βΒ Β βΒ Β βββ a.out
βΒ Β βΒ Β βΒ Β βββ CMakeCXXCompilerId.cpp
βΒ Β βΒ Β βΒ Β βββ tmp
βΒ Β βΒ Β βββ cmake.check_cache
βΒ Β βΒ Β βββ CMakeConfigureLog.yaml
βΒ Β βΒ Β βββ OpenQoEWorker.dir
βΒ Β βΒ Β βΒ Β βββ src
βΒ Β βΒ Β βββ pkgRedirects
βΒ Β βΒ Β βββ rules.ninja
βΒ Β βΒ Β βββ TargetDirectories.txt
βΒ Β βββ cmake_install.cmake
βΒ Β βββ compile_commands.json
βΒ Β βββ OpenQoEWorker
βββ compose.yaml
βββ docs
βΒ Β βββ api-reference.md
βΒ Β βββ architecture.md
βΒ Β βββ contributing.md
βΒ Β βββ data-model.md
βΒ Β βββ deployment-checklist.md
βΒ Β βββ deployment-guide.md
βΒ Β βββ observability
βΒ Β βΒ Β βββ dashboards.md
βΒ Β βΒ Β βββ README.md
βΒ Β βββ production-ready.md
βΒ Β βββ sdk-integration.md
βΒ Β βββ technical-spec.md
βββ examples
βΒ Β βββ dashjs-demo
βΒ Β βΒ Β βββ index.html
βΒ Β βββ DEMO_TEMPLATE.md
βΒ Β βββ hlsjs-demo
βΒ Β βΒ Β βββ index.html
βΒ Β βββ html5-demo
βΒ Β βΒ Β βββ index.html
βΒ Β βββ README.md
βΒ Β βββ shaka-demo
βΒ Β βΒ Β βββ index.html
βΒ Β βββ videojs-demo
βΒ Β βββ index.html
βββ LICENSE
βββ observability
βΒ Β βββ alloy
βΒ Β βΒ Β βββ config.alloy
βΒ Β βββ dashboards
βΒ Β βΒ Β βββ impact-explorer.json
βΒ Β βΒ Β βββ live-streaming.json
βΒ Β βΒ Β βββ quality-delivery.json
βΒ Β βΒ Β βββ vod-monitoring.json
βΒ Β βββ grafana
βΒ Β βΒ Β βββ provisioning
βΒ Β βΒ Β βββ dashboards
βΒ Β βΒ Β βΒ Β βββ dashboards.yml
βΒ Β βΒ Β βββ datasources
βΒ Β βΒ Β βββ datasources.yml
βΒ Β βββ GRAFANA_DASHBOARDS.md
βΒ Β βββ loki
βΒ Β βΒ Β βββ loki-config.yaml
βΒ Β βββ mimir
βΒ Β βΒ Β βββ mimir-config.yml
βΒ Β βΒ Β βββ runtime.yml
βΒ Β βββ prometheus
βΒ Β βΒ Β βββ prometheus.yml
βΒ Β βΒ Β βββ rules
βΒ Β βΒ Β βββ load-rules.sh
βΒ Β βΒ Β βββ openqoe-alert-rules.yml
βΒ Β βΒ Β βββ openqoe-recording-rules.yml
βΒ Β βββ README.md
βΒ Β βββ tempo
βΒ Β βββ tempo-config.yaml
βββ openqoe-dev.code-workspace
βββ README.md
βββ sdk
βΒ Β βββ jest.config.js
βΒ Β βββ package.json
βΒ Β βββ package-lock.json
βΒ Β βββ README.md
βΒ Β βββ rollup.config.js
βΒ Β βββ src
βΒ Β βΒ Β βββ adapters
βΒ Β βΒ Β βΒ Β βββ DashJsAdapter.ts
βΒ Β βΒ Β βΒ Β βββ HlsJsAdapter.ts
βΒ Β βΒ Β βΒ Β βββ HTML5Adapter.ts
βΒ Β βΒ Β βΒ Β βββ ShakaAdapter.ts
βΒ Β βΒ Β βΒ Β βββ VideoJsAdapter.ts
βΒ Β βΒ Β βββ core
βΒ Β βΒ Β βΒ Β βββ BatchManager.ts
βΒ Β βΒ Β βΒ Β βββ EventCollector.ts
βΒ Β βΒ Β βΒ Β βββ QueueManager.ts
βΒ Β βΒ Β βΒ Β βββ RetryManager.ts
βΒ Β βΒ Β βΒ Β βββ SessionManager.ts
βΒ Β βΒ Β βΒ Β βββ Transport.ts
βΒ Β βΒ Β βββ index.ts
βΒ Β βΒ Β βββ OpenQoE.ts
βΒ Β βΒ Β βββ types.ts
βΒ Β βΒ Β βββ utils
βΒ Β βΒ Β βββ device.ts
βΒ Β βΒ Β βββ logger.ts
βΒ Β βΒ Β βββ privacy.ts
βΒ Β βββ tests
βΒ Β βΒ Β βββ core
βΒ Β βΒ Β βΒ Β βββ BatchManager.test.ts
βΒ Β βΒ Β βΒ Β βββ SessionManager.test.ts
βΒ Β βΒ Β βββ utils
βΒ Β βΒ Β βββ privacy.test.ts
βΒ Β βββ tsconfig.json
βββ sonar-project.properties
βββ test
βΒ Β βββ dashjs-test
βΒ Β βΒ Β βββ index.html
βΒ Β βββ hlsjs-test
βΒ Β βΒ Β βββ index.html
βΒ Β βββ html5-test
βΒ Β βΒ Β βββ index.html
βΒ Β βββ shaka-test
βΒ Β βΒ Β βββ index.html
βΒ Β βββ videojs-test
βΒ Β βββ index.html
βββ worker
βββ compute
βΒ Β βββ events.go
βΒ Β βββ helpers.go
βΒ Β βββ metrics.go
βΒ Β βββ system_metrics.go
βΒ Β βββ types.go
βββ config
βΒ Β βββ auth.go
βΒ Β βββ cardinality.go
βΒ Β βββ config.go
βΒ Β βββ destination.go
βΒ Β βββ env.go
βΒ Β βββ redis.go
βββ data_structure
βΒ Β βββ pair.go
βΒ Β βββ set.go
βββ Dockerfile
βββ go.mod
βββ go.sum
βββ main.go
βββ middlewares
βΒ Β βββ auth.go
βΒ Β βββ headers.go
βββ otelservice
βΒ Β βββ setup.go
βΒ Β βββ tracer.go
βΒ Β βββ types.go
βββ pool
βΒ Β βββ worker.go
βββ README.md
βββ requesthandlers
βββ controller.go
βββ markdevice.go
βββ requestvalidation.go
βββ types.go
cd sdk
npm install
npm run build
npm testcd worker
go build .
./worker
# Available at http://localhost:8788# while in root level
npm install -g http-server
http-server
# Open http://localhost:8080We welcome contributions! Whether it's:
- π Bug reports
- β¨ Feature requests
- π Documentation improvements
- π§ Code contributions
Please read our Contributing Guide for guidelines.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Commit with clear messages (
git commit -m 'Add amazing feature') - Push to your branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Copyright 2026-27 OpenQoE Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
- π Website: https://openqoe.dev
- π Documentation: Start with docs/deployment-guide.md
- π Bug Reports: GitHub Issues
- π‘ Feature Requests: GitHub Discussions
- π¬ Questions: GitHub Discussions Q&A
- Check the documentation
- Search existing issues
- Check troubleshooting guide
- Ask in Discussions
OpenQoE is built with:
- TypeScript - Type safe development
- Go - Low Latency highly concurrent native application with strict type safety
- Grafana Alloy - Open Telemetry collector for Observability Signals
- Grafana Mimir - Prometheus-compatible metrics storage
- Grafana Loki - Log aggregation
- Grafana Tempo - Trace Correleation
- Grafana - Visualization platform
- Docker - Containerization
Inspired by commercial QoE monitoring solutions for continuous improvement and industry best practices.
Current Version: 2.0.0 Status: β Dash.js, HLS.js, HTML5 Ready / ποΈ Core v2 In Beta Last Updated: January 2026
See docs/production-ready.md for complete production readiness report.
- β SDK for all 5 major web players
- β Low Latency
- β 4 comprehensive Grafana dashboards (58 panels)
- β 25 recording rules for performance
- β 18 production-ready alerts
- β Self-hosted Docker stack
- β Grafana Cloud support
- β Complete documentation
Phase 2 (Optional):
- Worker Health Dashboard (pipeline monitoring)
- Advanced cardinality analytics
- Custom metric extensions
- Load testing framework
If you find OpenQoE useful, please consider giving us a star β on GitHub. It helps others discover the project!
Made with β€οΈ by the OpenQoE Community