|
- // Functions for parsing and creating a media fragment identifiers.
- // A media fragment is used to specify a time range of an audio/video track, e.g. #t=12,18.5.
- // See https://www.w3.org/TR/media-frags/
-
- // Creates a media fragment identifier for a given time range (in seconds).
- export function createMediaFragmentIdentifier({ start, end }) {
- // Always output the time in seconds, as it is more widely supported than h:m:s syntax.
- const maybeStart = start !== undefined ? start : '';
- const maybeEnd = end !== undefined ? `,${end}` : '';
- const fragmentIdentifier = `t=${maybeStart}${maybeEnd}`;
- return fragmentIdentifier;
- }
-
- // Parses the time range from a media fragment identifier.
- // Returns an object { start, end }; both numbers are given in seconds (possibly non-integer).
- // Note this only supports the usual npt (normal playing time) format, not smpte or wall clock time.
- export 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 };
- }
|