MPEG-DASH Streaming with Dash.js handler

Dash.js Version: 4.3.0
Buffer Level:
Reported Bitrate:
Framerate:
Resolution:
Nuevodevel.com introduce nuevo-dash plugin, source handler based on dash.js library for supporting MPEG-DASH playback on browsers with support for Media Source Extensions.This is alternative for videojs default HTTP streaming engine. Existing videos-contrib-dash plugin is outdated, it doesn't allow to set dash.js options, doesn't allow to load and manage quality variants.
The plugin by Nuevodevel.com supports the latest Dash.js version: 4.3.
Code snippet
<script src="//domain.com/videojs/video.min.js"></script>
<script src="//domain.com/videojs/plugins/nuevo-dash.js"></script>
<script src="//domain.com/videojs/nuevo.min.js"></script>

<video id="myplayer" class="video-js" width+"640" height="360" controls>
<source src="//path/to/manifest.mpd" type="application/dash+xml" />
</video>

<script>
var player = videojs('myplayer');
player.nuevoPlugin({
logo: "//domain.com/path/to/logo.png",
logourl: "/domain.com"
});
</script>

Passing options to Dash.js

With the release of dash.js structure the various settings in the dash.js has changed. See how few options can be passed to dash.js when using nuevo-dash plugin.
Code snippet
<script>
const dashOptions = {
streaming: {
buffer: {
fastSwitchEnabled: true
}
abr:{
limitBitrateByPortal: true,
initialBitrate: {
audio: -1,
video: 360
}
}
}
}
var player = videojs('myplayer', { html5:{ dash: dashOptions }});
</script>

Dash.js setting options are described here. Click button below to see an array of all default Dash.js options.
DASH.JS OPTIONS
const defaultSettings = {
        debug: {
            logLevel: Debug.LOG_LEVEL_WARNING,
            dispatchEvent: false
        },
        streaming: {
            abandonLoadTimeout: 10000,
            wallclockTimeUpdateInterval: 100,
            lowLatencyEnabled: false,
            manifestUpdateRetryInterval: 100,
            cacheInitSegments: false,
            eventControllerRefreshDelay: 150,
            capabilities: {
                filterUnsupportedEssentialProperties: true,
                useMediaCapabilitiesApi: false
            },
            timeShiftBuffer: {
                calcFromSegmentTimeline: false,
                fallbackToSegmentTimeline: true
            },
            metrics: {
                maxListDepth: 100
            },
            delay: {
                liveDelayFragmentCount: NaN,
                liveDelay: NaN,
                useSuggestedPresentationDelay: true,
                applyServiceDescription: true
            },
            protection: {
                keepProtectionMediaKeys: false
            },
            buffer: {
                fastSwitchEnabled: true,
                flushBufferAtTrackSwitch: false,
                reuseExistingSourceBuffers: true,
                bufferPruningInterval: 10,
                bufferToKeep: 20,
                bufferTimeAtTopQuality: 30,
                bufferTimeAtTopQualityLongForm: 60,
                initialBufferLevel: NaN,
                stableBufferTime: 12,
                longFormContentDurationThreshold: 600,
                stallThreshold: 0.3,
                useAppendWindow: true,
                setStallState: true
            },
            gaps: {
                jumpGaps: true,
                jumpLargeGaps: true,
                smallGapLimit: 1.5,
                threshold: 0.3
            },
            utcSynchronization: {
                useManifestDateHeaderTimeSource: true,
                backgroundAttempts: 2,
                timeBetweenSyncAttempts: 30,
                maximumTimeBetweenSyncAttempts: 600,
                minimumTimeBetweenSyncAttempts: 2,
                timeBetweenSyncAttemptsAdjustmentFactor: 2,
                maximumAllowedDrift: 100,
                enableBackgroundSyncAfterSegmentDownloadError: true,
                defaultTimingSource: {
                    scheme: 'urn:mpeg:dash:utc:http-xsdate:2014',
                    value: 'https://time.akamai.com/?iso&ms'
                }
            },
            scheduling: {
                defaultTimeout: 500,
                lowLatencyTimeout: 0,
                scheduleWhilePaused: true
            },
            text: {
                defaultEnabled: true
            },
            liveCatchup: {
                minDrift: 0.02,
                maxDrift: 0,
                playbackRate: 0.5,
                latencyThreshold: 60,
                playbackBufferMin: 0.5,
                enabled: false,
                mode: Constants.LIVE_CATCHUP_MODE_DEFAULT
            },
            lastBitrateCachingInfo: {
                enabled: true,
                ttl: 360000
            },
            lastMediaSettingsCachingInfo: {
                enabled: true,
                ttl: 360000
            },
            cacheLoadThresholds: {
                video: 50,
                audio: 5
            },
            trackSwitchMode: {
                audio: Constants.TRACK_SWITCH_MODE_ALWAYS_REPLACE,
                video: Constants.TRACK_SWITCH_MODE_NEVER_REPLACE
            },
            selectionModeForInitialTrack: Constants.TRACK_SELECTION_MODE_HIGHEST_BITRATE,
            fragmentRequestTimeout: 0,
            retryIntervals: {
                [HTTPRequest.MPD_TYPE]: 500,
                [HTTPRequest.XLINK_EXPANSION_TYPE]: 500,
                [HTTPRequest.MEDIA_SEGMENT_TYPE]: 1000,
                [HTTPRequest.INIT_SEGMENT_TYPE]: 1000,
                [HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE]: 1000,
                [HTTPRequest.INDEX_SEGMENT_TYPE]: 1000,
                [HTTPRequest.MSS_FRAGMENT_INFO_SEGMENT_TYPE]: 1000,
                [HTTPRequest.LICENSE]: 1000,
                [HTTPRequest.OTHER_TYPE]: 1000,
                lowLatencyReductionFactor: 10
            },
            retryAttempts: {
                [HTTPRequest.MPD_TYPE]: 3,
                [HTTPRequest.XLINK_EXPANSION_TYPE]: 1,
                [HTTPRequest.MEDIA_SEGMENT_TYPE]: 3,
                [HTTPRequest.INIT_SEGMENT_TYPE]: 3,
                [HTTPRequest.BITSTREAM_SWITCHING_SEGMENT_TYPE]: 3,
                [HTTPRequest.INDEX_SEGMENT_TYPE]: 3,
                [HTTPRequest.MSS_FRAGMENT_INFO_SEGMENT_TYPE]: 3,
                [HTTPRequest.LICENSE]: 3,
                [HTTPRequest.OTHER_TYPE]: 3,
                lowLatencyMultiplyFactor: 5
            },
            abr: {
                movingAverageMethod: Constants.MOVING_AVERAGE_SLIDING_WINDOW,
                ABRStrategy: Constants.ABR_STRATEGY_DYNAMIC,
                additionalAbrRules: {
                    insufficientBufferRule: true,
                    switchHistoryRule: true,
                    droppedFramesRule: true,
                    abandonRequestsRule: false
                },
                bandwidthSafetyFactor: 0.9,
                useDefaultABRRules: true,
                useDeadTimeLatency: true,
                limitBitrateByPortal: false,
                usePixelRatioInLimitBitrateByPortal: false,
                maxBitrate: {
                    audio: -1,
                    video: -1
                },
                minBitrate: {
                    audio: -1,
                    video: -1
                },
                maxRepresentationRatio: {
                    audio: 1,
                    video: 1
                },
                initialBitrate: {
                    audio: -1,
                    video: -1
                },
                initialRepresentationRatio: {
                    audio: -1,
                    video: -1
                },
                autoSwitchBitrate: {
                    audio: true,
                    video: true
                },
                fetchThroughputCalculationMode: Constants.ABR_FETCH_THROUGHPUT_CALCULATION_MOOF_PARSING
            },
            cmcd: {
                enabled: false,
                sid: null,
                cid: null,
                rtp: null,
                rtpSafetyFactor: 5,
                mode: Constants.CMCD_MODE_QUERY
            }
        }
HIDE

Protected Content

For most protection schemes, the license server information (URL & init data) is included in the manifest. The notable exception to this is Widevine-Modular (WV). To playback WV content, you must provide the URL to a Widevine license server proxy through "keySystem" array when using the player.src() function. Detailed information about using DRM through Dash.js you can find here.
Code snippet
<script>
var protectionData = {
"com.widevine.alpha": { "serverURL": "http://m.widevine.com/proxy" }
};
player.src({
src: 'http://example.com/my/manifest.mpd',
type: 'application/dash+xml',
keySystemOptions: protectionData
});
</script>

DRM specific headers

Code snippet
<script>
var protectionData = {
"com.widevine.alpha": {
"serverURL": "http://m.widevine.com/proxy",
"httpRequestHeaders": {
"X-AxDRM-Message": "key"
},
priority: 0
}
};
player.src({
src: 'http://example.com/my/manifest.mpd',
type: 'application/dash+xml',
keySystemOptions: protectionData
});
You can access dash player instance as player.dash.mediaPlayer. This way you can track dash events, use dash player methods, etc.
Code snippet
<script>
var dashVersion = player.dash.mediaPlayer.getVersion();
var metrics = player.dash.mediaPlayer.getDashMetrics();
</script>