Revise API and add worker.run
This commit is contained in:
parent
db0c02a90a
commit
c7234f23c0
@ -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
47
examples/browser/run.html
Normal 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>
|
@ -26,13 +26,16 @@
|
|||||||
logger: ({ message }) => console.log(message),
|
logger: ({ message }) => console.log(message),
|
||||||
});
|
});
|
||||||
|
|
||||||
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
17
examples/node/run.js
Executable 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);
|
||||||
|
})();
|
@ -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
43
package-lock.json
generated
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user