ffprobe无法读取AWS上的节点JS createWriteStream()生成的文件

时间:2016-09-29 14:40:41

标签: node.js amazon-web-services asynchronous ffmpeg promise

我在AWS上运行了一个设置,当视频文件上传到S3存储桶时触发AWS Lambda功能。 Lambda函数在节点中编写并下载文件,将其流式传输到临时工作文件,然后在其上执行ffprobe,然后执行ffmpeg命令。

ffprobe会抛出以下错误:

[mov,mp4,m4a,3gp,3g2,mj2 @ 0x4ea8e20] error reading header download: Invalid data found when processing input

这个bug很难重现,只发生了一半的时间,我认为这是因为程序的异步性质。

我的主要功能如下

downloadFile(library.getDownloadStream, logger, sourceLocation, localFilePath)
        .then(() => ffprobe(logger))
        .then(() => ffmpeg(logger, keyPrefix))
        .then(() => removeDownload(logger, localFilePath))
        .then(() => uploadFiles(library.uploadToBucket, logger, keyPrefix))
        .then(data => invocation.callback())
        .catch(error => invocation.callback(error));

ffprobe功能:

function downloadFile(downloadFunc, logger, sourceLocation, download) {
    return new Promise((resolve, reject) => {
        logger.log(`Starting download: ${sourceLocation.bucket} / ${sourceLocation.key}`);

        var downloadFile = createWriteStream(download);

        downloadFunc(sourceLocation.bucket, sourceLocation.key)
            .on('end', () => {
                logger.log("closing writing stream");
                downloadFile.end();

                logger.log('Download finished');

                resolve();
            })
            .on('error', reject)
            .pipe(downloadFile);
    });
}

每次构建/更新都会将最新的ffmpeg版本上传到AWS。我无法在本地重现此错误。

为什么ffprobe会对标题抛出此错误?

更新

记录下载文件的文件大小打印完全相同的字节数,无论ffprobe是否成功。

但是,当我在解析promise之前设置timeOut时,错误不再发生,并且ffprobe每次都成功运行:

downloadFunc(sourceLocation.bucket, sourceLocation.key)
        .on('end', () => {

            logger.log('Download finished');

            // Filesize
            var meta = fs.statSync(download);
            var fileSizeInBytes = meta["size"];

            logger.log(fileSizeInBytes);

            // resolve();
            setTimeout(resolve, 1000); 
        })
        .on('error', reject)
        .pipe(downloadFile);

为什么会这样?

1 个答案:

答案 0 :(得分:1)

我认为你不需要downloadfile.end如果你正在使用它。也许这就是问题所在。结束事件写完管道后会发生吗?在解决之前可能会有一点延迟。您还可以在下次手动检查服务器上的文件长度进行调试,看看它是否全部写完了。