diff --git a/package.json b/package.json index d5f8f628..6357b738 100644 --- a/package.json +++ b/package.json @@ -47,12 +47,14 @@ "electron": "^1.4.5", "electron-default-menu": "^1.0.0", "execa": "^0.5.0", + "file-type": "^3.9.0", "jquery": "^3.1.1", "keyboardjs": "^2.3.3", "lodash": "^4.16.4", "react": "^15.3.2", "react-dom": "^15.3.2", "react-hammerjs": "^0.5.0", + "read-chunk": "^2.0.0", "which": "^1.2.11" } } diff --git a/src/ffmpeg.js b/src/ffmpeg.js index 7f12a977..844546c3 100644 --- a/src/ffmpeg.js +++ b/src/ffmpeg.js @@ -2,8 +2,12 @@ const execa = require('execa'); const bluebird = require('bluebird'); const which = bluebird.promisify(require('which')); const path = require('path'); -const util = require('./util'); const fs = require('fs'); +const fileType = require('file-type'); +const readChunk = require('read-chunk'); +const _ = require('lodash'); + +const util = require('./util'); bluebird.promisifyAll(fs); @@ -56,7 +60,7 @@ function cut(filePath, format, cutFrom, cutTo) { }); } -function getFormats(filePath) { +function getFormat(filePath) { return bluebird.try(() => { console.log('getFormat', filePath); @@ -68,14 +72,21 @@ function getFormats(filePath) { .then((result) => { const formatsStr = JSON.parse(result.stdout).format.format_name; console.log('formats', formatsStr); - const formats = formatsStr.split(','); - return formats; + const formats = (formatsStr || '').split(','); + + // ffprobe sometimes returns a list of formats, try to be a bit smarter about it. + return readChunk(filePath, 0, 262) + .then((bytes) => { + const ft = fileType(bytes); + if (_.includes(formats, ft.ext)) return ft.ext; + return formats[0] || undefined; + }); }); }); } module.exports = { cut, - getFormats, + getFormat, showFfmpegFail, }; diff --git a/src/menu.js b/src/menu.js index 9d2fea1f..da8b4fa5 100644 --- a/src/menu.js +++ b/src/menu.js @@ -19,8 +19,8 @@ module.exports = (app, mainWindow) => { label: 'Open', accelerator: 'CmdOrCtrl+O', click() { - dialog.showOpenDialog({ properties: ['openFile'] }, (data) => { - mainWindow.webContents.send('file-opened', data); + dialog.showOpenDialog({ properties: ['openFile'] }, (filePaths) => { + mainWindow.webContents.send('file-opened', filePaths); }); }, }, diff --git a/src/renderer.jsx b/src/renderer.jsx index afdc9043..b319af0b 100644 --- a/src/renderer.jsx +++ b/src/renderer.jsx @@ -65,15 +65,17 @@ class App extends React.Component { }; const load = (filePath) => { + console.log('Load', filePath); if (this.state.working) return alert('I\'m busy'); resetState(); this.setState({ working: true }); - return ffmpeg.getFormats(filePath) - .then((formats) => { - if (formats.length < 1) return alert('Unsupported file'); - return this.setState({ filePath, fileFormat: formats[0] }); + + return ffmpeg.getFormat(filePath) + .then((fileFormat) => { + if (!fileFormat) return alert('Unsupported file'); + return this.setState({ filePath, fileFormat }); }) .catch((err) => { if (err.code === 1) { @@ -85,9 +87,9 @@ class App extends React.Component { .finally(() => this.setState({ working: false })); }; - electron.ipcRenderer.on('file-opened', (event, message) => { - if (!message) return; - load(message); + electron.ipcRenderer.on('file-opened', (event, filePaths) => { + if (!filePaths || filePaths.length !== 1) return; + load(filePaths[0]); }); document.ondragover = document.ondragend = ev => ev.preventDefault(); diff --git a/test/formats.sh b/test/formats.sh index d165a153..c1871fe0 100755 --- a/test/formats.sh +++ b/test/formats.sh @@ -1 +1 @@ -for f in sample-videos/*; do echo -n "$f: "; ffprobe -show_format -of json -i "$f" | json format.format_name; done 2> /dev/null +for f in *; do echo -n "$f: "; ffprobe -show_format -of json -i "$f" | json format.format_name; done 2> /dev/null