使用 Node JS 将 h264 文件转换或包装为 mp4



我正在Raspberry Pi上拍摄视频,并希望将原始h264文件转换为mp4文件,或者可能将其包装在mp4中,就像使用命令行/Python所做的那样。但是,我希望在NodeJS中执行此操作。似乎有很多节点JS库在npm上使用Raspberry Pi的mp4-box库。但是,它们都没有适当的文档或似乎适合我的项目需求。我不知道我是否错过了什么,或者这是否是不可能的。

没有一种直接的方法可以将 H.264 编码的文件嵌入到 MP4 容器中,而无需从头开始实际构建整个文件结构。这是可行的,但为了做到这一点,您需要了解 mp4 容器格式(主要基于 Quicktime MOV 容器(并使用TypedArrays构建它,您可以将结果保存为 MP4 文件(我在这里创建了一个描述容器文件结构的粘贴(。

另一种方法是从 Node 生成 FFmpeg.js(或者直接使用该软件(并提供 H.264 作为输入并将其保存为 MP4 文件。这很简单。该命令将类似于:

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

要从 Node 运行它,可以使用spawn(请参阅示例(。

这种基本方法的替代方案是安装和使用流畅的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);

几点注意事项:

  • 流利可以挑剔文件名(空格等(。
  • FFmpeg 需要预安装并在全局路径中可用。如果您不希望它,则可以改用ffmpeg.setFfmpegPath(pathToFFmpegBin)
  • 要在 RPI 上安装 FFmpeg,此资源可能很有用。

尝试在我的 pi zero 上安装 ffmpeg 花了两个多小时并以错误告终,因此这是包装 mp4 的另一种方法:

  1. 安装 MP4Box
sudo apt install -y gpac
  1. 在你的 Node 脚本中,使用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已经是一种压缩格式,它不是原始视频格式。

最新更新