Merge pull request #13 from santosh898/master
Implemented ConcatDemuxer.
This commit is contained in:
		
						commit
						9cc345c5a4
					
				
							
								
								
									
										60
									
								
								docs/api.md
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								docs/api.md
									
									
									
									
									
								
							| @ -1,5 +1,4 @@ | ||||
| API | ||||
| === | ||||
| # API | ||||
| 
 | ||||
| - [createWorker()](#create-worker) | ||||
|   - [Worker.load](#worker-load) | ||||
| @ -14,6 +13,7 @@ API | ||||
| --- | ||||
| 
 | ||||
| <a name="create-worker"></a> | ||||
| 
 | ||||
| ## 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. | ||||
| @ -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)` | ||||
|   - `progress` a function to trace the progress, a quick example is `p => console.log(p)` | ||||
| 
 | ||||
| 
 | ||||
| **Examples:** | ||||
| 
 | ||||
| ```javascript | ||||
| const { createWorker } = FFmpeg; | ||||
| const worker = createWorker({ | ||||
|   corePath: './node_modules/@ffmpeg/core/ffmpeg-core.js', | ||||
|   logger: m => console.log(m), | ||||
|   corePath: "./node_modules/@ffmpeg/core/ffmpeg-core.js", | ||||
|   logger: m => console.log(m) | ||||
| }); | ||||
| ``` | ||||
| 
 | ||||
| <a name="worker-load"></a> | ||||
| 
 | ||||
| ### 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. | ||||
| @ -55,6 +56,7 @@ Worker.load() loads ffmpeg-core.js script (download from remote if not presented | ||||
| ``` | ||||
| 
 | ||||
| <a name="worker-write"></a> | ||||
| 
 | ||||
| ### 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. | ||||
| @ -68,11 +70,15 @@ Worker.write() writes data to specific path in Emscripten file system, it is an | ||||
| 
 | ||||
| ```javascript | ||||
| (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> | ||||
| 
 | ||||
| ### Worker.writeText(path, text): Promise | ||||
| 
 | ||||
| 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 | ||||
| (async () => { | ||||
|   await worker.write('sub.srt', '...'); | ||||
|   await worker.write("sub.srt", "..."); | ||||
| })(); | ||||
| ``` | ||||
| 
 | ||||
| <a name="worker-read"></a> | ||||
| 
 | ||||
| ### Worker.read(path, del): Promise | ||||
| 
 | ||||
| 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 | ||||
| (async () => { | ||||
|   const { data } = await worker.read('output.mp4'); | ||||
|   const { data } = await worker.read("output.mp4"); | ||||
| })(); | ||||
| ``` | ||||
| 
 | ||||
| <a name="worker-remove"></a> | ||||
| 
 | ||||
| ### 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. | ||||
| @ -121,11 +129,12 @@ Worker.remove() removes files in file system, it will be better to delete unused | ||||
| 
 | ||||
| ```javascript | ||||
| (async () => { | ||||
|   await worker.remove('output.mp4'); | ||||
|   await worker.remove("output.mp4"); | ||||
| })(); | ||||
| ``` | ||||
| 
 | ||||
| <a name="worker-transcode"></a> | ||||
| 
 | ||||
| ### Worker.transcode(inputPath, outputPath, options, del, jobId): Promise | ||||
| 
 | ||||
| Worker.transcode() transcode a video file to another format. | ||||
| @ -142,11 +151,12 @@ Worker.transcode() transcode a video file to another format. | ||||
| 
 | ||||
| ```javascript | ||||
| (async () => { | ||||
|   await worker.transcode('flame.avi', 'output.mp4', '-s 1920x1080'); | ||||
|   await worker.transcode("flame.avi", "output.mp4", "-s 1920x1080"); | ||||
| })(); | ||||
| ``` | ||||
| 
 | ||||
| <a name="worker-trim"></a> | ||||
| 
 | ||||
| ### Worker.trim(inputPath, outputPath, from, to, options, del, jobId): Promise | ||||
| 
 | ||||
| Worker.trim() trims video to specific interval. | ||||
| @ -165,11 +175,34 @@ Worker.trim() trims video to specific interval. | ||||
| 
 | ||||
| ```javascript | ||||
| (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> | ||||
| 
 | ||||
| ### Worker.run(args, options, jobId): Promise | ||||
| 
 | ||||
| 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 | ||||
| (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" | ||||
|   }); | ||||
| })(); | ||||
| ``` | ||||
|  | ||||
							
								
								
									
										57
									
								
								examples/browser/concatDemuxer.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								examples/browser/concatDemuxer.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| <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>Select multiple video files to Concatenate</h3> | ||||
|     <video id="output-video" controls></video><br /> | ||||
|     <input type="file" id="uploader" multiple /> | ||||
|     <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"); | ||||
|         message.innerHTML = "Loading ffmpeg-core.js"; | ||||
|         await worker.load(); | ||||
|         message.innerHTML = "Start Concating"; | ||||
|         const inputPaths = []; | ||||
|         for (const file of files) { | ||||
|           const { name } = file; | ||||
|           await worker.write(name, file); | ||||
|           inputPaths.push(name); | ||||
|         } | ||||
|         await worker.concatDemuxer(inputPaths, "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,6 +122,14 @@ module.exports = (_options = {}) => { | ||||
|     ) | ||||
|   ); | ||||
| 
 | ||||
|   const concatDemuxer = async (inputPaths, outputPath, opts = '', del = true, jobId) => { | ||||
|     const text = inputPaths.reduce((acc, input) => `${acc}\nfile ${input}`, ''); | ||||
|     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); | ||||
|   }; | ||||
| 
 | ||||
|   const ls = (path, jobId) => ( | ||||
|     startJob(createJob({ | ||||
|       id: jobId, action: 'ls', payload: { path }, | ||||
| @ -175,6 +183,7 @@ module.exports = (_options = {}) => { | ||||
|     run, | ||||
|     transcode, | ||||
|     trim, | ||||
|     concatDemuxer, | ||||
|     ls, | ||||
|     terminate, | ||||
|   }; | ||||
|  | ||||
| @ -66,7 +66,9 @@ const ls = ({ | ||||
| const run = async ({ | ||||
|   payload: { | ||||
|     args: _args, | ||||
|     options: { inputPath, outputPath, del }, | ||||
|     options: { | ||||
|       inputPath, inputPaths, outputPath, del, | ||||
|     }, | ||||
|   }, | ||||
| }, res) => { | ||||
|   const args = [...defaultArgs, ..._args.trim().split(' ')]; | ||||
| @ -75,6 +77,9 @@ const run = async ({ | ||||
|   Module.FS.unlink(outputPath); | ||||
|   if (del && typeof inputPath === 'string') { | ||||
|     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(' ')}` }); | ||||
| }; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 jeromewu
						jeromewu