Saturday 27 May 2017

Node express and long running tasks

I have a web module that a user uses to upload a video. Once its uploaded I use ffmpeg to convert the video to an mp4. The problem I have is that it can take a very long time for the conversion of the video and I dont really want the user to sit there and wait.

The following code section will loop through the files and convert the videos:

...
for (var x = 0; x < processFiles.entrys.length; x++) {
    let file = processFiles.entrys[x];
    const sourceVideoFile = tempRepo + '/' + file.renamedFile;
    const destVideoFile = usePath + '/' + file.renamedFile;

    processFiles.entry.data.file = file.renamedFile;
    const videoConv = await this._convertVideo(this.path, sourceVideoFile, destVideoFile)
....
}
response.status(200).send({ status: 'ok' });

Calling _convertVideo() converts the current video to an mp4. And this is what takes a very long time. I was thinking what if I dont wait for _convertVideo and respond to the client before it _convertVideo completes.

So if I modify my code a little and remove the await (and modify the _convertVideo function so its not async)

for (var x = 0; x < processFiles.entrys.length; x++) {
    let file = processFiles.entrys[x];
    console.log(dCount);
    const sourceVideoFile = tempRepo + '/' + file.renamedFile;
    const destVideoFile = usePath + '/' + file.renamedFile;

    processFiles.entry.data.file = file.renamedFile;
    const videoConv = this._convertVideo(this.path, sourceVideoFile, destVideoFile)
....
}
response.status(200).send({ status: 'ok' });

My question is, would the processing the videos still occur even though the client got a response already? Is there any issues of doing it this way?

Thanks

Here is the function that converts the video:

async _convertVideo(config_path, source_path, dest_path) 

    let results = {
        code: 500,
        message: '',
        entrys: []
    };

    return new Promise((resolve, reject) => {

        nconf.file({
            file: `${config_path}/Media.json`
        });
        nconf.load();

        const ffmpegPath = nconf.get(`convert_to_fragmented_mp4:path`);
        const command = nconf.get(`convert_to_fragmented_mp4:command`);
        const args = nconf.get(`convert_to_fragmented_mp4:args`);

        let ffmpegArgs = [];

        for (let item of args) {
            console.log(item);
            if (item === 'video_file_input') {
                ffmpegArgs.push(source_path);
            } else if (item === 'video_file_output') {
                ffmpegArgs.push(dest_path);
            } else
                ffmpegArgs.push(item);
        }

        var proc = spawn(`${ffmpegPath}/${command}`, ffmpegArgs);

        proc.stdout.on('data', (data) => {
            console.log(data);
        });

        proc.stderr.on('data', (data) => {
            console.log(data);
        });

        proc.on('close', (code) => {
            console.log('finished: ' + code);
            results.code = 200;
            fs.stat(dest_path, (err, stats) => {
                if (err) {
                    results = 500;
                    reject(results);
                } else {
                    results.code = 200;
                    results.entrys.push({
                        size: stats.size
                    });

                    resolve(results);

                }
            });
        });
    });
}



via adviner

No comments:

Post a Comment