节点js异步/等待ytdl和ffmpeg的Promise问题

时间:2020-08-31 14:35:57

标签: javascript node.js ffmpeg promise async-await

我构建了一个简单的youtube下载器cli。看起来像这样(不进行任何arg解析即可简化重现):

const ytdl = require('ytdl-core');
const config = require('config');
const progressBar = require('./progressBar');
const logger = require('./logger');
const ffmpeg = require('fluent-ffmpeg');

const url = 'https://www.youtube.com/watch?v=Np8ibIagn3M';

const getInfo = async (url) => {
    logger.info(`Getting metadata for ${url}`);
    const response = await ytdl.getBasicInfo(url);
    const info = response.videoDetails.title;
    logger.info(`Title: ${info}`);
    return info;
};

const getStream = async (url) => {
    logger.info(`Downloading from ${url} ...`);

    let allReceived = false;
    return new Promise((resolve, reject) => {
        const stream = ytdl(url, {
            quality: 'highest',
            filter: (format) => format.container === 'mp4',
        })
            .on('progress', (_, totalDownloaded, total) => {
                if (!allReceived) {
                    progressBar.start(total, 0, {
                        mbTotal: (total / 1024 / 1024).toFixed(2),
                        mbValue: 0,
                    });
                    allReceived = true;
                }
                progressBar.increment();
                progressBar.update(totalDownloaded, {
                    mbValue: (totalDownloaded / 1024 / 1024).toFixed(2),
                });
            })
            .on('end', () => {
                progressBar.stop();
                logger.info('Successfully downloaded the stream!');
            });
        return resolve(stream);
    });
};

const convertToMp3 = async (stream, title) => {
    return new Promise((resolve, reject) => {
        ffmpeg({ source: stream })
            .output(`${config.get('audioDir')}/${title}.mp3`)
            .audioBitrate('192k')
            .run();
        return resolve();
    });
};

const main = async (url) => {
    const info = await getInfo(url);
    console.log('here 1');
    const stream = await getStream(url);
    console.log('here 2');
    await convertToMp3(stream, info);
    console.log('done');
};

main(url);

输出如下:

➜ node youtube.js
info:    Getting metadata for https://www.youtube.com/watch?v=Np8ibIagn3M
info:    Title: Tu boca -  (Bachata Remix Dj Khalid)
here 1
info:    Downloading from https://www.youtube.com/watch?v=Np8ibIagn3M ...
here 2
done
[Progress] [████████████████████████████████████████] 100% | Downloaded: 7.15/7.15 MB | Elapsed Time: 5s
info:    Successfully downloaded the stream!

但是,我希望得到以下输出:

➜ node youtube.js
info:    Getting metadata for https://www.youtube.com/watch?v=Np8ibIagn3M
info:    Title: Tu boca -  (Bachata Remix Dj Khalid)
here 1
info:    Downloading from https://www.youtube.com/watch?v=Np8ibIagn3M ...
[Progress] [████████████████████████████████████████] 100% | Downloaded: 7.15/7.15 MB | Elapsed Time: 5s
here 2
info:    Successfully downloaded the stream!
done

我认为我在理解异步/等待方面遇到了麻烦。据我了解,函数的赋值使我可以等待结果。但是,它似乎不起作用。我不知道为什么以及如何正确调试它。

已编辑:

const getStream = async (url) => {
    logger.info(`Downloading from ${url} ...`);

    let allReceived = false;
    return new Promise((resolve, reject) => {
        const stream = ytdl(url, {
            quality: 'highest',
            filter: (format) => format.container === 'mp4',
        })
            .on('progress', (_, totalDownloaded, total) => {
                console.log('totalDownloaded: ' + totalDownloaded);
                if (!allReceived) {
                    console.log('total: ' + total);
                    progressBar.start(total, 0, {
                        mbTotal: (total / 1024 / 1024).toFixed(2),
                        mbValue: 0,
                    });
                    allReceived = true;
                }
                progressBar.increment();
                progressBar.update(totalDownloaded, {
                    mbValue: (totalDownloaded / 1024 / 1024).toFixed(2),
                });
            })
            .on('end', () => {
                progressBar.stop();
                logger.info('Successfully downloaded the stream!');
                resolve(stream);
            });
    });
};

但是现在是这样的:

➜ node youtube.js
info:    Getting metadata for https://www.youtube.com/watch?v=Np8ibIagn3M
info:    Title: Tu boca -  (Bachata Remix Dj Khalid)
here 1
info:    Downloading from https://www.youtube.com/watch?v=Np8ibIagn3M ...
[Progress] [██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 14% | Downloaded: 1.02/7.15 MB | Elapsed Time: 52s

添加了console.log:

totalDownloaded: 16384
total: 7493903
[Progress] [░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0% | Downloaded: 0/7.15 MB | Elapsed Time: 0stotalDownloaded: 32768
totalDownloaded: 49152
totalDownloaded: 65536
totalDownloaded: 81920
totalDownloaded: 98304
totalDownloaded: 114688
totalDownloaded: 131072
totalDownloaded: 147456
totalDownloaded: 163840
totalDownloaded: 180224
totalDownloaded: 196608
totalDownloaded: 212992
totalDownloaded: 229376
totalDownloaded: 245760
totalDownloaded: 262144
totalDownloaded: 278528
totalDownloaded: 294912
totalDownloaded: 311296
totalDownloaded: 327680
totalDownloaded: 344064
totalDownloaded: 360448
totalDownloaded: 376832
totalDownloaded: 393216
totalDownloaded: 409600
totalDownloaded: 425984
totalDownloaded: 442368
totalDownloaded: 458752
totalDownloaded: 475136
totalDownloaded: 491520
totalDownloaded: 507904
totalDownloaded: 524288
totalDownloaded: 540672
totalDownloaded: 557056
totalDownloaded: 573440
totalDownloaded: 589824
totalDownloaded: 606208
totalDownloaded: 622592
totalDownloaded: 638976
totalDownloaded: 655360
totalDownloaded: 671744
totalDownloaded: 688128
totalDownloaded: 704512
totalDownloaded: 720896
totalDownloaded: 737280
totalDownloaded: 753664
totalDownloaded: 770048
totalDownloaded: 786432
totalDownloaded: 802816
totalDownloaded: 819200
totalDownloaded: 835584
totalDownloaded: 851968
totalDownloaded: 868352
totalDownloaded: 884736
totalDownloaded: 901120
totalDownloaded: 917504
totalDownloaded: 933888
totalDownloaded: 950272
totalDownloaded: 966656
totalDownloaded: 983040
totalDownloaded: 999424
totalDownloaded: 1015808
totalDownloaded: 1032192
totalDownloaded: 1048576
totalDownloaded: 1064960
[Progress] [██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 14% | Downloaded: 1.02/7.15 MB | Elapsed Time: 25s

1 个答案:

答案 0 :(得分:0)

您已经正确使用了Promise,但是您似乎想要一个不同的输出。这就是getStream()内部的情况:

  1. 登录“从$ {url}下载”。
  2. 创建一个承诺并返回。
  3. 设置“进度”和“结束”的事件监听器。
  4. 解决承诺(并继续执行程序)
  5. 获取“结束”事件;运行回调函数并记录“已成功下载流!”。

假设您希望事件5在4之前发生,则需要删除resolve(stream)中的getStream(),并将其移至on("end", {...})回调函数的末尾,如下所示:< / p>

.on('end', () => {
  progressBar.stop();
  logger.info('Successfully downloaded the stream!');
  resolve(stream);
});