wfm/js/main.js

182 lines
5.8 KiB
JavaScript
Raw Normal View History

2023-03-02 12:56:08 +00:00
import Plyr from '../vendor/plyr-3.7.3.mjs';
const container = document.getElementById('container');
function displayError(message) {
const errorBox = document.createElement('div');
errorBox.classList.add('error');
errorBox.innerText = message;
container.appendChild(errorBox);
throw new Error(); // abort
}
function loadPlaybackState(videoUrl) {
const item = localStorage.getItem('wfm__playerstate');
if (item) {
const data = JSON.parse(item);
if (Object.prototype.hasOwnProperty.call(data, videoUrl)) {
return data[videoUrl];
}
}
return {
time: 0,
};
}
function savePlaybackState(videoUrl, state) {
const item = localStorage.getItem('wfm__playerstate');
let data;
if (item) {
data = JSON.parse(item);
} else {
data = {};
}
data[videoUrl] = state;
localStorage.setItem('wfm__playerstate', JSON.stringify(data));
}
function parseQuery() {
if (window.location.hash.length > 1) {
const qs = window.location.hash.substring(1);
const query = new URLSearchParams(qs);
const source = query.get('source');
const sourceType = query.get('source_type');
const captions = query.getAll('captions');
const captionLanguages = query.getAll('caption_langs');
const captionLabels = query.getAll('caption_labels');
if (!source || !sourceType) {
displayError('missing source or sourceType parameter');
}
if (captions.length !== captionLanguages.length || captions.length !== captionLabels.length) {
displayError('mismatch between captions, caption_langs and caption_labels length');
}
return {
source, sourceType,
captions, captionLanguages, captionLabels,
}
} else {
return null;
}
}
function parseTimestamp(timestamp) {
const results = /^(0|[1-9]+):([0-9]{2}):([0-9]{2}).([0-9]+)$/g.exec(timestamp);
const [_, hours, mins, secs, frac] = results;
return {
hours, mins, secs, frac,
};
}
function formatTimestamp({ hours, mins, secs, frac }) {
const ms = `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
if (hours !== 0) {
return `${hours}:${ms}`;
} else {
return ms;
}
}
const query = parseQuery();
if (query !== null) {
const {
source, sourceType,
captions, captionLanguages, captionLabels
} = query;
const video = document.createElement('video');
video.controls = true;
video.crossOrigin = 'anonymous';
const sourceEle = document.createElement('source');
sourceEle.src = source;
sourceEle.type = sourceType;
video.appendChild(sourceEle);
for (let i = 0; i < captions.length; i++) {
const url = captions[i];
const lang = captionLanguages[i];
const label = captionLabels[i];
const track = document.createElement('track');
track.kind = 'subtitles';
track.label = label;
track.srclang = lang;
track.src = url;
video.appendChild(track);
}
video.autoplay = true;
container.appendChild(video);
const player = new Plyr(video, {
captions: {
active: true,
},
iconUrl: 'vendor/plyr-3.7.3.svg',
});
player.on('ready', () => {
const state = loadPlaybackState(source);
console.log('setting start time', state);
player.currentTime = state.time;
console.log(player.currentTime);
});
player.on('timeupdate', () => {
savePlaybackState(source, {
time: player.currentTime,
});
});
} else {
const BASE = '/videos/';
fetch(BASE+'media.json')
.then(res => res.json())
.then(({ videos }) => {
const ul = document.createElement('ul');
ul.classList.add('video-list');
for (const video of videos) {
//if (!video.filename.includes('telescope')) continue;
const query = [
['source', BASE+video.filename],
['source_type', 'video/mp4'],
...video.subtitles.map(subName => ['captions', BASE+subName]),
...video.subtitles.map(subName => {
const s = subName.split('.');
return ['caption_langs', s[s.length - 2]];
}),
...video.subtitles.map(subName => ['caption_labels', subName]),
];
const duration = parseTimestamp(video.duration);
const thumbnail = video.thumbnail;
const thumbnailContainer = document.createElement('div');
thumbnailContainer.classList.add('thumbnail-container');
const durationEle = document.createElement('p');
durationEle.classList.add('thumbnail-duration');
durationEle.innerText = formatTimestamp(duration);
const img = document.createElement('img');
img.src = BASE+thumbnail;
img.classList.add('thumbnail');
const qs = new URLSearchParams(query).toString();
const ele = document.createElement('li');
const a = document.createElement('a');
a.classList.add('video-card');
a.href = '#' + qs;
const title = document.createElement('h2');
title.innerText = video.filename;
thumbnailContainer.appendChild(img);
thumbnailContainer.appendChild(durationEle);
a.appendChild(thumbnailContainer);
a.appendChild(title);
ele.appendChild(a);
ul.appendChild(ele);
}
container.appendChild(ul);
});
}
window.addEventListener('hashchange', (e) => {
window.location.reload();
});