Skip to main content

Overview

CMAF (Common Media Application Format) is a standardized media format that enables efficient delivery of streaming content. It uses fragmented MP4 (fMP4) containers that can be packaged for both HLS and DASH, reducing storage and encoding costs.

Key Benefits

  • Unified workflow: Single encode for HLS and DASH
  • Reduced storage: One set of media files for multiple protocols
  • Lower latency: Smaller chunks enable faster delivery
  • Better codec support: Native support for HEVC, AV1, VP9
  • Efficient: Reduced CDN costs and bandwidth usage
  • Standards-based: ISO BMFF/MP4 format

How CMAF Works

CMAF uses fragmented MP4 (fMP4) containers that can be delivered via:
  • HLS with fMP4: Apple devices, browsers
  • DASH: Android, browsers, smart TVs
  • MSE (Media Source Extensions): Modern browsers

Enabling CMAF in Ant Media Server

Configuration

CMAF is enabled through HLS with fMP4 segments:
# Enable HLS with CMAF/fMP4
settings.hlsMuxingEnabled=true
settings.hlsSegmentType=fmp4

# Enable DASH (uses same CMAF segments)
settings.dashMuxingEnabled=true

# Segment duration (shorter for low latency)
settings.hlsTime=2
settings.dashSegDuration=2s

# Fragment duration (sub-segment chunks)
settings.dashFragmentDuration=0.5s

Publishing for CMAF

# Publish via RTMP
ffmpeg -re -i input.mp4 \
  -c:v libx264 -preset veryfast -b:v 2500k \
  -c:a aac -b:a 128k \
  -f flv rtmp://your-server.com/WebRTCAppEE/stream123

# Access as:
# HLS: https://your-server.com:5443/WebRTCAppEE/streams/stream123.m3u8
# DASH: https://your-server.com:5443/WebRTCAppEE/streams/stream123.mpd

Playing CMAF Streams

HLS with fMP4 (CMAF)

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="video" controls width="100%"></video>

<script>
  const video = document.getElementById('video');
  const hlsUrl = 'https://your-server.com:5443/WebRTCAppEE/streams/stream123.m3u8';
  
  if (Hls.isSupported()) {
    const hls = new Hls({
      enableWorker: true,
      lowLatencyMode: true,
      backBufferLength: 90
    });
    
    hls.loadSource(hlsUrl);
    hls.attachMedia(video);
    
    hls.on(Hls.Events.MANIFEST_PARSED, () => {
      video.play();
    });
  }
</script>

DASH (CMAF)

<script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
<video id="video" controls width="100%"></video>

<script>
  const url = 'https://your-server.com:5443/WebRTCAppEE/streams/stream123.mpd';
  const player = dashjs.MediaPlayer().create();
  
  player.initialize(document.getElementById('video'), url, true);
  
  player.updateSettings({
    streaming: {
      lowLatencyEnabled: true,
      liveDelay: 3,
      delay: {
        liveDelay: 3
      },
      buffer: {
        fastSwitchEnabled: true
      }
    }
  });
</script>

Low Latency CMAF (LL-DASH / LL-HLS)

Configuration for Ultra-Low Latency

# Enable low latency modes
settings.lLDashEnabled=true
settings.lLHLSEnabled=true

# Short segments
settings.hlsTime=2
settings.dashSegDuration=2s

# Small fragments (chunks)
settings.dashFragmentDuration=0.2s
settings.hlsPartTargetDuration=0.2

# Target latency
settings.targetLatency=3s

# Streaming mode
settings.dashHttpStreaming=true

LL-DASH Player Configuration

const player = dashjs.MediaPlayer().create();

player.updateSettings({
    streaming: {
        lowLatencyEnabled: true,
        liveDelay: 3,  // Target 3 second latency
        liveCatchup: {
            enabled: true,
            mode: 'liveCatchupModeDefault'
        },
        delay: {
            liveDelay: 3,
            liveDelayFragmentCount: NaN,  // Use time-based delay
            useSuggestedPresentationDelay: false
        },
        buffer: {
            fastSwitchEnabled: true,
            flushBufferAtTrackSwitch: false,
            reuseExistingSourceBuffers: true,
            bufferTimeDefault: 12,
            bufferTimeAtTopQuality: 12,
            bufferTimeAtTopQualityLongForm: 12
        }
    }
});

CMAF Structure

File Organization

streams/
├── stream123.m3u8              # HLS master playlist
├── stream123.mpd               # DASH manifest
├── stream123_init.mp4          # Initialization segment
├── stream123_000000000.m4s     # Media segment 0
├── stream123_000000001.m4s     # Media segment 1
├── stream123_000000002.m4s     # Media segment 2
└── ...

# With ABR:
streams/
├── stream123.m3u8              # HLS master
├── stream123.mpd               # DASH master
├── stream123_360p/
   ├── init.mp4
   └── segment_*.m4s
├── stream123_720p/
   ├── init.mp4
   └── segment_*.m4s
└── stream123_1080p/
    ├── init.mp4
    └── segment_*.m4s

HLS Playlist (CMAF)

#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:2
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=0.6
#EXT-X-PART-INF:PART-TARGET=0.2
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-MAP:URI="stream123_init.mp4"
#EXT-X-PROGRAM-DATE-TIME:2024-01-15T10:30:00.000Z
#EXTINF:2.000,
stream123_000000000.m4s
#EXTINF:2.000,
stream123_000000001.m4s
#EXTINF:2.000,
stream123_000000002.m4s

DASH Manifest (CMAF)

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" 
     type="dynamic"
     minimumUpdatePeriod="PT2S"
     suggestedPresentationDelay="PT3S"
     availabilityStartTime="2024-01-15T10:30:00Z"
     publishTime="2024-01-15T10:30:00Z"
     timeShiftBufferDepth="PT30S">
  <Period start="PT0S">
    <!-- Video Adaptation Set -->
    <AdaptationSet mimeType="video/mp4" 
                   codecs="avc1.64001f" 
                   startWithSAP="1" 
                   segmentAlignment="true">
      <SegmentTemplate timescale="1000" 
                       media="stream123_$Number$.m4s" 
                       initialization="stream123_init.mp4" 
                       duration="2000" 
                       startNumber="0" />
      <Representation id="720p" 
                      bandwidth="2500000" 
                      width="1280" 
                      height="720" />
    </AdaptationSet>
    
    <!-- Audio Adaptation Set -->
    <AdaptationSet mimeType="audio/mp4" 
                   codecs="mp4a.40.2" 
                   startWithSAP="1">
      <SegmentTemplate timescale="1000" 
                       media="stream123_audio_$Number$.m4s" 
                       initialization="stream123_audio_init.mp4" 
                       duration="2000" 
                       startNumber="0" />
      <Representation id="audio" 
                      bandwidth="128000" 
                      audioSamplingRate="44100" />
    </AdaptationSet>
  </Period>
</MPD>

Advanced Features

HEVC/H.265 Support

CMAF has excellent HEVC support:
# Encode with HEVC
ffmpeg -i input.mp4 \
  -c:v libx265 -preset fast -b:v 2000k \
  -c:a aac -b:a 128k \
  -f dash \
  -seg_duration 2 \
  output.mpd
# Enable HEVC in Ant Media Server
settings.h265Enabled=true
settings.hlsSegmentType=fmp4

Common Encryption (CENC)

CMAF supports DRM:
# Package with Widevine and PlayReady
packager \
  'in=input.mp4,stream=video,output=video.mp4' \
  'in=input.mp4,stream=audio,output=audio.mp4' \
  --enable_widevine_encryption \
  --key_server_url "https://license.server/proxy" \
  --content_id "content123" \
  --signer "widevine_test" \
  --enable_playready_encryption \
  --mpd_output output.mpd \
  --hls_master_playlist_output output.m3u8

Troubleshooting

Playback Issues

Initialization Segment Missing:
# Check for init.mp4
ls -la /usr/local/antmedia/webapps/WebRTCAppEE/streams/*init*

# Verify init segment in playlist
curl https://your-server.com:5443/WebRTCAppEE/streams/stream123.m3u8 | grep -i init
Codec Compatibility:
# Check codec in manifest
ffprobe https://your-server.com:5443/WebRTCAppEE/streams/stream123.mpd

# Verify browser support
# In browser console:
MediaSource.isTypeSupported('video/mp4; codecs="avc1.64001f"')
MediaSource.isTypeSupported('video/mp4; codecs="hev1.1.6.L120.90"')
Segment Timing Issues:
# Validate segment durations
ffprobe -show_entries packet=pts_time,dts_time \
  https://your-server.com:5443/WebRTCAppEE/streams/stream123_000000000.m4s

Performance Optimization

# Optimize for low latency
settings.dashFragmentDuration=0.2s
settings.dashSegDuration=2s
settings.targetLatency=3s

# Optimize for quality
settings.dashFragmentDuration=2s
settings.dashSegDuration=10s
settings.useTimelineDashMuxing=true

Best Practices

Production Recommendations

  1. Use fMP4: Set hlsSegmentType=fmp4 for CMAF benefits
  2. Consistent GOP: Set fixed keyframe interval (e.g., 2 seconds)
  3. Short fragments: Use 0.2-0.5s fragments for low latency
  4. CDN optimization: Enable CORS, set appropriate cache headers
  5. Monitor segment generation: Track timing and availability
  6. Test across devices: Verify HLS and DASH playback

Quality Settings

settings.hlsSegmentType=fmp4
settings.dashSegDuration=1s
settings.dashFragmentDuration=0.2s
settings.lLDashEnabled=true
settings.targetLatency=2s

CMAF vs Traditional Formats

FeatureCMAFHLS (TS)DASH (TS)
ContainerfMP4MPEG-TSMPEG-TS or fMP4
StorageSingleSeparateSeparate
HEVC SupportExcellentLimitedGood
LatencyLowMediumMedium
Browser SupportGoodExcellentGood
UnificationYesNoNo

Migration Guide

From Traditional HLS to CMAF

# Before (HLS with TS)
settings.hlsSegmentType=mpegts

# After (CMAF)
settings.hlsSegmentType=fmp4
settings.dashMuxingEnabled=true
Benefits:
  • 30-40% storage reduction
  • Better HEVC support
  • Unified HLS/DASH workflow

Resources

Build docs developers (and LLMs) love