I am writing a program where I need to process a video multiple times using ffmpeg. The ffmpeg codes (below) are inside a 'then' statement of a promise.
ffmpeg(path)
.size('640x?')
.aspect('1:1')
.autopad('#682BAB')
.saveToFile(`${userDirPath}/11-${userFileName}`)
.on('end', () => {
ffmpeg()
.input('test-11-start.mp4')
.mergeAdd(`${userDirPath}/11-${userFileName}`)
.mergeAdd('test-11-end.mp4')
.mergeToFile(`${userDirPath}/11-final-${userFileName}`, 'temp/')
.on('end', () => console.log('FFmpeg done!'));
});
There is another ffmpeg function after this (same, but with a different aspect ratio) and then, a 'then' statement with some other functions.
The problem is that this ffmpeg function runs asynchronously, and the next statements (which use the resulting file of ffmpeg func) are executed before it finishes executing and so I want it to run synchronously. I've tried async await (below) but it still runs asynchronously. What is wrong with code?
async function ffmpegMerge() {
try {
await ffmpeg(path)
.size('640x?')
.aspect('1:1')
.autopad('#682BAB')
.saveToFile(`${userDirPath}/11-${userFileName}`)
.on('end', () => {
ffmpeg()
.input(`test-11-start.mp4`)
.mergeAdd(`${userDirPath}/11-${userFileName}`)
.mergeAdd(`test-11-end.mp4`)
.mergeToFile(`${userDirPath}/11-final-${userFileName}.mp4`, 'temp/')
.on('end', () => console.log('FFmpeg done!'));
})
}
catch (err) {
return Promise.reject(new Error(err));
}
}
I am writing a program where I need to process a video multiple times using ffmpeg. The ffmpeg codes (below) are inside a 'then' statement of a promise.
ffmpeg(path)
.size('640x?')
.aspect('1:1')
.autopad('#682BAB')
.saveToFile(`${userDirPath}/11-${userFileName}`)
.on('end', () => {
ffmpeg()
.input('test-11-start.mp4')
.mergeAdd(`${userDirPath}/11-${userFileName}`)
.mergeAdd('test-11-end.mp4')
.mergeToFile(`${userDirPath}/11-final-${userFileName}`, 'temp/')
.on('end', () => console.log('FFmpeg done!'));
});
There is another ffmpeg function after this (same, but with a different aspect ratio) and then, a 'then' statement with some other functions.
The problem is that this ffmpeg function runs asynchronously, and the next statements (which use the resulting file of ffmpeg func) are executed before it finishes executing and so I want it to run synchronously. I've tried async await (below) but it still runs asynchronously. What is wrong with code?
async function ffmpegMerge() {
try {
await ffmpeg(path)
.size('640x?')
.aspect('1:1')
.autopad('#682BAB')
.saveToFile(`${userDirPath}/11-${userFileName}`)
.on('end', () => {
ffmpeg()
.input(`test-11-start.mp4`)
.mergeAdd(`${userDirPath}/11-${userFileName}`)
.mergeAdd(`test-11-end.mp4`)
.mergeToFile(`${userDirPath}/11-final-${userFileName}.mp4`, 'temp/')
.on('end', () => console.log('FFmpeg done!'));
})
}
catch (err) {
return Promise.reject(new Error(err));
}
}
Share
Improve this question
asked Dec 14, 2019 at 2:22
sciencaholicsciencaholic
1431 gold badge2 silver badges12 bronze badges
2
-
Why not put the first
ffmpeg
"code" into an function which returns a Promise and resolves when the render is finished(where you log FFMPEG done!). The secondffmpegMerge()
function then is called on the resolve of the first? – Mattstir Commented Jan 23, 2020 at 10:18 -
I did try that, but it weirdly did not work. I used promise inside a promise to solve this, put the rest of the code inside the second
ffmpeg()
's.on('end', () => {})
. I used to think nested promises are a bad practice, that's why I wasn't going for it before, but they're not. – sciencaholic Commented Jan 24, 2020 at 6:35
2 Answers
Reset to default 13Create a function
with promise
and use await
to wait until the function
is resolved.
This is an example of using ffmpeg
synchronously:
function ffmpegSync(){
return new Promise((resolve,reject)=>{
ffmpeg(path)
.size('640x?')
.aspect('1:1')
.autopad('#682BAB')
.saveToFile(`${userDirPath}/11-${userFileName}`)
.on('end', () => {
ffmpeg()
.input(`test-11-start.mp4`)
.mergeAdd(`${userDirPath}/11-${userFileName}`)
.mergeAdd(`test-11-end.mp4`)
.mergeToFile(`${userDirPath}/11-final-${userFileName}.mp4`, 'temp/')
.on('end', () => console.log('FFmpeg done!'));
resolve()
})
on('error',(err)=>{
return reject(new Error(err))
})
})
}
Now just use the function ffmpegSync
and await
.
createThumbnailForVideo().then(()=>{
console.log('ok');
})
function createThumbnailForVideo(){
return new Promise((resolve,reject)=>{
const ffmpegInstaller = require('@ffmpeg-installer/ffmpeg');
const ffmpeg = require('fluent-ffmpeg');
ffmpeg.setFfmpegPath(ffmpegInstaller.path);
var path = require('path'), // Default node module
pathToFile = path.join(__dirname, 'tempfiles', fileName),
pathToSnapshot = path.join(__dirname, 'tempfiles');
var proc = ffmpeg(pathToFile)
.on('filenames', (filenames)=> {})
.on('end', (data)=> {
console.log('screenshots were saved');
})
.on('error', (err)=> {
console.log('an error happened: ' + err.message);
return reject(new Error(err))
})
.takeScreenshots({ count: 1,filename:`thumb_${onlyName}.png`, timemarks: [ '00:00:01.000' ], size: '250x?' },pathToSnapshot)
.on('end', () => {
console.log('FFmpeg done!')
resolve()
})
.on('error', (err)=> {
console.log('an error happened: ' + err.message);
return reject(new Error(err))
})
})