diff --git a/package.json b/package.json index 549d56f..1a8ff12 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,14 @@ "version": "0.1.0", "dependencies": { "@babel/core": "^7.13.13", + "@ffmpeg/core": "^0.9.0", + "@ffmpeg/ffmpeg": "^0.9.8", "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", + "fork-me-on-github": "^1.0.6", "react": "^16.14.0", "react-copy-to-clipboard": "^5.0.3", "react-dom": "^16.14.0", diff --git a/src/ChecksumResolver.js b/src/ChecksumResolver.js index c4f3cb9..d1edc9e 100644 --- a/src/ChecksumResolver.js +++ b/src/ChecksumResolver.js @@ -25,7 +25,7 @@ import { FilePicker } from '../src/Components' import { CopyToClipboard } from 'react-copy-to-clipboard'; import ControlledAccordions from './ControlledAccordions' - +import OnlineConverter from "./OnlineConverter"; import 'react-notifications-component/dist/theme.css' import ReactNotification from 'react-notifications-component' @@ -179,7 +179,7 @@ class ChecksumResolver extends React.Component { // return; // } - this.setState({ fileName: file.name }); + this.setState({ fileName: file.name, file:file }); const slic = file.slice(653, 653 + 20); const results = this.buf2hex(await slic.arrayBuffer()); this.setChecksum(results) @@ -189,7 +189,7 @@ class ChecksumResolver extends React.Component { render() { const { classes } = this.props; - const { checksum, activationBytes, fileName } = this.state; + const { checksum, activationBytes, fileName, file } = this.state; // const { files, onClick, errors, HiddenFileInput } = useFilePicker({ // maxFileSize: 1000000, @@ -296,6 +296,7 @@ class ChecksumResolver extends React.Component { diff --git a/src/ControlledAccordions.js b/src/ControlledAccordions.js index 99d96da..d7b0b2e 100644 --- a/src/ControlledAccordions.js +++ b/src/ControlledAccordions.js @@ -21,6 +21,7 @@ import { Radio, RadioGroup } from '@material-ui/core'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import FormControl from '@material-ui/core/FormControl'; import FormLabel from '@material-ui/core/FormLabel'; +import OnlineConverter from "./OnlineConverter"; class ControlledAccordions extends React.Component { constructor(props) { @@ -71,7 +72,7 @@ class ControlledAccordions extends React.Component { { os: "osx", cmd: "./ffmpeg", discriminator: '\'' }, ]; - let fileNameWithoutExtension = fileName.split('.')[0]; + let fileNameWithoutExtension = fileName.split('.').slice(0, -1).join('.'); fileNameWithoutExtension = fileNameWithoutExtension == 'input' ? 'output' : fileNameWithoutExtension; const osMap = osToBinMaps.filter(x => x.os == operatingSystem)[0]; @@ -89,10 +90,8 @@ class ControlledAccordions extends React.Component { } render() { - const { classes } = this.props; + const { classes, file, activationBytes} = this.props; const { expanded, outputFormat, operatingSystem } = this.state; - - return (
@@ -101,10 +100,10 @@ class ControlledAccordions extends React.Component { aria-controls="panel2bh-content" id="panel2bh-header" > - Command + Command and Convert - Generate ffmpeg command - + Generate ffmpeg command or convert in browser + +
diff --git a/src/OnlineConverter.jsx b/src/OnlineConverter.jsx new file mode 100644 index 0000000..50bcfec --- /dev/null +++ b/src/OnlineConverter.jsx @@ -0,0 +1,67 @@ +import React, {useState} from "react"; +import Button from '@material-ui/core/Button'; +import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'; +import Typography from "@material-ui/core/Typography"; + +const downloadFile= (data, outputFileName, outputFormat) => { + let a = document.createElement("a"); + document.body.appendChild(a); + const blob = new Blob([data.buffer], { type: 'audio/'+outputFormat}); + const url = window.URL.createObjectURL(blob); + a.href = url; + a.download = outputFileName; + a.click(); + window.URL.revokeObjectURL(url); +} +const getCommandAsList = (file, outputFileName, outputFormat, activationBytes) =>{ + const outputFormatCodecMaps = [ + { format: "m4b", codec: "copy" }, + { format: "flac", codec: "flac" }, + { format: "mp3", codec: "libmp3lame" }, + ]; + const codec = outputFormatCodecMaps.filter(x => x.format === outputFormat)[0].codec; + const filename = file.name; + return [`-y`, + '-activation_bytes', activationBytes, + '-i', filename, + '-c:a', codec, + '-vn', outputFileName + ]; +} +const doTranscode = async (file, outputFileName, outputFormat, activationBytes, setMessage) => { + const ffmpeg = createFFmpeg({ + log: true, + progress: ({ ratio }) => { + setMessage(`Complete: ${(ratio * 100.0).toFixed(2)}%`); + } + }); + const command = getCommandAsList(file, outputFileName, outputFormat, activationBytes); + setMessage('Loading ffmpeg-core.js'); + await ffmpeg.load(); + setMessage('Start transcoding'); + ffmpeg.FS('writeFile', file.name, await fetchFile(file)); + await ffmpeg.run(...command); + setMessage('Complete transcoding'); + const data = ffmpeg.FS('readFile', outputFileName); + downloadFile(data,outputFileName, outputFormat) +}; +const OnlineConverter = (props) => { + const {file, activationBytes, outputFormat} = props + const [message, setMessage] = useState('Click Start to transcode'); + + const downloadDisabled = !(file && activationBytes && outputFormat) + + return( +
+ + {message} +
+ ) +} + +export default OnlineConverter \ No newline at end of file diff --git a/src/index.js b/src/index.js index bdb5f4e..b213da9 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,8 @@ import './index.css'; import * as serviceWorker from './serviceWorker'; import ChecksumResolver from './ChecksumResolver'; import ReactNotification from 'react-notifications-component' +import ForkMeOnGithub from 'fork-me-on-github'; + import ReactGA from 'react-ga'; ReactGA.initialize('UA-174657678-1'); @@ -15,7 +17,11 @@ ReactDOM.render( - + , document.getElementById('root')