1
0
mirror of https://github.com/mifi/lossless-cut.git synced 2024-11-22 02:12:30 +01:00

Implement partial speed control

J, K, L, however backward playing is not supported by chromium.
Also bump electron to 1.4.5
And don't use electron-compile anymore as it doesn't really give us anything
This commit is contained in:
Mikael Finstad 2016-11-03 20:16:27 +01:00
parent 95ed72edef
commit 2abacd010d
4 changed files with 50 additions and 13 deletions

View File

@ -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
- <kbd>SPACE</kbd> Play/pause
- <kbd>SPACE</kbd>, <kbd>k</kbd> Play/pause
- <kbd>j</kbd> Slow down video
- <kbd>l</kbd> Speed up video
- <kbd></kbd> Seek backward 1 sec
- <kbd></kbd> Seek forward 1 sec
- <kbd>.</kbd> (period) Tiny seek forward

View File

@ -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",

View File

@ -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);

View File

@ -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 {
<div id="player">
<video
src={this.state.filePath}
onPlay={() => this.setState({ playing: true })}
onPause={() => this.setState({ playing: false })}
onRateChange={() => this.playbackRateChange()}
onPlay={() => this.onPlay(true)}
onPause={() => this.onPlay(false)}
onDurationChange={e => this.setState({ duration: e.target.duration })}
onTimeUpdate={e => this.setState({ currentTime: e.target.currentTime })}
/>
@ -264,6 +294,9 @@ class App extends React.Component {
</div>
<div className="right-menu">
<button className="playback-rate" title="Playback rate">
{_.round(this.state.playbackRate, 1) || 1}x
</button>
<i
title="Capture frame"
className="button fa fa-camera"