From 25735fcb34ea5a416009b3aa3e9d57291539116d Mon Sep 17 00:00:00 2001 From: Bettina Steger Date: Thu, 27 May 2021 20:02:01 +0200 Subject: [PATCH] add bufferToVideo and fetchVideo (#54) * add bufferToVideo and fetchVideo * fixes for mov videos * use oncanplay instead of timeout --- src/dom/bufferToVideo.ts | 16 ++++++++++++++++ src/dom/fetchVideo.ts | 12 ++++++++++++ src/dom/index.ts | 1 + src/env/createBrowserEnv.ts | 1 + src/env/createNodejsEnv.ts | 8 ++++++++ src/env/types.ts | 1 + 6 files changed, 39 insertions(+) create mode 100644 src/dom/bufferToVideo.ts create mode 100644 src/dom/fetchVideo.ts diff --git a/src/dom/bufferToVideo.ts b/src/dom/bufferToVideo.ts new file mode 100644 index 0000000..6e0a6ee --- /dev/null +++ b/src/dom/bufferToVideo.ts @@ -0,0 +1,16 @@ +import { env } from '../env/index'; + +export function bufferToVideo(buf: Blob): Promise { + return new Promise((resolve, reject) => { + if (!(buf instanceof Blob)) reject(new Error('bufferToVideo - expected buf to be of type: Blob')); + + const video = env.getEnv().createVideoElement(); + video.oncanplay = () => resolve(video); + video.onerror = reject; + video.type = buf.type; + video.playsInline = true; + video.autoplay = true; + video.muted = true; + video.src = URL.createObjectURL(buf); + }); +} diff --git a/src/dom/fetchVideo.ts b/src/dom/fetchVideo.ts new file mode 100644 index 0000000..de83a50 --- /dev/null +++ b/src/dom/fetchVideo.ts @@ -0,0 +1,12 @@ +import { bufferToVideo } from './bufferToVideo'; +import { fetchOrThrow } from './fetchOrThrow'; + +export async function fetchVideo(uri: string): Promise { + const res = await fetchOrThrow(uri); + const blob = await (res).blob(); + + if (!blob.type.startsWith('video/')) { + throw new Error(`fetchVideo - expected blob type to be of type video/*, instead have: ${blob.type}, for url: ${res.url}`); + } + return bufferToVideo(blob); +} diff --git a/src/dom/index.ts b/src/dom/index.ts index 10e5aff..0767f72 100644 --- a/src/dom/index.ts +++ b/src/dom/index.ts @@ -7,6 +7,7 @@ export * from './fetchImage'; export * from './fetchJson'; export * from './fetchNetWeights'; export * from './fetchOrThrow'; +export * from './fetchVideo'; export * from './getContext2dOrThrow'; export * from './getMediaDimensions'; export * from './imageTensorToCanvas'; diff --git a/src/env/createBrowserEnv.ts b/src/env/createBrowserEnv.ts index f9d6124..e4035ad 100644 --- a/src/env/createBrowserEnv.ts +++ b/src/env/createBrowserEnv.ts @@ -16,6 +16,7 @@ export function createBrowserEnv(): Environment { Video: HTMLVideoElement, createCanvasElement: () => document.createElement('canvas'), createImageElement: () => document.createElement('img'), + createVideoElement: () => document.createElement('video'), fetch, readFile, }; diff --git a/src/env/createNodejsEnv.ts b/src/env/createNodejsEnv.ts index 3f624a4..bb7bbb9 100644 --- a/src/env/createNodejsEnv.ts +++ b/src/env/createNodejsEnv.ts @@ -6,6 +6,8 @@ export function createNodejsEnv(): Environment { // eslint-disable-next-line dot-notation const Canvas = global['Canvas'] || global.HTMLCanvasElement; const Image = global.Image || global.HTMLImageElement; + // eslint-disable-next-line dot-notation + const Video = global['Video'] || global.HTMLVideoElement; const createCanvasElement = () => { if (Canvas) return new Canvas(); @@ -17,6 +19,11 @@ export function createNodejsEnv(): Environment { throw new Error('createImageElement - missing Image implementation for nodejs environment'); }; + const createVideoElement = () => { + if (Video) return new Video(); + throw new Error('createVideoElement - missing Video implementation for nodejs environment'); + }; + const fetch = global.fetch; // if (!fetch) throw new Error('fetch - missing fetch implementation for nodejs environment'); @@ -30,6 +37,7 @@ export function createNodejsEnv(): Environment { Video: global.HTMLVideoElement || class {}, createCanvasElement, createImageElement, + createVideoElement, fetch, ...fileSystem, }; diff --git a/src/env/types.ts b/src/env/types.ts index ba02a38..ebaf715 100644 --- a/src/env/types.ts +++ b/src/env/types.ts @@ -11,6 +11,7 @@ export type Environment = FileSystem & { Video: typeof HTMLVideoElement createCanvasElement: () => HTMLCanvasElement createImageElement: () => HTMLImageElement + createVideoElement: () => HTMLVideoElement // eslint-disable-next-line no-undef, no-unused-vars fetch: (url: string, init?: RequestInit) => Promise }