Investigating Client-Side Video Quality Instability
Summary
I’ve been investigating differences between videos recorded directly by Janus Gateway and those recorded from the WebRTC element in the browser.
In my tests, the Janus recordings maintain consistently higher and smoother visual quality, while the browser-side recordings show occasional drops or spiky variations.
I’d love to understand what might be causing this difference — whether it’s related to how Janus handles streams internally, encoder settings, or something else entirely.
Thanks for your time and for maintaining such a powerful project ![]()
Open Questions
- What could explain the frame-level spikiness in client-side recordings compared to the stable Janus output?
- Are there configuration parameters that can reduce these quality dips?
Experiment Setup
Goal: Understand and minimize client-side quality degradation when streaming via Janus Gateway.
Repo: janus-demo
Prerequisites
- Docker - For running the Janus server
- Node.js and npm - For the middleware and client
- Python 3 - For VMAF analysis tools
- FFmpeg - For video processing
How to Reproduce
-
Clone the repo:
git clone https://github.com/linadarwish/janus-demo cd janus-demo -
Ensure your system is idle — no heavy background CPU/network processes.
-
Run the demo:
./run-demo.shThis automatically:
- Builds the Janus Docker image
- Installs all dependencies
- Starts all services (Janus server, Node.js middleware, React client)
- Opens the demo at http://localhost:3000
-
Perform the test:
- In the web interface, check the box “Enable Janus recording”
- Click “Start Connection”
- Immediately click “Start Recording” to begin browser-side media recording
- Let both recordings run for at least 90 seconds (until the sample video completes its loop)
- Click “Stop Connection”
- Click “Stop Recording” to finish browser recording
- Wait for both recordings to download:
media-rec-[timestamp].webm→ browser media recording (downloads immediately)[timestamp]-janus-rec-[id]-video.mjr→ Janus recording (downloads after ~1 minute processing)
- Do not refresh the page until the Janus recording has downloaded
VMAF Analysis
VMAF (Video Multi-Method Assessment Fusion) is a perceptual video quality metric developed by Netflix that scores videos 0-100 based on reference comparison.
Setup VMAF Tools
# Install Python dependencies
cd scripts/vmaf
uv sync
# Pull Docker image for VMAF analysis
docker pull gfdavila/easyvmaf
Convert Janus Recording
First, convert the .mjr file to a standard video format:
# From project root - replace with your actual .mjr filename
bash scripts/mjr-to-webm.sh [timestamp]-janus-rec-[id]-video.mjr
This creates a .webm file in the same directory.
Run VMAF Comparison
# Compare recordings using the video sync VMAF script
python3 scripts/vmaf/video_sync_vmaf.py scripts/vmaf/reference-video.mp4 media-rec-[timestamp].webm
# For the Janus recording comparison
python3 scripts/vmaf/video_sync_vmaf.py scripts/vmaf/reference-video.mp4 [timestamp]-janus-rec-[id]-video.webm
Script Output
The analysis creates timestamped directories like vmaf_results_[filename]_YYYYMMDD_HHMMSS/ containing:
- VMAF analysis JSON results (
*_vmaf.json) - Frame-by-frame quality plots (
*_vmaf_frames.png) - Quality distribution histograms (
*_vmaf_histogram.png)
Observed Quality Trends
Janus Gateway Recording
- Consistently high VMAF scores
- Smooth quality curve with few significant drops or spikes
- Almost stable encoding throughout the recording duration
Browser Media Recording
- Highly variable VMAF scores with frequent spikes and drops
- Early recording instability - significant quality dips in first 30 seconds
- Quality fluctuations throughout recording
Source Video Media Recording
To rule out that the media recording mechanism itself is significantly dropping quality, the code was temporarily altered to capture the source video element directly instead of the WebRTC stream. This shows that the overall trend is stable and within the excellent quality bucket.
Results:
- Stable VMAF scores
- No significant quality drops


