diff options
author | lonkaars <loek@pipeframe.xyz> | 2021-07-24 16:55:07 +0200 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2021-07-24 16:55:07 +0200 |
commit | def71ea56c99873af04dadc1c0e801d42c406826 (patch) | |
tree | a083576cf451f6370c273d5d4586ac02aaa10998 | |
parent | ff0609458ab50dd627b13b604f7c8c42af9a67b3 (diff) |
import net video saves in the cool new file format :tada:
-rw-r--r-- | components/videosourcesettings.tsx | 15 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | pages/editor.tsx | 13 | ||||
-rw-r--r-- | project.ts | 18 | ||||
-rw-r--r-- | yarn.lock | 24 |
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(); }} @@ -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')); + } } } @@ -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" |