|
@@ -0,0 +1,38 @@ |
|
|
|
|
|
// Parses the time range from a media fragment identifier such as '#t=12.5,1:59:45.12'. |
|
|
|
|
|
// See https://www.w3.org/TR/media-frags/ |
|
|
|
|
|
// Note this only supports npt (normal playing time) format, not smpte or wall clock time. |
|
|
|
|
|
// Returns an object { start, end }; both numbers are given in seconds (possibly non-integer). |
|
|
|
|
|
export default function parseMediaFragmentIdentifier(fragmentIdentifier) { |
|
|
|
|
|
// Strip possible leading hash character '#'. |
|
|
|
|
|
if (fragmentIdentifier.startsWith('#')) { |
|
|
|
|
|
fragmentIdentifier = fragmentIdentifier.substring(1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const temporalDimensionRegex = /(?:^|&)(?:t|%74)=([^&]+)(?=&|$)/g; |
|
|
|
|
|
const temporalDimensionMatches = [...fragmentIdentifier.matchAll(temporalDimensionRegex)]; |
|
|
|
|
|
if (temporalDimensionMatches.length === 0) { |
|
|
|
|
|
throw new Error('No time dimension defined'); |
|
|
|
|
|
} |
|
|
|
|
|
// If there are multiple occurrences (e.g. t=1&t=2), take the last one. |
|
|
|
|
|
const temporalDimensionMatch = temporalDimensionMatches[temporalDimensionMatches.length - 1]; |
|
|
|
|
|
const temporalDimensionValue = decodeURIComponent(temporalDimensionMatch[1]); |
|
|
|
|
|
|
|
|
|
|
|
const nptRegex = /^(?:npt:)?(?:(?:(\d+):)??(?:(\d+):)?(\d+(?:\.\d*)?))?(?:,(?:(\d+):)??(?:(\d+):)?(\d+(?:\.\d*)?))?$/; |
|
|
|
|
|
const nptMatch = temporalDimensionValue.match(nptRegex); |
|
|
|
|
|
if (!nptMatch) { |
|
|
|
|
|
throw new Error('Unable to parse fragment identifier.'); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const start = (nptMatch[3] ? Number.parseFloat(nptMatch[3]) : 0) |
|
|
|
|
|
+ (nptMatch[2] ? Number.parseInt(nptMatch[2]) * 60 : 0) |
|
|
|
|
|
+ (nptMatch[1] ? Number.parseInt(nptMatch[1]) * 60 * 60 : 0); |
|
|
|
|
|
|
|
|
|
|
|
let end; |
|
|
|
|
|
if (nptMatch[6]) { |
|
|
|
|
|
end = Number.parseFloat(nptMatch[6]) |
|
|
|
|
|
+ (nptMatch[5] ? Number.parseInt(nptMatch[5]) * 60 : 0) |
|
|
|
|
|
+ (nptMatch[4] ? Number.parseInt(nptMatch[4]) * 60 * 60 : 0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return { start, end }; |
|
|
|
|
|
} |