diff --git a/package.json b/package.json index 568161b1..6efc9b57 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "keyboardjs": "^2.3.3", "lodash": "^4.16.4", "mime-types": "^2.1.14", + "moment": "^2.18.1", "react": "^15.3.2", "react-dom": "^15.3.2", "react-hammerjs": "^0.5.0", diff --git a/src/ffmpeg.js b/src/ffmpeg.js index 2b70d157..ffb37865 100644 --- a/src/ffmpeg.js +++ b/src/ffmpeg.js @@ -6,6 +6,8 @@ const fs = require('fs'); const fileType = require('file-type'); const readChunk = require('read-chunk'); const _ = require('lodash'); +const readline = require('readline'); +const moment = require('moment'); const util = require('./util'); @@ -35,7 +37,25 @@ function getFfmpegPath() { }); } -function cut(customOutDir, filePath, format, cutFrom, cutTo) { +function handleProgress(process, cutDuration, onProgress) { + const rl = readline.createInterface({ input: process.stderr }); + rl.on('line', (line) => { + try { + const match = line.match(/frame=\s*[^\s]+\s+fps=\s*[^\s]+\s+q=\s*[^\s]+\s+(?:size|Lsize)=\s*[^\s]+\s+time=\s*([^\s]+)\s+/); // eslint-disable-line max-len + if (!match) return; + + const str = match[1]; + console.log(str); + const progressTime = moment.duration(str).asSeconds(); + console.log(progressTime); + onProgress(progressTime / cutDuration); + } catch (err) { + console.log('Failed to parse ffmpeg progress line', err); + } + }); +} + +function cut(customOutDir, filePath, format, cutFrom, cutTo, onProgress) { return bluebird.try(() => { const extWithoutDot = path.extname(filePath) || `.${format}`; const ext = `.${extWithoutDot}`; @@ -54,8 +74,14 @@ function cut(customOutDir, filePath, format, cutFrom, cutTo) { console.log('ffmpeg', ffmpegArgs.join(' ')); + onProgress(0); + return getFfmpegPath() - .then(ffmpegPath => execa(ffmpegPath, ffmpegArgs)) + .then((ffmpegPath) => { + const process = execa(ffmpegPath, ffmpegArgs); + handleProgress(process, cutTo - cutFrom, onProgress); + return process; + }) .then((result) => { console.log(result.stdout); }); diff --git a/src/renderer.jsx b/src/renderer.jsx index 44f5841f..fe4e450b 100644 --- a/src/renderer.jsx +++ b/src/renderer.jsx @@ -163,6 +163,10 @@ class App extends React.Component { if (!this.state.cutEndTime) this.setState({ cutEndTime: duration }); } + onCutProgress(cutProgress) { + this.setState({ cutProgress }); + } + setCutStart() { this.setState({ cutStartTime: this.state.currentTime }); } @@ -248,7 +252,14 @@ class App extends React.Component { this.setState({ working: true }); const outputDir = this.state.outputDir; const fileFormat = this.state.fileFormat; - return ffmpeg.cut(outputDir, filePath, fileFormat, cutStartTime, cutEndTime) + return ffmpeg.cut( + outputDir, + filePath, + fileFormat, + cutStartTime, + cutEndTime, + progress => this.onCutProgress(progress), + ) .catch((err) => { console.error('stdout:', err.stdout); console.error('stderr:', err.stderr); @@ -278,9 +289,15 @@ class App extends React.Component { render() { return (