简介
GStreamer是一个创建流媒体应用程序的框架。有了GStreamer框架,就可以设计和建立低延迟的应用程序,它可以处理任何类型的流媒体数据流,包括音频和视频功能。
GStreamer核心为插件、数据流和媒体类型处理提供了一个框架。它还提供了一个API来编写使用各种插件的应用程序。
基于插件的框架提供了各种编解码器和其他功能,它们可以被链接并安排在一个管道中,该管道定义了数据流。然而,在写这篇文章的时候,还没有官方的Node.js端口/绑定用于GStreamer应用程序。
特性和使用案例
GStreamer的主要用例之一是用于构建媒体播放器。作为一个开发者,你可以使用一套广泛的强大工具来创建媒体管道,而不需要写一行代码。
默认情况下,GStreamer包括用于建立媒体播放器的组件,支持非常广泛的格式,包括MP3、Ogg/Vorbis、MPEG-1/2、AVI、QuickTime、mod等等。
然而,GStreamer提供了比其他媒体播放器多得多的功能。它的主要优点是,可插入的组件可以混合成任意的管道,这样就有可能编写一个视频或音频编辑应用程序。具体来说,GStreamer提供了:
- 一个用于多媒体应用的API
- 一个插件架构
- 一个管线架构
- 一个用于媒体类型处理/协商的机制
GStreamer的插件架构
通过插件,GStreamer可以连接到其他多媒体框架,重新使用现有的组件(如编解码器)和其他平台的输入/输出机制。
GStreamer的核心在本质上是与媒体无关的。它只知道字节和块,并且只包含基本元素。所有的媒体处理功能都由核心外部的插件提供。这些插件告诉核心如何处理特定类型的媒体。
GStreamer插件可以分为以下几组:
- 协议处理
- 来源:用于音频和视频(涉及协议插件)
- 格式:解析器、格式化器、多路复用器、解复用器、元数据、字幕
- 编解码器:编码器和解码器
- 过滤器:转换器、混合器、效果器
- 汇:用于音频和视频(涉及协议插件)
GStreamer的安装
要安装GStreamer,文档中提供了各种方法,根据你选择的操作系统来选择。
对于macOS X,我们需要安装OSX Snow Leopard(10.6)或更高版本,以及XCode 3.2.6或更高版本。然而,推荐的系统版本是macOS Sierra与XCode 8。我们可以从GStreamer的下载页面安装运行时和开发安装程序,我们可以在这里找到。
对于其他操作系统/环境,包括Windows、iOS、Android和Linux,我们可以看看文档中的下载页面,其中包括所有支持的生态系统和为开发目的构建GStreamer SDK的方法的列表。
我们可以在我们的系统路径上导航到/Library/Frameworks/GStreamer.framework/Commands ,看看可用的命令来玩转GStreamer。一些常用的命令包括gst-launch-1.0,gst-inspect-1.0,gst-play-1.0 。
用Node.js设置GStreamer
安装完成后,我们可以继续使用Node.js运行时间来消费GStreamer管道,并将结果输出到网络浏览器。
让我们创建一个我们选择的文件夹,使用npm或Yarn安装Express.js,并按照说明设置一个带有package.json 文件的基本项目:
npm install express or yarn add express
然后继续创建一个index.js 文件,以保存我们用GStreamer做流媒体例子的JavaScript代码。请看下面的index.js 文件:
const express = require('express')
const http = require('http')
const net = require('net');
const child = require('child_process');
const app = express();
app.use(express.static(__dirname + '/'));
const httpServer = http.createServer(app);
const port = 3000;
//send the html page which holds the video tag
app.get('/', function (req, res) {
res.send('index.html');
});
//stop the connection
app.post('/stop', function (req, res) {
console.log('Connection closed using /stop endpoint.');
if (gstMuxer != undefined) {
gstMuxer.kill(); //kill the GStreamer Pipeline
}
gstMuxer = undefined;
res.end();
});
//send the video stream
app.get('/stream', function (req, res) {
res.writeHead(200, {
'Content-Type': 'video/webm',
});
const tcpServer = net.createServer(function (socket) {
socket.on('data', function (data) {
res.write(data);
});
socket.on('close', function () {
console.log('Socket closed.');
res.end();
});
});
tcpServer.maxConnections = 1;
tcpServer.listen(function () {
console.log("Connection started.");
if (gstMuxer == undefined) {
console.log("inside gstMuxer == undefined");
const cmd = 'gst-launch-1.0';
const args = getGstPipelineArguments(this);
const gstMuxer = child.spawn(cmd, args);
gstMuxer.stderr.on('data', onSpawnError);
gstMuxer.on('exit', onSpawnExit);
}
else {
console.log("New GST pipeline rejected because gstMuxer != undefined.");
}
});
});
httpServer.listen(port);
console.log(`Camera Streaming App listening at http://localhost:${port}`)
process.on('uncaughtException', function (err) {
console.log(err);
});
//functions
function onSpawnError(data) {
console.log(data.toString());
}
function onSpawnExit(code) {
if (code != null) {
console.log('GStreamer error, exit code ' + code);
}
}
function getGstPipelineArguments(tcpServer) {
const args =
['/Users/alexandernnakwue/Downloads/samplevideo.mp4', 'pattern=ball',
'!', 'video/x-raw,width=320,height=240,framerate=100/1',
'!', 'vpuenc_h264', 'bitrate=2000',
'!', 'mp4mux', 'fragment-duration=10',
'!', 'tcpclientsink', 'host=localhost',
'port=' + tcpServer.address().port];
return args;
}
正如我们在上面的文件中看到的,我们有三个端点:
- 一个发送HTML页面的端点,其中有视频标签
- 一个发送视频流的端点
- 一个结束连接的端点
接下来,创建HTML页面(index.html ),其中包含视频标签,如下图所示。
正如我在介绍中提到的,目前还没有Node.js的官方端口或绑定。上面的代码改编自Stack Overflow的这个帖子。
我们可以继续使用gst-launch-1.0 命令来启动流媒体应用程序和参数,其中包括流媒体的视频或音频源、TCP端口和地址、设置等等。随着页面的加载,我们在用play() 方法尽快播放视频流。
注意:这只适用于基于Chromium的浏览器。我将在下面详细解释。l
Gstreamer的一些限制
今天Node.js的GStreamer的当前实现是非标准化的,仍然有不足之处。例如,目前的实现与浏览器不完全兼容,只能在基于Chromium的浏览器中工作,因为在Chrome中加载资源所需的一些HTTP头文件是不可用的。此外,在一些系统架构上构建GStreamer仍然是一项艰巨的任务,因为它仍然包含很多的错误。
GStreamer还不能直接支持多种不同编程语言的端口。这意味着,打算在Node.js应用程序中利用GStreamer的开发者需要使用node-addon-api ,直接从Node中调用C 代码。然而,这种方法需要大量的工作,而且在使用node-gyp构建时可能特别容易出错。
总结
正如我们可能已经注意到的,今天Node.js的GStreamer绑定是有限的。
也有其他可用的绑定,比如node-gstreamer-superficial,但是根据文档,它并不试图成为GStreamer的一个完整的JS绑定,希望有一天能被node-gir (或实现)。
其他可用的绑定或黑客只是不能像预期的那样工作,没有标准化,或者容易出现错误。这的确是一个巨大的挑战,在不久的将来,需要建立一个标准化的、全行业的Node.js绑定的移植。