aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--components/videosourcesettings.tsx15
-rw-r--r--package.json2
-rw-r--r--pages/editor.tsx13
-rw-r--r--project.ts18
-rw-r--r--yarn.lock24
5 files changed, 57 insertions, 15 deletions
diff --git a/components/videosourcesettings.tsx b/components/videosourcesettings.tsx
index ae7f75b..f4cea9e 100644
--- a/components/videosourcesettings.tsx
+++ b/components/videosourcesettings.tsx
@@ -1,12 +1,18 @@
import { useRef } from 'react';
-import { LocalVideo } from '../project';
+import { TimedVideoPlayer } from '../pages/present';
+import { arrayBufferToBase64, LocalVideo } from '../project';
import Button from '@material-ui/core/Button';
import Switch from '@material-ui/core/Switch';
import { UploadRoundedIcon } from './icons';
-export function LocalVideoSettings(props: { settings: LocalVideo; }) {
+type VideoSourceSettings = {
+ settings: LocalVideo;
+ player: TimedVideoPlayer;
+};
+
+export function LocalVideoSettings(props: VideoSourceSettings) {
var fileUploadRef = useRef(null);
return <>
@@ -20,7 +26,10 @@ export function LocalVideoSettings(props: { settings: LocalVideo; }) {
if (!file) return;
var reader = new FileReader();
reader.addEventListener('load', async ev => {
- props.settings.load(ev.target.result as ArrayBuffer);
+ var video = ev.target.result as ArrayBuffer;
+ props.settings.load(video);
+ props.settings.mimetype = file.type;
+ props.player.loadVideo(arrayBufferToBase64(video, file.type));
});
reader.readAsArrayBuffer(file);
}}
diff --git a/package.json b/package.json
index f59dfce..9637f4d 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"@mdi/js": "^5.9.55",
"@mdi/react": "^1.5.0",
"@types/mousetrap": "^1.6.8",
+ "@types/semver": "^7.3.8",
"@types/uuid": "^8.3.0",
"ajv": "^8.3.0",
"copy-webpack-plugin": "^9.0.1",
@@ -33,6 +34,7 @@
"react-dom": "^17.0.2",
"react-spring": "^9.1.2",
"react-use-gesture": "^9.1.3",
+ "semver": "^7.3.5",
"timecode-boss": "^4.2.3",
"ts-json-schema-generator": "^0.93.0",
"use-mousetrap": "^1.0.4",
diff --git a/pages/editor.tsx b/pages/editor.tsx
index 5a63cb4..b90ba7f 100644
--- a/pages/editor.tsx
+++ b/pages/editor.tsx
@@ -18,7 +18,7 @@ import KeybindSelector from '../components/keybindselector';
import PlaySkipIconAni from '../components/play-skip';
import Selection from '../components/selection';
import TimecodeInput from '../components/timeinput';
-import Project, { LocalVideo, VideoSources, VideoSourceType } from '../project';
+import Project, { arrayBufferToBase64, VideoSources, VideoSourceType } from '../project';
import timeline, {
anySlide,
clickThroughBehaviours,
@@ -1064,7 +1064,7 @@ function DefaultSettings() {
{(() => {
if (!projectFile.video) return null;
var SourceSettings = VideoSources.find(s => s.type == projectFile.video.type).settings;
- return <SourceSettings settings={projectFile.video} />;
+ return <SourceSettings settings={projectFile.video} player={player} />;
})()}
</div>
<div className={'section ' + (ready.timeline.value ? '' : 'disabled')}>
@@ -1094,10 +1094,7 @@ function DefaultSettings() {
global.update.refreshLiveTimeline.value();
global.ready.timeline.set(true);
- player.loadVideo(
- 'data:' + projectFile.video.mimetype + ';base64,'
- + btoa(String.fromCharCode.apply(null, new Uint8Array(projectFile.video.source))),
- );
+ player.loadVideo(arrayBufferToBase64(projectFile.video.source, projectFile.video.mimetype));
global.ready.video.available.set(true);
player.player.addEventListener(
@@ -1124,11 +1121,7 @@ function DefaultSettings() {
children='Download .prspr'
startIcon={<DescriptionRoundedIcon />}
onClick={async () => {
- var vidSrc = player.player.src.split(';');
projectFile.loadProject(player.timeline);
- projectFile.video = new LocalVideo();
- await projectFile.video.load(Uint8Array.from(atob(vidSrc[1].substr(7)), c => c.charCodeAt(0)));
- projectFile.video.mimetype = vidSrc[0].substr(5);
projectFile.saveProject();
projectFile.downloadProjectFile();
}}
diff --git a/project.ts b/project.ts
index 6bf561a..6ddd29b 100644
--- a/project.ts
+++ b/project.ts
@@ -1,5 +1,6 @@
import { MediaInfo as Mediainfo, ResultObject } from 'mediainfo.js/dist/types';
import JSZip from 'jszip';
+import semver from 'semver';
import { TimedVideoPlayer } from './pages/present';
import { LocalVideoSettings } from './components/videosourcesettings';
@@ -7,6 +8,13 @@ import { LocalVideoSettings } from './components/videosourcesettings';
// garbage garbage garbage
declare var MediaInfo: () => Promise<Mediainfo>;
+export function arrayBufferToBase64(buffer: ArrayBuffer, mimetype?: string) {
+ var out = '';
+ if (mimetype) out += 'data:' + mimetype + ';base64,';
+ out += btoa(new Uint8Array(buffer).reduce((data, byte) => data + String.fromCharCode(byte), ''));
+ return out;
+}
+
const filext = '.prspr';
interface VideoSource {
@@ -111,6 +119,8 @@ export default class {
async openProject(data: ArrayBuffer) {
this.zip = new JSZip();
await this.zip.loadAsync(data);
+
+ this.version = await this.zip.file('meta/version').async('string');
this.project = {
name: await this.zip.file('meta/name').async('string'),
settings: { controlType: await this.zip.file('settings/controlType').async('string') },
@@ -118,11 +128,15 @@ export default class {
framerate: Number(await this.zip.file('source/framerate').async('string')),
framecount: Number(await this.zip.file('source/framecount').async('string')),
} as TimedVideoPlayer['timeline'];
+
var type = await this.zip.file('source/type').async('string');
var videoSourceType = VideoSources.find(s => s.type == type);
- if (!videoSourceType) return;
+
this.video = new videoSourceType.class(await this.zip.file('source/video').async('arraybuffer'));
this.video.mimetype = await this.zip.file('source/mimetype').async('string');
- this.video.config = JSON.parse(await this.zip.file('source/config').async('string'));
+
+ if (semver.lt('0.1.1', this.version)) {
+ this.video.config = JSON.parse(await this.zip.file('source/config').async('string'));
+ }
}
}
diff --git a/yarn.lock b/yarn.lock
index bce5297..842521e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -357,6 +357,11 @@
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275"
integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==
+"@types/semver@^7.3.8":
+ version "7.3.8"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.8.tgz#508a27995498d7586dcecd77c25e289bfaf90c59"
+ integrity sha512-D/2EJvAlCEtYFEYmmlGwbGXuK886HzyCc3nZX/tkFTQdEU8jZDAgiv08P162yB17y4ZXZoq7yFAnW4GDBb9Now==
+
"@types/uuid@^8.3.0":
version "8.3.0"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f"
@@ -1606,6 +1611,13 @@ loose-envify@^1.1.0, loose-envify@^1.4.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
make-dir@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
@@ -2225,6 +2237,13 @@ semver@^6.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+semver@^7.3.5:
+ version "7.3.5"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
+ integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
+ dependencies:
+ lru-cache "^6.0.0"
+
serialize-javascript@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
@@ -2690,6 +2709,11 @@ y18n@^5.0.5:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
yargs-parser@^20.2.2:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"