diff --git a/README.md b/README.md index fd73e2c6..125ccde4 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,9 @@ Simple, cross platform video editor for lossless trimming / cutting of videos. G The original video files will not be modified. Instead it creates a lossless export in the same directory as the original file with from/to timestamps. Note that the cut is currently not precise around the cutpoints, so video before/after the nearest keyframe will be lost. EXIF data is preserved. ### Keyboard shortcuts -- SPACE Play/pause +- SPACE, k Play/pause +- j Slow down video +- l Speed up video - ← Seek backward 1 sec - → Seek forward 1 sec - . (period) Tiny seek forward diff --git a/package.json b/package.json index 8b2dd70d..60a0fdeb 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,12 @@ "description": "", "main": "index.js", "scripts": { - "start": "electron src", - "build": "rm -rf dist && babel src -d dist --copy-files && ln -s ../node_modules dist/ && ln -s ../package.json ./dist/", + "start": "electron dist", "watch": "npm run build && babel src -d dist --copy-files -w", - "start-dist": "./node_modules/electron-prebuilt-compile/node_modules/electron/cli.js dist", + "build": "rm -rf dist && babel src -d dist --copy-files && ln -s ../node_modules dist/ && ln -s ../package.json ./dist/", "package": "electron-packager dist LosslessCut --out=package --asar --overwrite --all --version 1.3.8", + "zip": "(cd package && for f in LosslessCut-*; do zip -r $f; done)", + "gifify": "gifify -p 405:299 -r 5@3 Untitled.mov-00.00.00.971-00.00.19.780.mp4", "lint": "eslint ." }, "author": { @@ -20,8 +21,8 @@ "devDependencies": { "babel-cli": "^6.18.0", "babel-preset-es2015": "^6.18.0", + "babel-preset-react": "^6.16.0", "electron-packager": "^8.1.0", - "electron-prebuilt-compile": "^1.4.4", "eslint": "^3.8.0", "eslint-config-airbnb": "^12.0.0", "eslint-plugin-import": "^1.16.0", @@ -33,6 +34,7 @@ "capture-frame": "^1.0.0", "classnames": "^2.2.5", "configstore": "^2.1.0", + "electron": "^1.4.5", "electron-default-menu": "^1.0.0", "execa": "^0.5.0", "jquery": "^3.1.1", diff --git a/src/main.css b/src/main.css index f229514a..1230d30a 100644 --- a/src/main.css +++ b/src/main.css @@ -38,7 +38,7 @@ input, button, textarea, :focus { padding: .4em; } -.jump-cut-start, .jump-cut-end { +.jump-cut-start, .jump-cut-end, .playback-rate { background: white; border-radius: .3em; color: rgba(0, 0, 0, 0.7); diff --git a/src/renderer.jsx b/src/renderer.jsx index 807a8e06..20dc5757 100644 --- a/src/renderer.jsx +++ b/src/renderer.jsx @@ -57,7 +57,7 @@ class App extends React.Component { const defaultState = { working: false, - filePath: '', // Setting video src="" prevents memory leak + filePath: '', // Setting video src="" prevents memory leak in chromium playing: false, currentTime: undefined, duration: undefined, @@ -67,7 +67,12 @@ class App extends React.Component { this.state = _.cloneDeep(defaultState); - const resetState = () => this.setState(defaultState); + const resetState = () => { + const video = getVideo(); + video.currentTime = 0; + video.playbackRate = 1; + this.setState(defaultState); + }; const load = (filePath) => { resetState(); @@ -88,6 +93,9 @@ class App extends React.Component { }; keyboardJs.bind('space', () => this.playCommand()); + keyboardJs.bind('k', () => this.playCommand()); + keyboardJs.bind('j', () => this.changePlaybackRate(-1)); + keyboardJs.bind('l', () => this.changePlaybackRate(1)); keyboardJs.bind('left', () => seekRel(-1)); keyboardJs.bind('right', () => seekRel(1)); keyboardJs.bind('period', () => shortStep(1)); @@ -98,6 +106,14 @@ class App extends React.Component { keyboardJs.bind('o', () => this.setCutEnd()); } + onPlay(playing) { + this.setState({ playing }); + + if (!playing) { + getVideo().playbackRate = 1; + } + } + setCutStart() { this.setState({ cutStartTime: this.state.currentTime }); } @@ -125,11 +141,24 @@ class App extends React.Component { setCursor((relX / $target[0].offsetWidth) * this.state.duration); } + changePlaybackRate(dir) { + const video = getVideo(); + if (!this.state.playing) { + video.playbackRate = 0.5; // dir * 0.5; + video.play(); + } else { + const newRate = video.playbackRate + (dir * 0.15); + video.playbackRate = _.clamp(newRate, 0.05, 16); + } + } + + playbackRateChange() { + this.state.playbackRate = getVideo().playbackRate; + } + playCommand() { const video = getVideo(); - if (this.state.playing) { - return video.pause(); - } + if (this.state.playing) return video.pause(); return video.play().catch((err) => { console.log(err); @@ -176,8 +205,9 @@ class App extends React.Component {