# Investigating Client-Side Video Quality Instability

**URL:** <https://janus.discourse.group/t/investigating-client-side-video-quality-instability/1733>\
**Category:** General\
**Created:** [October 21, 2025, 1:23pm UTC](https://janus.discourse.group/t/investigating-client-side-video-quality-instability/1733 "2025-10-21T13:23:05Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Lina](https://avatars.discourse-cdn.com/v4/letter/l/bb73d2/32.png) [@Lina](https://janus.discourse.group/u/Lina)\
**Post date:** [October 21, 2025, 1:23pm UTC](https://janus.discourse.group/t/investigating-client-side-video-quality-instability/1733/1 "2025-10-21T13:23:06Z")

</div>

# 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

1. What could explain the frame-level spikiness in client-side recordings compared to the stable Janus output?
2. 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](https://github.com/linadarwish/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

1. **Clone the repo:**

2. **Ensure your system is idle** — no heavy background CPU/network processes.

3. **Run the demo:**

4. **Perform the test:**

* * *

## VMAF Analysis

**[VMAF](https://github.com/Netflix/vmaf/tree/master) (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

```bash
# 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:

```bash
# 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

```bash
# 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

 ![2025-10-20T12-40-47-543Z-janus-rec-1760963954728-49qlnaz7q-video-trimmed_vmaf_frames](https://global.discourse-cdn.com/free1/uploads/janus/original/1X/f52d3e75b7440a0127e93ea410c80e84c03d572d.png)

### 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

 ![media-rec-1760964041044-trimmed_vmaf_frames](https://global.discourse-cdn.com/free1/uploads/janus/original/1X/f171941727a557e4d1ceece9902ffe9a784b55b5.png)

### 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

 ![lr-2-trimmed_vmaf_frames](https://global.discourse-cdn.com/free1/uploads/janus/original/1X/36c0cbfb20260687b4ad6550b3d95c6bc7538cb3.png)

---

<div class="post-metadata">

**Author:** ![lorenzo](https://yyz2.discourse-cdn.com/free1/user_avatar/janus.discourse.group/lorenzo/32/425_2.png) [@lorenzo](https://janus.discourse.group/u/lorenzo)\
**Post date:** [October 21, 2025, 1:25pm UTC](https://janus.discourse.group/t/investigating-client-side-video-quality-instability/1733/2 "2025-10-21T13:25:37Z")

</div>

Sorry, not going to do all that 😁 But thanks for sharing, it looks like a cool analysis!

The main difference that comes to mind is that when we’re recording in Janus, we’re recording the same exact frames that get to the browser, without decoding them, and then putting them into a playable file. When you record in the browser, you’re recording decoded media and then encoding it again to put in a webm file. This means it goes through a transformation process, and it’s not the same data, just the same visual content.
