Adaptive Bitrate Streaming

Automatically adjusting video quality based on network conditions using HLS, DASH protocols and player implementation for smooth playback and optimal user experience.

16 stars

Best use case

Adaptive Bitrate Streaming is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Automatically adjusting video quality based on network conditions using HLS, DASH protocols and player implementation for smooth playback and optimal user experience.

Teams using Adaptive Bitrate Streaming should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/adaptive-bitrate-streaming/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/content-media/adaptive-bitrate-streaming/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/adaptive-bitrate-streaming/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How Adaptive Bitrate Streaming Compares

Feature / AgentAdaptive Bitrate StreamingStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Automatically adjusting video quality based on network conditions using HLS, DASH protocols and player implementation for smooth playback and optimal user experience.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Adaptive Bitrate Streaming

> **Current Level:** Advanced  
> **Domain:** Video Streaming / Media

---

## Overview

Adaptive Bitrate (ABR) streaming automatically adjusts video quality based on network conditions. This guide covers HLS, DASH, and player implementation for building video streaming solutions that provide smooth playback across varying network conditions.

---

## ABR Concepts

```
Network Speed Detection → Quality Selection → Seamless Switching
```

**Benefits:**
- Smooth playback
- Reduced buffering
- Optimal quality
- Better user experience

## HLS (HTTP Live Streaming)

### Master Playlist

```m3u8
#EXTM3U
#EXT-X-VERSION:3

#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.640028,mp4a.40.2"
1080p/playlist.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=3000000,RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2"
720p/playlist.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=1500000,RESOLUTION=854x480,CODECS="avc1.64001e,mp4a.40.2"
480p/playlist.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360,CODECS="avc1.64001e,mp4a.40.2"
360p/playlist.m3u8
```

### Media Playlist

```m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0

#EXTINF:10.0,
segment_0000.ts
#EXTINF:10.0,
segment_0001.ts
#EXTINF:10.0,
segment_0002.ts
#EXTINF:10.0,
segment_0003.ts

#EXT-X-ENDLIST
```

## Creating ABR Streams with FFmpeg

```bash
# Create HLS with multiple bitrates
ffmpeg -i input.mp4 \
  -filter_complex \
  "[0:v]split=4[v1][v2][v3][v4]; \
   [v1]scale=w=1920:h=1080[v1out]; \
   [v2]scale=w=1280:h=720[v2out]; \
   [v3]scale=w=854:h=480[v3out]; \
   [v4]scale=w=640:h=360[v4out]" \
  -map "[v1out]" -c:v:0 libx264 -b:v:0 5M -maxrate:v:0 5M -bufsize:v:0 10M \
  -map "[v2out]" -c:v:1 libx264 -b:v:1 3M -maxrate:v:1 3M -bufsize:v:1 6M \
  -map "[v3out]" -c:v:2 libx264 -b:v:2 1.5M -maxrate:v:2 1.5M -bufsize:v:2 3M \
  -map "[v4out]" -c:v:3 libx264 -b:v:3 800k -maxrate:v:3 800k -bufsize:v:3 1.6M \
  -map a:0 -c:a:0 aac -b:a:0 128k \
  -map a:0 -c:a:1 aac -b:a:1 128k \
  -map a:0 -c:a:2 aac -b:a:2 96k \
  -map a:0 -c:a:3 aac -b:a:3 64k \
  -f hls \
  -hls_time 6 \
  -hls_playlist_type vod \
  -hls_flags independent_segments \
  -hls_segment_type mpegts \
  -hls_segment_filename "stream_%v/data%03d.ts" \
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2 v:3,a:3" \
  stream_%v.m3u8
```

## DASH (MPEG-DASH)

### MPD Manifest

```xml
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" type="static">
  <Period>
    <AdaptationSet mimeType="video/mp4" codecs="avc1.64001f">
      <Representation id="1080p" bandwidth="5000000" width="1920" height="1080">
        <BaseURL>1080p/</BaseURL>
        <SegmentTemplate media="segment_$Number$.m4s" initialization="init.mp4" startNumber="1" duration="6000" timescale="1000"/>
      </Representation>
      <Representation id="720p" bandwidth="3000000" width="1280" height="720">
        <BaseURL>720p/</BaseURL>
        <SegmentTemplate media="segment_$Number$.m4s" initialization="init.mp4" startNumber="1" duration="6000" timescale="1000"/>
      </Representation>
    </AdaptationSet>
    <AdaptationSet mimeType="audio/mp4" codecs="mp4a.40.2">
      <Representation id="audio" bandwidth="128000">
        <BaseURL>audio/</BaseURL>
        <SegmentTemplate media="segment_$Number$.m4s" initialization="init.mp4" startNumber="1" duration="6000" timescale="1000"/>
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>
```

### Creating DASH with FFmpeg

```bash
ffmpeg -i input.mp4 \
  -map 0:v -map 0:a \
  -c:v libx264 -c:a aac \
  -b:v:0 5M -s:v:0 1920x1080 \
  -b:v:1 3M -s:v:1 1280x720 \
  -b:v:2 1.5M -s:v:2 854x480 \
  -b:a 128k \
  -f dash \
  -seg_duration 6 \
  -use_template 1 \
  -use_timeline 1 \
  -init_seg_name 'init-$RepresentationID$.m4s' \
  -media_seg_name 'chunk-$RepresentationID$-$Number%05d$.m4s' \
  manifest.mpd
```

## Player Implementation

### Video.js

```typescript
// components/VideoPlayer.tsx
import { useEffect, useRef } from 'react';
import videojs from 'video.js';
import 'video.js/dist/video-js.css';

export function VideoPlayer({ src }: { src: string }) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const playerRef = useRef<any>(null);

  useEffect(() => {
    if (!videoRef.current) return;

    const player = videojs(videoRef.current, {
      controls: true,
      autoplay: false,
      preload: 'auto',
      fluid: true,
      sources: [{
        src,
        type: 'application/x-mpegURL' // HLS
      }]
    });

    playerRef.current = player;

    // Quality selection
    player.on('loadedmetadata', () => {
      const qualityLevels = player.qualityLevels();
      
      qualityLevels.on('addqualitylevel', (event: any) => {
        console.log('Quality level added:', event.qualityLevel);
      });

      qualityLevels.on('change', () => {
        console.log('Quality changed to:', qualityLevels[qualityLevels.selectedIndex]);
      });
    });

    return () => {
      if (playerRef.current) {
        playerRef.current.dispose();
      }
    };
  }, [src]);

  return (
    <div data-vjs-player>
      <video ref={videoRef} className="video-js vjs-big-play-centered" />
    </div>
  );
}
```

### hls.js

```typescript
// components/HLSPlayer.tsx
import { useEffect, useRef } from 'react';
import Hls from 'hls.js';

export function HLSPlayer({ src }: { src: string }) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const hlsRef = useRef<Hls | null>(null);

  useEffect(() => {
    if (!videoRef.current) return;

    if (Hls.isSupported()) {
      const hls = new Hls({
        enableWorker: true,
        lowLatencyMode: true,
        backBufferLength: 90
      });

      hls.loadSource(src);
      hls.attachMedia(videoRef.current);

      hls.on(Hls.Events.MANIFEST_PARSED, () => {
        console.log('Manifest loaded, levels:', hls.levels);
      });

      hls.on(Hls.Events.LEVEL_SWITCHED, (event, data) => {
        console.log('Level switched to:', data.level);
      });

      hls.on(Hls.Events.ERROR, (event, data) => {
        if (data.fatal) {
          switch (data.type) {
            case Hls.ErrorTypes.NETWORK_ERROR:
              console.error('Network error');
              hls.startLoad();
              break;
            case Hls.ErrorTypes.MEDIA_ERROR:
              console.error('Media error');
              hls.recoverMediaError();
              break;
            default:
              hls.destroy();
              break;
          }
        }
      });

      hlsRef.current = hls;
    } else if (videoRef.current.canPlayType('application/vnd.apple.mpegurl')) {
      // Native HLS support (Safari)
      videoRef.current.src = src;
    }

    return () => {
      if (hlsRef.current) {
        hlsRef.current.destroy();
      }
    };
  }, [src]);

  return (
    <video
      ref={videoRef}
      controls
      style={{ width: '100%', maxWidth: '800px' }}
    />
  );
}
```

### Shaka Player (DASH)

```typescript
// components/DASHPlayer.tsx
import { useEffect, useRef } from 'react';
import shaka from 'shaka-player';

export function DASHPlayer({ src }: { src: string }) {
  const videoRef = useRef<HTMLVideoElement>(null);
  const playerRef = useRef<shaka.Player | null>(null);

  useEffect(() => {
    if (!videoRef.current) return;

    const player = new shaka.Player(videoRef.current);

    player.configure({
      abr: {
        enabled: true,
        defaultBandwidthEstimate: 1000000
      },
      streaming: {
        bufferingGoal: 30,
        rebufferingGoal: 2
      }
    });

    player.load(src).then(() => {
      console.log('Video loaded successfully');
    }).catch((error) => {
      console.error('Error loading video:', error);
    });

    player.addEventListener('adaptation', () => {
      const tracks = player.getVariantTracks();
      const activeTrack = tracks.find(t => t.active);
      console.log('Adapted to:', activeTrack?.height + 'p');
    });

    playerRef.current = player;

    return () => {
      if (playerRef.current) {
        playerRef.current.destroy();
      }
    };
  }, [src]);

  return (
    <video
      ref={videoRef}
      controls
      style={{ width: '100%', maxWidth: '800px' }}
    />
  );
}
```

## Quality Selection

```typescript
// Manual quality selection
export function QualitySelector({ player }: { player: any }) {
  const [qualities, setQualities] = useState<Quality[]>([]);
  const [currentQuality, setCurrentQuality] = useState<number>(-1);

  useEffect(() => {
    if (!player) return;

    const qualityLevels = player.qualityLevels();
    
    const levels: Quality[] = [];
    for (let i = 0; i < qualityLevels.length; i++) {
      levels.push({
        index: i,
        height: qualityLevels[i].height,
        bitrate: qualityLevels[i].bitrate,
        label: `${qualityLevels[i].height}p`
      });
    }

    setQualities(levels);

    qualityLevels.on('change', () => {
      setCurrentQuality(qualityLevels.selectedIndex);
    });
  }, [player]);

  const selectQuality = (index: number) => {
    const qualityLevels = player.qualityLevels();
    
    // Disable all levels
    for (let i = 0; i < qualityLevels.length; i++) {
      qualityLevels[i].enabled = false;
    }

    // Enable selected level
    if (index === -1) {
      // Auto mode
      for (let i = 0; i < qualityLevels.length; i++) {
        qualityLevels[i].enabled = true;
      }
    } else {
      qualityLevels[index].enabled = true;
    }
  };

  return (
    <select value={currentQuality} onChange={(e) => selectQuality(parseInt(e.target.value))}>
      <option value={-1}>Auto</option>
      {qualities.map((q) => (
        <option key={q.index} value={q.index}>
          {q.label}
        </option>
      ))}
    </select>
  );
}

interface Quality {
  index: number;
  height: number;
  bitrate: number;
  label: string;
}
```

## DRM Integration

```typescript
// DRM configuration for Shaka Player
const drmConfig = {
  drm: {
    servers: {
      'com.widevine.alpha': 'https://widevine-proxy.example.com/proxy',
      'com.microsoft.playready': 'https://playready.example.com/rightsmanager.asmx'
    }
  }
};

player.configure(drmConfig);

// FairPlay for Safari
if (shaka.Player.isBrowserSupported() && 
    navigator.requestMediaKeySystemAccess) {
  // Configure FairPlay
}
```

---

## Quick Start

### HLS Manifest Generation

```bash
# Generate HLS with multiple bitrates
ffmpeg -i input.mp4 \
  -c:v libx264 -preset veryfast -b:v:0 3000k -s:v:0 1920x1080 \
  -c:v libx264 -preset veryfast -b:v:1 1500k -s:v:1 1280x720 \
  -c:v libx264 -preset veryfast -b:v:2 800k -s:v:2 854x480 \
  -c:a aac -b:a 128k \
  -var_stream_map "v:0,a:0 v:1,a:0 v:2,a:0" \
  -master_pl_name master.m3u8 \
  -f hls -hls_time 6 -hls_list_size 0 \
  stream_%v/playlist.m3u8
```

### HLS.js Player

```javascript
import Hls from 'hls.js'

const video = document.getElementById('video')
const hls = new Hls()

hls.loadSource('https://server/master.m3u8')
hls.attachMedia(video)

// Monitor quality changes
hls.on(Hls.Events.LEVEL_SWITCHED, (event, data) => {
  console.log('Switched to quality:', data.level)
})
```

---

## Production Checklist

- [ ] **Multiple Qualities**: Provide 3-5 quality levels
- [ ] **Segment Duration**: Use 6-10 second segments
- [ ] **Buffer Management**: Configure appropriate buffers
- [ ] **Error Handling**: Handle network errors gracefully
- [ ] **CDN**: Use CDN for global distribution
- [ ] **Monitoring**: Monitor playback quality and buffering
- [ ] **Testing**: Test on various network conditions
- [ ] **Fallback**: Fallback to lower quality on errors
- [ ] **Analytics**: Track quality switches and buffering
- [ ] **Documentation**: Document quality levels
- [ ] **Optimization**: Optimize encoding settings
- [ ] **Compatibility**: Test across browsers and devices

---

## Anti-patterns

### ❌ Don't: Single Quality

```bash
# ❌ Bad - One quality only
ffmpeg -i input.mp4 -b:v 3000k output.m3u8
```

```bash
# ✅ Good - Multiple qualities
ffmpeg -i input.mp4 \
  -b:v:0 3000k -b:v:1 1500k -b:v:2 800k \
  -var_stream_map "v:0 v:1 v:2" \
  master.m3u8
```

### ❌ Don't: Long Segments

```bash
# ❌ Bad - Long segments
-hls_time 30  # 30 seconds - slow adaptation
```

```bash
# ✅ Good - Shorter segments
-hls_time 6  # 6 seconds - faster adaptation
```

---

## Integration Points

- **Live Streaming** (`37-video-streaming/live-streaming/`) - Live ABR
- **CDN Delivery** (`37-video-streaming/cdn-delivery/`) - CDN setup
- **Video Analytics** (`37-video-streaming/video-analytics/`) - Quality metrics

---

## Further Reading

- [HLS Specification](https://developer.apple.com/streaming/)
- [DASH Specification](https://dashif.org/)
- [HLS.js Documentation](https://github.com/video-dev/hls.js/)
5. **Quality Selection** - Allow manual quality override
6. **Analytics** - Track quality switches
7. **CDN** - Use CDN for delivery
8. **Testing** - Test on various network conditions
9. **Fallback** - Provide progressive download fallback
10. **DRM** - Implement DRM when needed

## Resources

- [HLS Specification](https://datatracker.ietf.org/doc/html/rfc8216)
- [DASH Specification](https://dashif.org/)
- [Video.js](https://videojs.com/)
- [hls.js](https://github.com/video-dev/hls.js/)
- [Shaka Player](https://github.com/shaka-project/shaka-player)

Related Skills

adaptive-workflows

16
from diegosouzapw/awesome-omni-skill

Self-learning workflow system that tracks what works best for your use cases. Records experiment results, suggests optimizations, creates custom templates, and builds a personal knowledge base. Use to learn from experience and optimize your LLM workflows over time.

Adaptive Daily Reflection & Planner

16
from diegosouzapw/awesome-omni-skill

An intelligent daily check-in assistant that adapts its depth based on user engagement. It collects key activities and emotions for daily summaries while extracting tasks for to-do list management.

adaptive-temporal-analysis-integration

16
from diegosouzapw/awesome-omni-skill

Integrate adaptive temporal analysis for drift detection.

adaptive-guardrail-calibrator

16
from diegosouzapw/awesome-omni-skill

Calibrate guardrail thresholds from live hardware telemetry and emit environment presets. Use when thresholds are hand-tuned or drift with hardware changes.

Adaptive Bitrate

16
from diegosouzapw/awesome-omni-skill

Adaptive Bitrate (ABR) streaming automatically adjusts video quality based on network conditions. This guide covers HLS, DASH, and player implementation for building video streaming solutions that pro

bgo

10
from diegosouzapw/awesome-omni-skill

Automates the complete Blender build-go workflow, from building and packaging your extension/add-on to removing old versions, installing, enabling, and launching Blender for quick testing and iteration.

Coding & Development

large-data-with-dask

16
from diegosouzapw/awesome-omni-skill

Specific optimization strategies for Python scripts working with larger-than-memory datasets via Dask.

langsmith-fetch

16
from diegosouzapw/awesome-omni-skill

Debug LangChain and LangGraph agents by fetching execution traces from LangSmith Studio. Use when debugging agent behavior, investigating errors, analyzing tool calls, checking memory operations, or examining agent performance. Automatically fetches recent traces and analyzes execution patterns. Requires langsmith-fetch CLI installed.

langchain-tool-calling

16
from diegosouzapw/awesome-omni-skill

How chat models call tools - includes bind_tools, tool choice strategies, parallel tool calling, and tool message handling

langchain-notes

16
from diegosouzapw/awesome-omni-skill

LangChain 框架学习笔记 - 快速查找概念、代码示例和最佳实践。包含 Core components、Middleware、Advanced usage、Multi-agent patterns、RAG retrieval、Long-term memory 等主题。当用户询问 LangChain、Agent、RAG、向量存储、工具使用、记忆系统时使用此 Skill。

langchain-js

16
from diegosouzapw/awesome-omni-skill

Builds LLM-powered applications with LangChain.js for chat, agents, and RAG. Use when creating AI applications with chains, memory, tools, and retrieval-augmented generation in JavaScript.

langchain-agents

16
from diegosouzapw/awesome-omni-skill

Expert guidance for building LangChain agents with proper tool binding, memory, and configuration. Use when creating agents, configuring models, or setting up tool integrations in LangConfig.