Node.js asyn c -функции выполняются параллельно? - PullRequest
0 голосов
/ 08 мая 2020

Приведенный ниже код создан для:

  1. КОНВЕРТИРОВАТЬ некоторые видео и сохранять их в папке преобразованных.
  2. СОЕДИНЯТЬ преобразованные видео.
  3. ОЧИСТИТЬ преобразованная папка.

НО в настоящее время при выполнении кода он объединяется при преобразовании и в конечном итоге вызывает ошибку. Мне нужно выполнить каждую функцию с приоритетом в соответствующем порядке.

const glob = require('glob');
const exec = require('child_process').exec;
const { unlink } = require("fs").promises;

function start(index) {


  const path = `./files/${index}`;
  const ConvertedVideos=path+"/converted/*.mp4";
  const videos = glob.sync(path+"/videos/*.mp4");
  const outputnoaudio = path+"/outputnoaudio.mp4";




  //THIS IS THE ORDER OF EXECUTION

  await convertVideos()
  await withFfmpegConcatVideo()
  await clearConverted()



  //HERE THE DEFINITION OF EACH FUNCTION

  async function convertVideos() {
    return new Promise((resolve) => {

      console.log('>>>Starting conversion!!!');
      const promises = videos.map(
        (video, index) => {
          var command = `ffmpeg -i ${video} -c:v libx264 -vf scale=1920:1080 -r 60 -c:a aac -ar 48000 -b:a 160k -strict experimental -f mp4 ./converted/${index}.mp4`;

          return new Promise((resolve) => {
            exec(command, (error, stdout, stderr) => {
              if (error) {
                console.warn(error);
              }
              resolve(stdout ? stdout : stderr);
              console.log('Converted video', index);
            });
          });
        }
      )
      Promise.all(promises);
      resolve();
    })
  }

  async function withFfmpegConcatVideo() {
    return new Promise((resolve) => {

      console.log('Starting concatenation...');

      var converted = glob.sync(ConvertedVideos);

      console.log('There is ', converted.length, 'converted videos');

      if (converted.length > 0) {

        (async () =>
          await concat({
            output: outputnoaudio,
            videos: converted,
            transition: {
              name: 'fade',
              duration: 200
            }
          }))()
      }
      resolve(console.log('Conversion finished'));
    })
  }


  async function clearConverted() {

    return new Promise((resolve) => {

      const converted =
        glob.sync(ConvertedVideos)

      if (converted.length === 0)
        return Promise.resolve([])

      const promises =
        converted.map(v => unlink(v).then(_ => {
          v
        }))

      Promise.all(promises).then('Clean done.')
      resolve();
    })
  }
}

start(1);

Я хочу сохранить чистый и повторно используемый код. Вы можете мне помочь?

Ответы [ 3 ]

1 голос
/ 08 мая 2020
withFfmpegConcatVideo().then(() => clearConverted());

Должен сработать

1 голос
/ 08 мая 2020

Ваша функция start выглядит некорректно, потому что вам не хватает оператора async.

Для ясности я предлагаю рассматривать это больше как файл C и создать async function main() {}, где вы вызываете и await ваши три функции.

В своей функции convertVideos вы вызываете Promise.all(), но не ждете этого. Обратите внимание, что Promise.all() на самом деле тоже возвращает обещание, и вы должны его дождаться, но для того, чтобы вы его ожидали, окружающая функция также должна иметь ключевое слово async. Я вижу ту же проблему в функции clearConverted.

Попробуйте дождаться ваших вызовов Promise.all и посмотрите, поможет ли это решить вашу проблему.

На самом деле ваша функция convertVideos кажется завернуть все в обещание, и я не думаю, что вам это нужно. Попробуйте это:

function convertVideos() {
    console.log('>>>Starting conversion!!!');
    const promises = videos.map(
        (video, index) => {
            var command = `ffmpeg -i ${video} -c:v libx264 -vf scale=1920:1080 -r 60 -c:a aac -ar 48000 -b:a 160k -strict experimental -f mp4 ./converted/${index}.mp4`;

            return new Promise((resolve) => {
                exec(command, (error, stdout, stderr) => {
                    if (error) {
                       console.warn(error);
                    } 
                resolve(stdout ? stdout : stderr);
                console.log('Converted video', index);
            });
        });
      });


    // Notice that you can return this promise from Promise.all.
    // The caller can then await this promise that will let you know when
    // all the videos are converted.
    return Promise.all(promises);
}
0 голосов
/ 09 мая 2020

Я только что исправил код благодаря вашим комментариям и нашел это решение.


const glob = require('glob');
const concat = require('ffmpeg-concat');
const {
  unlink
} =
require("fs").promises;
const exec = require("child_process").exec;

async function start(index){



  const path = `./files/${index}`;
  const pathToConverted = `${path}/converted`;
  const videos = glob.sync(`${path}/[0-99]/videoKeywords/[0-99]/*output.mp4`);
  const output = `${path}/output.mp4`;
  const outputmuted = `${path}/outputmuted.mp4`;




   async function clearConverted() {

    await new Promise(async (resolve) => {
      console.log('Starting cleaning...');
      const converted = glob.sync(`${pathToConverted}/*.mp4`)

      if (converted.length === 0)
        return Promise.resolve([])

      const promises =
        converted.map(v => unlink(v).then(_ => {
          console.log("   File Deleted");
          v
        }))

      await Promise.all(promises).then(async () => await console.log('Clean done.'))

      resolve()
    })
  }




async function convertVideos() {
    await new Promise(async (resolve) => {

      console.log('>>>Starting conversion of', videos.length, 'files!!!');


      for (let i = 0; i < videos.length; i++) {

        let video = videos[i];

        var command = `ffmpeg -i ${video} -c:v libx264 -vf scale=1920:1080 -r 60 -c:a aac -ar 48000 -b:a 160k -strict experimental -f mp4 ${pathToConverted}/${i}.mp4`;

        await new Promise((resolve) => {
          exec(command, (error, stdout, stderr) => {
            if (error) {
              console.warn(error);
            }
            resolve(stdout ? stdout : stderr);
            console.log('  Converted video', i);
          });
        });
      }
      resolve();
    }).then(async () => await console.log('Conversion finished!!!'))
  }




 async function clearConverted() {

    await new Promise(async (resolve) => {
      console.log('Starting cleaning...');
      const converted = glob.sync(`${pathToConverted}/*.mp4`)

      if (converted.length === 0)
        return Promise.resolve([])

      const promises =
        converted.map(v => unlink(v).then(_ => {
          console.log("   File Deleted");
          v
        }))

      await Promise.all(promises).then(async () => await console.log('Clean done.'))

      resolve()
    })
  }
}
start(0);

Обратите внимание, что эта реализация function convertVideos() выполняет преобразование последовательно асинхронно, что означает, что он конвертирует один файл за шагом. В предыдущей реализации этой функции выполнение выполняется параллельно, что оптимально для преобразования нескольких видео, если у вас несколько ядер.

Если у вас есть предложения по коду для обработки большего объема видео в В то же время, пожалуйста, обращайтесь в службу поддержки.

...