Revise API and add worker.run

This commit is contained in:
jeromewu 2019-11-06 11:57:41 +00:00
parent db0c02a90a
commit c7234f23c0
8 changed files with 177 additions and 37 deletions

View File

@ -40,7 +40,9 @@ const worker = createWorker();
(async () => { (async () => {
await worker.load(); await worker.load();
const { data } = await worker.transcode('./test.avi', 'mp4'); await worker.write('test.avi', './test.avi');
await worker.transcode('test.avi', 'test.mp4');
const { data } = await worker.read('test.mp4');
fs.writeFileSync('./test.mp4', data); fs.writeFileSync('./test.mp4', data);
})(); })();
``` ```

47
examples/browser/run.html Normal file
View File

@ -0,0 +1,47 @@
<html>
<head>
<script src="/dist/ffmpeg.dev.js"></script>
<style>
html, body {
margin: 0;
width: 100%;
height: 100%
}
body {
display: flex;
flex-direction: column;
align-items: center;
}
</style>
</head>
<body>
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
<video id="output-video" controls></video><br/>
<input type="file" id="uploader">
<p id="message" />
<script>
const { createWorker } = FFmpeg;
const worker = createWorker({
corePath: '../../node_modules/@ffmpeg/core/ffmpeg-core.js',
logger: ({ message }) => console.log(message),
});
const transcode = async ({ target: { files } }) => {
const message = document.getElementById('message');
const { name } = files[0];
message.innerHTML = 'Loading ffmpeg-core.js';
await worker.load();
message.innerHTML = 'Start transcoding';
await worker.write(name, files[0]);
await worker.run(`-i ${name} output.mp4`);
message.innerHTML = 'Complete transcoding';
const { data } = await worker.read('output.mp4');
const video = document.getElementById('output-video');
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
}
const elm = document.getElementById('uploader');
elm.addEventListener('change', transcode);
</script>
</body>
</html>

View File

@ -28,11 +28,14 @@
const transcode = async ({ target: { files } }) => { const transcode = async ({ target: { files } }) => {
const message = document.getElementById('message'); const message = document.getElementById('message');
const { name } = files[0];
message.innerHTML = 'Loading ffmpeg-core.js'; message.innerHTML = 'Loading ffmpeg-core.js';
await worker.load(); await worker.load();
message.innerHTML = 'Start transcoding'; message.innerHTML = 'Start transcoding';
const { data } = await worker.transcode(files[0], 'mp4'); await worker.write(name, files[0]);
await worker.transcode(name, 'output.mp4');
message.innerHTML = 'Complete transcoding'; message.innerHTML = 'Complete transcoding';
const { data } = await worker.read('output.mp4');
const video = document.getElementById('output-video'); const video = document.getElementById('output-video');
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' })); video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));

17
examples/node/run.js Executable file
View File

@ -0,0 +1,17 @@
const fs = require('fs');
const { createWorker } = require('../../src');
const worker = createWorker({
logger: ({ message }) => console.log(message),
});
(async () => {
await worker.load();
console.log('Start transcoding');
await worker.write('flame.avi', '../../tests/assets/flame.avi');
await worker.run('-i flame.avi flame.mp4');
const { data } = await worker.read('flame.mp4');
console.log('Complete transcoding');
fs.writeFileSync('flame.mp4', Buffer.from(data));
process.exit(0);
})();

View File

@ -1,9 +1,6 @@
const fs = require('fs'); const fs = require('fs');
const { createWorker } = require('../../src'); const { createWorker } = require('../../src');
const { argv } = process;
const [,, inputPath, outputPath] = argv;
const worker = createWorker({ const worker = createWorker({
logger: ({ message }) => console.log(message), logger: ({ message }) => console.log(message),
}); });
@ -11,8 +8,10 @@ const worker = createWorker({
(async () => { (async () => {
await worker.load(); await worker.load();
console.log('Start transcoding'); console.log('Start transcoding');
const { data } = await worker.transcode(inputPath, outputPath.split('.').pop()); await worker.write('flame.avi', '../../tests/assets/flame.avi');
await worker.transcode('flame.avi', 'flame.mp4');
const { data } = await worker.read('flame.mp4');
console.log('Complete transcoding'); console.log('Complete transcoding');
fs.writeFileSync(outputPath, Buffer.from(data)); fs.writeFileSync('flame.mp4', Buffer.from(data));
process.exit(0); process.exit(0);
})(); })();

43
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "@ffmpeg/ffmpeg", "name": "@ffmpeg/ffmpeg",
"version": "0.2.22", "version": "0.2.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -3056,7 +3056,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -3077,12 +3078,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -3097,17 +3100,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -3224,7 +3230,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -3236,6 +3243,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -3250,6 +3258,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -3257,12 +3266,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -3281,6 +3292,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -3361,7 +3373,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -3373,6 +3386,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -3458,7 +3472,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -3494,6 +3509,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -3513,6 +3529,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -3556,12 +3573,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.3", "version": "3.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },

View File

@ -56,18 +56,41 @@ module.exports = (_options = {}) => {
})) }))
); );
const transcode = async (media, outputExt, opts, jobId) => ( const write = async (path, data, jobId) => (
startJob(createJob({
id: jobId,
action: 'write',
payload: {
path,
data: await loadMedia(data),
},
}))
);
const transcode = (inputPath, outputPath, opts, jobId) => (
startJob(createJob({ startJob(createJob({
id: jobId, id: jobId,
action: 'transcode', action: 'transcode',
payload: { payload: {
media: await loadMedia(media), inputPath,
outputExt, outputPath,
options: opts, options: opts,
}, },
})) }))
); );
const read = (path, jobId) => (
startJob(createJob({
id: jobId, action: 'read', payload: { path },
}))
);
const run = (args, jobId) => (
startJob(createJob({
id: jobId, action: 'run', payload: { args },
}))
);
const terminate = async (jobId) => { const terminate = async (jobId) => {
if (worker !== null) { if (worker !== null) {
await startJob(createJob({ await startJob(createJob({
@ -86,8 +109,10 @@ module.exports = (_options = {}) => {
if (status === 'resolve') { if (status === 'resolve') {
log(`[${workerId}]: Complete ${jobId}`); log(`[${workerId}]: Complete ${jobId}`);
let d = data; let d = data;
if (action === 'transcode') { if (action === 'read') {
d = Uint8Array.from({ ...data, length: Object.keys(data).length }); d = Uint8Array.from({ ...data, length: Object.keys(data).length });
} else {
logger(d);
} }
resolves[action]({ jobId, data: d }); resolves[action]({ jobId, data: d });
} else if (status === 'reject') { } else if (status === 'reject') {
@ -104,7 +129,10 @@ module.exports = (_options = {}) => {
setResolve, setResolve,
setReject, setReject,
load, load,
write,
transcode, transcode,
read,
run,
terminate, terminate,
}; };
}; };

View File

@ -38,30 +38,52 @@ const load = ({ workerId, payload: { options: { corePath } } }, res) => {
}); });
}); });
ffmpeg = Module.cwrap('ffmpeg', 'number', ['number', 'number']); ffmpeg = Module.cwrap('ffmpeg', 'number', ['number', 'number']);
res.resolve(true); res.resolve({ message: 'Loaded ffmpeg-core' });
}); });
} else { } else {
res.resolve(true); res.resolve({ message: 'Loaded ffmpeg-core' });
} }
}; };
const write = ({
payload: {
path,
data,
},
}, res) => {
const d = Uint8Array.from({ ...data, length: Object.keys(data).length });
Module.FS.writeFile(path, d);
res.resolve({ message: `Write ${path} (${d.length} bytes)` });
};
const transcode = ({ const transcode = ({
payload: { payload: {
media, inputPath,
outputExt, outputPath,
options = '', options = '',
}, },
}, res) => { }, res) => {
const data = Uint8Array.from({ ...media, length: Object.keys(media).length }); const args = [...defaultArgs, ...`${options} -i ${inputPath} ${outputPath}`.trim().split(' ')];
const iPath = 'media';
const oPath = `media.${outputExt}`;
const args = [...defaultArgs, ...`${options} -i file:${iPath} ${oPath}`.trim().split(' ')];
Module.FS.writeFile(iPath, data);
ffmpeg(args.length, strList2ptr(args)); ffmpeg(args.length, strList2ptr(args));
const out = Module.FS.readFile(oPath); res.resolve({ message: `Complete transcoding ${inputPath} to ${outputPath}` });
Module.FS.unlink(iPath); };
Module.FS.unlink(oPath);
res.resolve(out); const read = ({
payload: {
path,
},
}, res) => {
res.resolve(Module.FS.readFile(path));
};
const run = ({
payload: {
args: _args,
},
}, res) => {
const args = [...defaultArgs, ..._args.trim().split(' ')];
ffmpeg(args.length, strList2ptr(args));
res.resolve({ message: `Complete ./ffmpeg ${_args}` });
}; };
exports.dispatchHandlers = (packet, send) => { exports.dispatchHandlers = (packet, send) => {
@ -80,7 +102,10 @@ exports.dispatchHandlers = (packet, send) => {
try { try {
({ ({
load, load,
write,
transcode, transcode,
read,
run,
})[packet.action](packet, res); })[packet.action](packet, res);
} catch (err) { } catch (err) {
/** Prepare exception to travel through postMessage */ /** Prepare exception to travel through postMessage */