Add Worker.trim

This commit is contained in:
Jerome Wu 2019-11-18 22:46:39 +08:00
parent 7a380f529b
commit e06c9bd19a
5 changed files with 137 additions and 26 deletions

View File

@ -4,10 +4,12 @@ API
- [createWorker()](#create-worker) - [createWorker()](#create-worker)
- [Worker.load](#worker-load) - [Worker.load](#worker-load)
- [Worker.write](#worker-write) - [Worker.write](#worker-write)
- [Worker.writeText](#worker-writeText)
- [Worker.read](#worker-read) - [Worker.read](#worker-read)
- [Worker.mkdir](#worker-mkdir) - [Worker.mkdir](#worker-mkdir)
- [Worker.remove](#worker-remove) - [Worker.remove](#worker-remove)
- [Worker.transcode](#worker-transcode) - [Worker.transcode](#worker-transcode)
- [Worker.trim](#worker-trim)
- [Worker.run](#worker-run) - [Worker.run](#worker-run)
--- ---
@ -72,6 +74,25 @@ Worker.write() writes data to specific path in Emscripten file system, it is an
})(); })();
``` ```
<a name="worker-writeText"></a>
### Worker.writeText(path, text, jobId): Promise
Worker.write() writes text data to specific path in Emscripten file system.
**Arguments:**
- `path` path to write data to file system
- `text` string to write to file
- `jobId` check Worker.load()
**Examples:**
```javascript
(async () => {
await worker.write('sub.srt', '...');
})();
```
<a name="worker-read"></a> <a name="worker-read"></a>
### Worker.read(path, jobId): Promise ### Worker.read(path, jobId): Promise
@ -146,6 +167,28 @@ Worker.transcode() transcode a video file to another format.
})(); })();
``` ```
<a name="worker-trim"></a>
### Worker.trim(inputPath, outputPath, from, to, options, jobId): Promise
Worker.trim() trims video to specific interval.
**Arguments:**
- `inputPath` input file path, the input file should be written through Worker.write()
- `outputPath` output file path, can be read with Worker.read() later
- `from` start time, can be in time stamp (00:00:12.000) or seconds (12)
- `to` end time, rule same as above
- `options` a string to add extra arguments to ffmpeg
- `jobId` check Worker.load()
**Examples:**
```javascript
(async () => {
await worker.trim('flame.avi', 'output.mp4', 1, 2);
})();
```
<a name="worker-run"></a> <a name="worker-run"></a>
### Worker.run(args, jobId): Promise ### Worker.run(args, jobId): Promise

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 mp4 (x264) video and trim its first 2 seconds and play!</h3>
<video id="output-video" controls></video><br/>
<input type="file" id="uploader">
<p id="message"></p>
<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 trimming';
await worker.write(name, files[0]);
await worker.trim(name, 'output.mp4', 0, 2);
message.innerHTML = 'Complete trimming';
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>

17
examples/node/trim.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 trimming');
await worker.write('flame.avi', '../../tests/assets/flame.avi');
await worker.trim('flame.avi', 'flame_trim.avi', 1, 2);
const { data } = await worker.read('flame_trim.avi');
console.log('Complete trimming');
fs.writeFileSync('flame_trim.avi', Buffer.from(data));
process.exit(0);
})();

View File

@ -69,18 +69,31 @@ module.exports = (_options = {}) => {
})) }))
); );
const transcode = (inputPath, outputPath, opts, jobId) => ( const writeText = async (path, text, jobId) => (
startJob(createJob({ startJob(createJob({
id: jobId, id: jobId,
action: 'transcode', action: 'writeText',
payload: { payload: {
inputPath, path,
outputPath, text,
options: opts,
}, },
})) }))
); );
const run = (args, jobId) => (
startJob(createJob({
id: jobId, action: 'run', payload: { args },
}))
);
const transcode = (inputPath, outputPath, opts = '', jobId) => (
run(`${opts} -i ${inputPath} ${outputPath}`, jobId)
);
const trim = (inputPath, outputPath, from, to, opts = '', jobId) => (
run(`${opts} -ss ${from} -i ${inputPath} -t ${to} -c copy ${outputPath}`, jobId)
);
const read = (path, jobId) => ( const read = (path, jobId) => (
startJob(createJob({ startJob(createJob({
id: jobId, action: 'read', payload: { path }, id: jobId, action: 'read', payload: { path },
@ -99,12 +112,6 @@ module.exports = (_options = {}) => {
})) }))
); );
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({
@ -145,7 +152,9 @@ module.exports = (_options = {}) => {
setReject, setReject,
load, load,
write, write,
writeText,
transcode, transcode,
trim,
read, read,
remove, remove,
mkdir, mkdir,

View File

@ -26,11 +26,6 @@ const strList2ptr = (strList) => {
return listPtr; return listPtr;
}; };
const doRun = (_args) => {
const args = [...defaultArgs, ..._args.trim().split(' ')];
ffmpeg(args.length, strList2ptr(args));
};
const load = ({ workerId, payload: { options: { corePath } } }, res) => { const load = ({ workerId, payload: { options: { corePath } } }, res) => {
if (Module == null) { if (Module == null) {
const Core = adapter.getCore(corePath); const Core = adapter.getCore(corePath);
@ -61,15 +56,14 @@ const write = ({
res.resolve({ message: `Write ${path} (${d.length} bytes)` }); res.resolve({ message: `Write ${path} (${d.length} bytes)` });
}; };
const transcode = ({ const writeText = ({
payload: { payload: {
inputPath, path,
outputPath, text,
options = '',
}, },
}, res) => { }, res) => {
doRun(`${options} -i ${inputPath} ${outputPath}`); Module.FS.writeFile(path, text);
res.resolve({ message: `Complete transcoding ${inputPath} to ${outputPath}` }); res.resolve({ message: `Write ${path} (${text.length} bytes)` });
}; };
const read = ({ const read = ({
@ -100,11 +94,12 @@ const mkdir = ({
const run = ({ const run = ({
payload: { payload: {
args, args: _args,
}, },
}, res) => { }, res) => {
doRun(args); const args = [...defaultArgs, ..._args.trim().split(' ')];
res.resolve({ message: `Complete ./ffmpeg ${args}` }); ffmpeg(args.length, strList2ptr(args));
res.resolve({ message: `Complete ${args.join(' ')}` });
}; };
exports.dispatchHandlers = (packet, send) => { exports.dispatchHandlers = (packet, send) => {
@ -124,7 +119,7 @@ exports.dispatchHandlers = (packet, send) => {
({ ({
load, load,
write, write,
transcode, writeText,
read, read,
remove, remove,
mkdir, mkdir,