concatDemuxer implemented
This commit is contained in:
parent
f93ae84794
commit
68fd03d55d
60
docs/api.md
60
docs/api.md
@ -1,5 +1,4 @@
|
|||||||
API
|
# API
|
||||||
===
|
|
||||||
|
|
||||||
- [createWorker()](#create-worker)
|
- [createWorker()](#create-worker)
|
||||||
- [Worker.load](#worker-load)
|
- [Worker.load](#worker-load)
|
||||||
@ -14,6 +13,7 @@ API
|
|||||||
---
|
---
|
||||||
|
|
||||||
<a name="create-worker"></a>
|
<a name="create-worker"></a>
|
||||||
|
|
||||||
## createWorker(options): Worker
|
## createWorker(options): Worker
|
||||||
|
|
||||||
createWorker is a factory function that creates a ffmpeg worker, a worker is basically a Web Worker in browser and Child Process in Node.
|
createWorker is a factory function that creates a ffmpeg worker, a worker is basically a Web Worker in browser and Child Process in Node.
|
||||||
@ -27,17 +27,18 @@ createWorker is a factory function that creates a ffmpeg worker, a worker is bas
|
|||||||
- `logger` a function to log the progress, a quick example is `m => console.log(m)`
|
- `logger` a function to log the progress, a quick example is `m => console.log(m)`
|
||||||
- `progress` a function to trace the progress, a quick example is `p => console.log(p)`
|
- `progress` a function to trace the progress, a quick example is `p => console.log(p)`
|
||||||
|
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { createWorker } = FFmpeg;
|
const { createWorker } = FFmpeg;
|
||||||
const worker = createWorker({
|
const worker = createWorker({
|
||||||
corePath: './node_modules/@ffmpeg/core/ffmpeg-core.js',
|
corePath: "./node_modules/@ffmpeg/core/ffmpeg-core.js",
|
||||||
logger: m => console.log(m),
|
logger: m => console.log(m)
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="worker-load"></a>
|
<a name="worker-load"></a>
|
||||||
|
|
||||||
### Worker.load(jobId): Promise
|
### Worker.load(jobId): Promise
|
||||||
|
|
||||||
Worker.load() loads ffmpeg-core.js script (download from remote if not presented), it makes Web Worker/Child Process ready for next action.
|
Worker.load() loads ffmpeg-core.js script (download from remote if not presented), it makes Web Worker/Child Process ready for next action.
|
||||||
@ -55,6 +56,7 @@ Worker.load() loads ffmpeg-core.js script (download from remote if not presented
|
|||||||
```
|
```
|
||||||
|
|
||||||
<a name="worker-write"></a>
|
<a name="worker-write"></a>
|
||||||
|
|
||||||
### Worker.write(path, data): Promise
|
### Worker.write(path, data): Promise
|
||||||
|
|
||||||
Worker.write() writes data to specific path in Emscripten file system, it is an essential step before doing any other tasks.
|
Worker.write() writes data to specific path in Emscripten file system, it is an essential step before doing any other tasks.
|
||||||
@ -68,11 +70,15 @@ Worker.write() writes data to specific path in Emscripten file system, it is an
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(async () => {
|
(async () => {
|
||||||
await worker.write('flame.avi', 'http://localhost:3000/tests/assets/flame.avi');
|
await worker.write(
|
||||||
|
"flame.avi",
|
||||||
|
"http://localhost:3000/tests/assets/flame.avi"
|
||||||
|
);
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="worker-writeText"></a>
|
<a name="worker-writeText"></a>
|
||||||
|
|
||||||
### Worker.writeText(path, text): Promise
|
### Worker.writeText(path, text): Promise
|
||||||
|
|
||||||
Worker.write() writes text data to specific path in Emscripten file system.
|
Worker.write() writes text data to specific path in Emscripten file system.
|
||||||
@ -86,11 +92,12 @@ Worker.write() writes text data to specific path in Emscripten file system.
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(async () => {
|
(async () => {
|
||||||
await worker.write('sub.srt', '...');
|
await worker.write("sub.srt", "...");
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="worker-read"></a>
|
<a name="worker-read"></a>
|
||||||
|
|
||||||
### Worker.read(path, del): Promise
|
### Worker.read(path, del): Promise
|
||||||
|
|
||||||
Worker.read() reads data from file system, often used to get output data after specific task.
|
Worker.read() reads data from file system, often used to get output data after specific task.
|
||||||
@ -104,11 +111,12 @@ Worker.read() reads data from file system, often used to get output data after s
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(async () => {
|
(async () => {
|
||||||
const { data } = await worker.read('output.mp4');
|
const { data } = await worker.read("output.mp4");
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="worker-remove"></a>
|
<a name="worker-remove"></a>
|
||||||
|
|
||||||
### Worker.remove(path): Promise
|
### Worker.remove(path): Promise
|
||||||
|
|
||||||
Worker.remove() removes files in file system, it will be better to delete unused files if you need to run ffmpeg.js multiple times.
|
Worker.remove() removes files in file system, it will be better to delete unused files if you need to run ffmpeg.js multiple times.
|
||||||
@ -121,11 +129,12 @@ Worker.remove() removes files in file system, it will be better to delete unused
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(async () => {
|
(async () => {
|
||||||
await worker.remove('output.mp4');
|
await worker.remove("output.mp4");
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="worker-transcode"></a>
|
<a name="worker-transcode"></a>
|
||||||
|
|
||||||
### Worker.transcode(inputPath, outputPath, options, del, jobId): Promise
|
### Worker.transcode(inputPath, outputPath, options, del, jobId): Promise
|
||||||
|
|
||||||
Worker.transcode() transcode a video file to another format.
|
Worker.transcode() transcode a video file to another format.
|
||||||
@ -142,11 +151,12 @@ Worker.transcode() transcode a video file to another format.
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(async () => {
|
(async () => {
|
||||||
await worker.transcode('flame.avi', 'output.mp4', '-s 1920x1080');
|
await worker.transcode("flame.avi", "output.mp4", "-s 1920x1080");
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="worker-trim"></a>
|
<a name="worker-trim"></a>
|
||||||
|
|
||||||
### Worker.trim(inputPath, outputPath, from, to, options, del, jobId): Promise
|
### Worker.trim(inputPath, outputPath, from, to, options, del, jobId): Promise
|
||||||
|
|
||||||
Worker.trim() trims video to specific interval.
|
Worker.trim() trims video to specific interval.
|
||||||
@ -165,11 +175,34 @@ Worker.trim() trims video to specific interval.
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(async () => {
|
(async () => {
|
||||||
await worker.trim('flame.avi', 'output.mp4', 1, 2);
|
await worker.trim("flame.avi", "output.mp4", 1, 2);
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="worker-concatDemuxer"></a>
|
||||||
|
|
||||||
|
### Worker.concatDemuxer(inputPaths, outputPath, options, del, jobId): Promise
|
||||||
|
|
||||||
|
Worker.concatDemuxer() concatenates multiple videos using concatDemuxer. This method won't encode the videos again. But it has its limitations. See [Concat demuxer Wiki](https://trac.ffmpeg.org/wiki/Concatenate)
|
||||||
|
|
||||||
|
**Arguments:**
|
||||||
|
|
||||||
|
- `inputPaths` input file paths as an Array, the input files should be written through Worker.write()
|
||||||
|
- `outputPath` output file path, can be read with Worker.read() later
|
||||||
|
- `options` a string to add extra arguments to ffmpeg
|
||||||
|
- `del` a boolean to determine whether to delete input file after the task is done, default: true
|
||||||
|
- `jobId` check Worker.load()
|
||||||
|
|
||||||
|
**Examples:**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
(async () => {
|
||||||
|
await worker.trim(["flame-1.avi", "flame-2.avi"], "output.mp4");
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
<a name="worker-run"></a>
|
<a name="worker-run"></a>
|
||||||
|
|
||||||
### Worker.run(args, options, jobId): Promise
|
### Worker.run(args, options, jobId): Promise
|
||||||
|
|
||||||
Worker.run() is similar to FFmpeg cli tool, aims to provide maximum flexiblity for users.
|
Worker.run() is similar to FFmpeg cli tool, aims to provide maximum flexiblity for users.
|
||||||
@ -184,6 +217,9 @@ Worker.run() is similar to FFmpeg cli tool, aims to provide maximum flexiblity f
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(async () => {
|
(async () => {
|
||||||
await worker.run('-i /data/flame.avi -s 1920x1080 output.mp4', { inputPath: 'flame.avi', outputPath: 'output.mp4' });
|
await worker.run("-i /data/flame.avi -s 1920x1080 output.mp4", {
|
||||||
|
inputPath: "flame.avi",
|
||||||
|
outputPath: "output.mp4"
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
<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 File</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 Concating";
|
|
||||||
await worker.write(name, files[0]);
|
|
||||||
const textFileName = "list.txt";
|
|
||||||
await worker.writeText(textFileName, `file ${name}\nfile ${name}`);
|
|
||||||
await worker.concatDemux(textFileName, "output.mp4");
|
|
||||||
message.innerHTML = "Complete Concating";
|
|
||||||
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>
|
|
@ -122,9 +122,11 @@ module.exports = (_options = {}) => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const concatDemux = (texFilePath, outputPath, opts = '', del = false, jobId) => {
|
const concatDemuxer = async (inputPaths, outputPath, opts = '', del = true, jobId) => {
|
||||||
run(`${opts} -f concat -safe 0 -i /data/${texFilePath} -c copy ${outputPath}`,
|
const text = inputPaths.reduce((acc, input) => `${acc}\nfile ${input}`, '');
|
||||||
{ del },
|
await writeText('concat_list.txt', text);
|
||||||
|
return run(`${opts} -f concat -safe 0 -i /data/concat_list.txt -c copy ${outputPath}`,
|
||||||
|
{ del, outputPath, inputPaths: [...inputPaths, 'concat_list.txt'] },
|
||||||
jobId);
|
jobId);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -181,7 +183,7 @@ module.exports = (_options = {}) => {
|
|||||||
run,
|
run,
|
||||||
transcode,
|
transcode,
|
||||||
trim,
|
trim,
|
||||||
concatDemux,
|
concatDemuxer,
|
||||||
ls,
|
ls,
|
||||||
terminate,
|
terminate,
|
||||||
};
|
};
|
||||||
|
@ -66,7 +66,9 @@ const ls = ({
|
|||||||
const run = async ({
|
const run = async ({
|
||||||
payload: {
|
payload: {
|
||||||
args: _args,
|
args: _args,
|
||||||
options: { inputPath, outputPath, del },
|
options: {
|
||||||
|
inputPath, inputPaths, outputPath, del,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, res) => {
|
}, res) => {
|
||||||
const args = [...defaultArgs, ..._args.trim().split(' ')];
|
const args = [...defaultArgs, ..._args.trim().split(' ')];
|
||||||
@ -75,6 +77,9 @@ const run = async ({
|
|||||||
Module.FS.unlink(outputPath);
|
Module.FS.unlink(outputPath);
|
||||||
if (del && typeof inputPath === 'string') {
|
if (del && typeof inputPath === 'string') {
|
||||||
await adapter.fs.deleteFile(inputPath);
|
await adapter.fs.deleteFile(inputPath);
|
||||||
|
} else if (del && Array.isArray(inputPaths)) {
|
||||||
|
inputPaths.reduce((promise, input) => promise.then(() => adapter.fs.deleteFile(input)),
|
||||||
|
Promise.resolve());
|
||||||
}
|
}
|
||||||
res.resolve({ message: `Complete ${args.join(' ')}` });
|
res.resolve({ message: `Complete ${args.join(' ')}` });
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user