如何将Python的BytesIO函数转换为Node.js/TypeScript?

dbf7pr2w  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(90)

我目前正在使用Svelte-Kit和Node.js适配器将我的Python后端与Svelte前端合并。我有一个媒体文件作为缓冲区,我试图弄清楚如何将所有内容保存在内存中,类似于我在Python中使用BytesIO的方式。
下面是我试图翻译成TypeScript / Node.js的Python函数:

def get_duration(input: BytesIO):
    command = "ffmpeg -i -".split(" ")
    output = subprocess.run(
        command,
        input=input.read(),
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    duration = None
    lines = output.stderr.decode().split("\n")
    print(lines)
    for line in lines:
        if "Duration:" in line:
            match = re.search(r"Duration: (\d+):(\d+):(\d+.\d+)", line)
            if match:
                hours = int(match.group(1))
                minutes = int(match.group(2))
                seconds = float(match.group(3))
                duration = hours * 3600 + minutes * 60 + seconds
            break
    input.seek(0)
    print(duration)
    return duration

这个函数在Python中运行良好,但我不确定如何将其转换为Node.js,同时将所有内容都保留在内存中。我需要将字节通过管道传输到stdin,并将stdout和stderr通过管道传输到内存中的对象。
我怀疑这可能涉及到Node.js的“fs”库,但我不确定是使用流还是缓冲区。
注意:我没有使用ffprobe的持续时间,因为它不断产生零的持续时间(可能是由于我的错误)。
我试过使用GPT-4,搜索Node.js文档,浏览StackOverflow来寻找关于内存管道的答案。然而,我对Node.js并不像对Python那样熟悉,Python对对象的更高层次的抽象使我避免了学习流、缓冲区、字节等。
GPT-4建议不可能使用Node.js完成我在Python函数中所做的事情,但我觉得很难相信。
我还研究了WRITEStream(),但第一个参数似乎需要FileLike对象,我认为Buffer不适合这种情况。

cl25kdpy

cl25kdpy1#

我已经通过Readable和Readable弄清楚了。由于标准输入错误,我遇到了测试提前退出的问题。原来这是由Vitest使用多个工作者运行测试造成的。我还切换回了FFProbe,它似乎没有与Python相同的问题。
以下是返回视频或音频文件的持续时间(以秒为单位),同时将所有内容保留在内存中的过程:

export async function getDuration(input: Buffer): Promise<number | undefined> {
    if (!Buffer.isBuffer(input)) {
        throw new Error('Input must be a buffer.')
    }

    if (input.length === 0) {
        throw new Error('Input must have a length.')
    }

    return new Promise((resolve, reject) => {
        const output = spawn(
            'ffprobe',
            ['-i', '-', '-show_entries', 'format=duration', '-print_format', 'json'],
            {
                stdio: ['pipe', 'pipe', 'pipe']
            }
        )

        let jsonOutput = ''

        output.stdout.on('data', (data) => {
            jsonOutput += data
        })

        output.on('exit', (code, signal) => {
            console.log(`ffprobe exited with code ${code} and signal ${signal}`)
            if (code !== 0) {
                reject(new Error(`FFprobe exited with code ${code}`))
                return
            }

            try {
                const { format } = JSON.parse(jsonOutput)
                resolve(Number(format.duration))
            } catch (err) {
                reject(err)
            }
        })

        // Create a Readable stream from the input buffer
        const stream = new Readable()
        stream.push(input)
        stream.push(null) // indicates end-of-file

        // Pipe the stream to the stdin of the ffprobe process
        stream.pipe(output.stdin)

        // Handle EPIPE error
        output.stdin.on('error', (error) => {
            if (error.code !== 'EPIPE') {
                reject(error)
            }
        })
    })
}

它比Python更复杂……
我想代码转换也是一样的,只是把输出管道改为可转换的。

相关问题