layers_GoProVideoLayer.js
import * as THREE from "three";
import { ProjectedLayer } from "./ProjectedLayer.js";
const gpmfExtract = require('gpmf-extract');
const goproTelemetry = require('gopro-telemetry');
let id = 0;
class GoProVideoLayer extends ProjectedLayer {
/**
* construct a projected layer that will project a three.js onto other loaded geospatial data from the given perspective.
* @param {Object} properties
* @param {String|Number} properties.id layer id should be unique
* @param {String} properties.name the name can be anything you want and is intended for labeling
* @param {String} videoURL url to a video
* @param {Boolean} [properties.depthTest = true] depth test prevents drawing the projected texture behind occluders but the precision is limitted at long distances
* @param {Boolean} [properties.visible = true] layer will be rendered if true (true by default)
* @param {Boolean} [showFrustum = true] show the projection camera frustum
*/
constructor(properties) {
super(properties);
const self = this;
self.video = document.createElement('video');
self.video.addEventListener('timeupdate', () => {
self._interpolatedTelemetry(self.video.currentTime*1000);
});
//self.video.src = properties.video; // video file path
self._fetchVideoAsBlob(properties.videoURL).then((blob) => {
const blobUrl = URL.createObjectURL(blob);
self.video.src = blobUrl;
self.video.crossOrigin = 'anonymous'; // Enable CORS if needed
self.video.loop = true; // Optional: loop the video
self.video.muted = true; // Optional: mute the video to allow autoplay
self.video.playsInline = true; // For iOS Safari
const file = new File([blob], id + ".mp4", { type: blob.type });
gpmfExtract(file, { browserMode: true, useWorker: true }).then(res => {
goproTelemetry(res, { decimalPlaces:"9", progress: self._progress, groupTimes:"frames"}, telemetry => {
self.telemetry = telemetry;
self.video.play();
});
});
});
}
_progress(p){
console.log(p);
}
async _fetchVideoAsBlob(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const blob = await response.blob();
return blob;
}
_getInterpolatedTelemetry(currentTime) {
//TODO interpolate or pick telemetry matching the current time and update camera
//this.setCameraFromLLHYawPitchRollFov(llh, yaw, pitch, roll, fov);
return null;
}
}
export { GoProVideoLayer };