feat: hls daterange tag support

This commit is contained in:
wudechang 2024-07-04 14:32:18 +08:00 committed by gemstone
parent c66b884c9c
commit 5e135dd690
4 changed files with 85 additions and 1 deletions

View File

@ -161,6 +161,12 @@ window.onload = function () {
player.on('retry', function (event) { pushEvent('retry', event) })
player.on('core_event', function (event) { pushEvent(event.eventName, event) })
player.on('error', function (event) { pushEvent(event.errorType, event, dlError) })
player.on('core_event', (info) => {
const { eventName, playlist } = info
if (eventName === 'core.hlslevelloaded' && playlist) {
console.log('playlist1111', playlist)
}
})
dStreamForce.checked = true
function refreshStreams() {

View File

@ -1,5 +1,5 @@
import { MediaPlaylist, MediaSegment, MediaSegmentKey } from './model'
import { getAbsoluteUrl, parseAttr, parseTag } from './utils'
import { getAbsoluteUrl, parseAttr, parseTag, isValidDaterange } from './utils'
export function parseMediaPlaylist (lines, parentUrl, useLowLatency) {
const media = new MediaPlaylist()
@ -156,6 +156,27 @@ export function parseMediaPlaylist (lines, parentUrl, useLowLatency) {
curSegment = new MediaSegment(parentUrl)
}
break
case 'SKIP': {
const attr = parseAttr(data)
const skippedSegments = parseInt(attr['SKIPPED-SEGMENTS'], 10)
if (skippedSegments <= Number.MAX_SAFE_INTEGER) {
media.skippedSegments += skippedSegments
}
}
break
case 'DATERANGE': {
const attr = parseAttr(data)
const dateRangeWithSameId = media.dateRanges[attr.ID]
attr._startDate = dateRangeWithSameId ? dateRangeWithSameId._startDate : new Date(attr['START-DATE'])
const endDate = dateRangeWithSameId?._endDate || new Date(attr.END_DATE)
if (Number.isFinite(endDate)) {
attr._endDate = endDate
}
if (isValidDaterange(attr, dateRangeWithSameId) || media.skippedSegments) {
media.dateRanges[attr.ID] = attr
}
}
break
default:
}
}

View File

@ -110,6 +110,8 @@ export class MediaPlaylist {
endPartIndex = 0
/** @type {Array.<MediaSegment>} */
segments = []
dateRanges = {}
skippedSegments = 0
}
export class MediaSegment {

View File

@ -51,3 +51,58 @@ export function getCodecs (type, codecs) {
}
}
}
export function isValidDaterange(attr, dateRangeWithSameId) {
let _badValueForSameId
if (dateRangeWithSameId) {
for (const key in dateRangeWithSameId) {
if (
Object.prototype.hasOwnProperty.call(dateRangeWithSameId, key) &&
attr[key] !== dateRangeWithSameId[key]
) {
_badValueForSameId = key;
break;
}
}
}
let duration = null
if (attr.DURATION) {
duration = parseFloat(attr.DURATION)
if (!Number.isFinite(duration)) {
duration = null
} else if (attr._endDate) {
duration = (attr._endDate.getTime() - attr._startDate.getTime()) / 1000
}
}
const cue = enumeratedStringList(attr.CUE || attr['X-CUE'], {
pre: false,
post: false,
once: false,
})
return (
!!attr.ID &&
!_badValueForSameId &&
Number.isFinite(attr._startDate.getTime()) &&
(duration === null || duration >= 0) &&
(!(attr.END_ON_NEXT === 'YES') || !!attr.CLASS) &&
(!attr.CUE ||
(!cue.pre && !cue.post) ||
cue.pre !== cue.post) &&
(!(attr.CLASS === 'com.apple.hls.interstitial') ||
'X-ASSET-URI' in attr ||
'X-ASSET-LIST' in attr)
);
}
function enumeratedStringList(attrValue, dict) {
return (attrValue ? attrValue.split(/[ ,]+/) : []).reduce(
(result, identifier) => {
result[identifier.toLowerCase()] = true;
return result;
},
dict,
);
}