【问题标题】:Promise chaining and resolutionPromise 链接和解析
【发布时间】:2019-01-23 18:59:47
【问题描述】:

我正在尝试在 Promise 的帮助下一个一个地转换视频。我使用 ffmpeg 进行转换,使用 multer 上传多个文件。

multer 一次上传多个文件,之后我必须逐个链接转换。截至目前,它只是转换第一个文件。

我认为在数组中链接承诺 ..like 应该可以工作,但我很困惑是否可以在数组中定义新的承诺,因为 ffmpeg 也返回一个承诺

我的路由器:

const router = require('express').Router();
const multer = require('multer');
const ffmpeg = require('ffmpeg');

let str;
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, './uploads');
  },
  filename: (req, file, cb) => {
    str = file.originalname.replace(/\.[^/.]+$/, "");
    str = str.replace(/[^a-z0-9+]+/gi, '_') + '.' + file.originalname.replace(/^.*\./, '');
    cb(null, str);
  }
});

const upload = multer({ storage: storage }).array('files', 12);

router.post('/upload', (req, res, next) => {
  // req.files is an array of files
  // req.body will contain the text fields, if there were any
  function uploadFile() {
    return new Promise((resolve, reject) => {
      upload(req, res, (err) => {
        if (err) {
          res.send(err) // Pass errors to Express.
          reject(`Error: Something went wrong!`);
        } else if (req.files == undefined) {
          res.send(`No File selected.`);
          resolve();
        } else if (!err && req.files.length > 0) {
          res.status(201).send(`${req.files.length} File(s): ${req.files} uploaded successfully.`);
          console.log('uploaded');
          resolve();
        }
      });
    });
  }

  uploadFile().then(() => {
    try {
      var process = new ffmpeg('./uploads/' + str);
      process.then(function (video) {
        console.log('The video is ready to be processed');
        video.addCommand('-hide_banner', '');
        video.addCommand('-y', '');
        video.addCommand('-c:a', 'aac');
        video.addCommand('-ar', '48000');
        video.addCommand('-c:v', 'h264');
        video.addCommand('-profile:v', 'main');
        video.addCommand('-crf', '20');
        video.addCommand('-sc_threshold', '0');
        video.addCommand('-g', '50');
        video.addCommand('-keyint_min', '50');
        video.addCommand('-hls_time', '4');
        video.addCommand('-hls_playlist_type', 'vod');
        video.addCommand('-vf', 'scale=-2:720');
        video.addCommand('-b:v', '1400k');
        video.addCommand('-maxrate', '1498k');
        video.addCommand('-bufsize', '2100k');
        video.addCommand('-b:a', '128k');
        video.save('./converted/' + str, function (error, file) {
          if (!error)
            console.log('Video file: ' + file);
        });
        }, function (err) {
          console.log('Error: ' + err);
        });
    } catch (e) {
      console.log(e.code);
      console.log(e.msg);
    }
  }).catch((err) => {
    console.log(Error, err);
  });
});

module.exports = router;

【问题讨论】:

    标签: node.js express ffmpeg promise multer


    【解决方案1】:

    我会使用 Promise.all 异步处理上传,它本身会返回一个带有结果数组的 promise。

    例子:

    const express = require ( 'express' );
    const router = express.Router ( {} );
    const multer = require ( 'multer' );
    const upload = multer ( { dest: 'uploads/' } );
    
    // Process a single upload - returns a promise
    const processUpload = file => {
        return new Promise ( ( resolve, reject ) => {
    
            // Processing code here
            // ...
    
            // Return the promise when done
            return resolve ( path );
    
        } );
    };
    
    // Handle upload route
    router.post ( '/upload', [
    
        // Process the multiple file upload
        upload.array ( 'files', 12 ),
    
        // Controller - process the uploaded files
        ( req, res, next ) => {
    
            // Create an array of promises for each uploaded file in req.files
            let promises = req.files.map ( file => processUpload ( file ) );
            Promise.all ( promises )
                .then ( results => {
    
                    // Handle the finished results here
                    return res
                        .status ( 201 )
                        .json ( {
                            message: `${results.length} files successfully uploaded`
                        } )
                    ;
    
                } )
                .catch ( e => next ( e ) )
            ;
    
        }
    
    ] );
    

    更新以按顺序处理上传:

    使用异步库进行更好的控制:http://caolan.github.io/async/docs.html#eachSeries

    const express = require ( 'express' );
    const router = express.Router ( {} );
    const async = require ( 'async' );
    const multer = require ( 'multer' );
    const upload = multer ( { dest: 'uploads/' } );
    
    // Process a single upload - returns a promise
    const processUpload = file => {
        return new Promise ( ( resolve, reject ) => {
    
            // Processing code here
            const process = new ffmpeg ( /../ );
            process
                .then ( video => {
    
                    // Return the promise when done
                    return resolve ( something );
    
                } )
                .catch ( e => reject ( e ) )
            ;
    
        } );
    };
    
    // Handle upload route
    router.post ( '/upload', [
    
        // Process the multiple file upload
        upload.array ( 'files', 12 ),
    
        // Controller - process the uploaded files
        ( req, res, next ) => {
    
            // Process multiple files sequentially
            let results = [];
            async.eachSeries (
    
                // Array to iterate through
                req.files,
    
                // Callback per file
                ( file, callback ) => {
    
                    processUpload(file)
                        .then(r => {
    
                            // Compile results and return this callback
                            results.push(r);
                            callback()
    
                        })
                        .catch ( e => callback ( e ) )
                    ;
    
                },
    
                // Completion handler
                e => {
    
                    if ( e ) {
                        return next ( e );
                    }
    
                    // Handle the finished results here
                    return res
                        .status ( 201 )
                        .json ( {
                            message: `${results.length} files successfully uploaded`
                        } )
                        ;
    
                }
            );
    
        }
    
    ] );
    

    希望这会有所帮助..

    【讨论】:

    • 我相信这会在所有文件上传后解决。目前也正在上传文件,在解决 .then() 之后我需要调用 ffmpeg 转换 API。因为 ffmpeg 不会一次转换多个文件,而是基于承诺。我需要在承诺中链接转换。听起来很简单,但 ffmpeg 已经返回了一个承诺。我不想阻止我的下一次上传并等待上一次转换发生。
    • 道歉 - 没有正确阅读您的问题 :) 答案已更新为使用异步库进行顺序控制流..
    • 已上传多个文件。上传完成后,我需要将转化排序。
    猜你喜欢
    • 1970-01-01
    • 2015-01-19
    • 2011-03-14
    • 2018-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    相关资源
    最近更新 更多