簡體   English   中英

使用 Node JS 將 h264 文件轉換或包裝為 mp4

[英]Convert or wrap h264 file to mp4 with Node JS

我正在 Raspberry Pi 上拍攝視頻,並希望將原始 h264 文件轉換為 mp4 文件,或者像使用命令行/Python 那樣將其包裝在 mp4 中。 但是,我希望在 NodeJS 中做到這一點。 似乎有很多 node JS 庫在 npm 上使用了 Raspberry Pi 的 mp4-box 庫。 但是,它們都沒有適當的文檔或似乎適合我的項目的需要。 我不知道我是否遺漏了什么或者這是不可能的。

沒有直接的方法可以將 H.264 編碼的文件嵌入到 MP4 容器中,而無需從頭開始實際構建整個文件結構。 可行的,但為了做到這一點,您需要了解 mp4 容器格式(主要基於 Quicktime MOV 容器)並使用TypedArrays構建它,結果您可以將其保存為 MP4 文件(我在這里創建了一個粘貼描述容器文件結構)。

另一種方法是從 Node.js 生成FFmpeg (或直接使用該軟件)並提供 H.264 作為輸入並將其保存為 MP4 文件。 這很直接。 該命令將類似於:

ffmpeg -i yourH264encodedFileHere -c:v copy mp4FileContainer.mp4

要從 Node 運行它,可以使用spawn (參見示例)。

這種基本方法的替代方法是安裝和使用fluent-ffmpeg NPM 模塊,它可以完成所有繁重的工作。

例子

var ffmpeg = require("fluent-ffmpeg");
var inFilename = "video.h264";
var outFilename = "video.mp4";

ffmpeg(inFilename)
  .outputOptions("-c:v", "copy") // this will copy the data instead or reencode it
  .save(outFilename);

一些注意事項:

  • fluent 對文件名(空格等)可能很挑剔。
  • FFmpeg 需要預先安裝並在全局路徑中可用。 如果你不想要它,你可以使用ffmpeg.setFfmpegPath(pathToFFmpegBin)代替。
  • 要在 RPI 上安裝 FFmpeg, 此資源可能很有用。

嘗試在我的 pi 零上安裝 ffmpeg 花了兩個多小時並以錯誤告終,所以這里有一種包裝 mp4 的替代方法:

  1. 安裝 MP4Box
sudo apt install -y gpac
  1. 在您的節點腳本中,使用exec調用MP4Box命令,如Raspivid 文檔所說
import raspivid from 'raspivid';
import { createWriteStream, unlinkSync } from 'fs'
import { exec } from 'child_process'
import internal from 'stream'


// Helper: promisify streaming to a file
const streamToFile = (inputStream: internal.Readable, filePath: string) => {
    return new Promise((resolve, reject) => {
        const fileWriteStream = createWriteStream(filePath)

        inputStream
            .pipe(fileWriteStream)
            .on('finish', resolve)
            .on('error', reject)
    })
}

// Helper: promisify executing shell command
const execPromise = (command: string) => {
        return new Promise((resolve, reject) => {
            exec(command, (error, stdout, stderr) => {
                doLogInfo(stdout)
                if (error) {
                    console.error(error.message)
                    reject(error)
                }
                if (stderr) {
                    console.error(stderr)
                    resolve(stderr)
                }
                resolve()
            })
        })
    }

// Driver
const getMp4FromRaspivid = async () => {
    // Record vid w raspivid
    const h264Path = './myVid.h264'
    const readVideoStream = await raspivid(VIDEO_OPTIONS) as internal.Readable;
    await streamToFile(readVideoStream, h264Path)

    // Wrap in mp4
    const mp4Path = './myVid.mp4'
    const execCommand = ['MP4Box', '-add', h264Path, mp4Path].join(' ')
    await execPromise(execCommand)

    // Delete h264
    unlinkSync(h264Path)

}

了解 mp4(如 mkv)是一個容器非常重要。 您可以向這些容器添加視頻、音頻、字幕“層”。 而 H.264 已經是一種壓縮格式,它不是原始視頻格式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM