Browse Source

Factor out and improve media fragment parser

tags/v0.1.0
Gerben 4 years ago
parent
commit
99bc635cd9
2 changed files with 45 additions and 9 deletions
  1. +7
    -9
      app/audio-player/contentscript.js
  2. +38
    -0
      app/util/parse-media-fragment-identifier.js

+ 7
- 9
app/audio-player/contentscript.js View File

@@ -1,6 +1,8 @@
import * as WaveformPlaylist from 'waveform-playlist'; import * as WaveformPlaylist from 'waveform-playlist';
import delay from 'delay'; import delay from 'delay';


import parseMediaFragmentIdentifier from '../util/parse-media-fragment-identifier.js';

async function init() { async function init() {
document.body.innerHTML = ` document.body.innerHTML = `
<main> <main>
@@ -46,15 +48,11 @@ async function init() {


const fragmentIdentifier = window.location.hash; const fragmentIdentifier = window.location.hash;
if (fragmentIdentifier) { if (fragmentIdentifier) {
const match = fragmentIdentifier.match(/#t=(\d+(?:\.\d+)?)?(?:,(\d+(?:\.\d+)?))?/);
if (match) {
if (match[1] !== undefined) {
start = Number.parseFloat(match[1]);
}
if (match[2] !== undefined) {
end = Number.parseFloat(match[2]);
}
}
try {
const parsed = parseMediaFragmentIdentifier(fragmentIdentifier);
start = parsed.start;
end = parsed.end;
} catch (err) {}
} }


// Emit event to update selection in player // Emit event to update selection in player


+ 38
- 0
app/util/parse-media-fragment-identifier.js View File

@@ -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 };
}

Loading…
Cancel
Save