Add Worker.trim
This commit is contained in:
parent
7a380f529b
commit
e06c9bd19a
43
docs/api.md
43
docs/api.md
@ -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
|
||||||
|
|
||||||
|
47
examples/browser/trim.html
Normal file
47
examples/browser/trim.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 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
17
examples/node/trim.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 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);
|
||||||
|
})();
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user