Technology | 15.Dezembro.2015

Stream live WebM video to browser using Node.js and GStreamer

In this post, we’ll stream live WebM video to the browser using just GStreamer and Node.js

In this post, we’ll stream live WebM video to the browser using just GStreamer and Node.js. In a previous post we did it using Flumotion. Follow the procedure mentioned in that post to setup GStreamer 0.10.32 (or later). We’ll use Node.js with the express middleware. We have used that previously to do on-demand streaming of a WebM file.

Code
We receive a request from the browser at port 9001, create a TCP server socket to listen to a WebM stream, and stream all data received from that socket to the browser. We then spawn a GStreamer pipeline to mux a WebM stream, and stream it to the TCP server socket using the tcpclientsink element. The code follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
var express = require('express')
var http = require('http')
var net = require('net');
var child = require('child_process');
 
var app = express();
var httpServer = http.createServer(app);
 
app.get('/', function(req, res) {
  var date = new Date();
 
  res.writeHead(200, {
    'Date':date.toUTCString(),
    'Connection':'close',
    'Cache-Control':'private',
    'Content-Type':'video/webm',
    'Server':'CustomStreamer/0.0.1',
  });
 
  var tcpServer = net.createServer(function (socket) {
    socket.on('data', function (data) {
      res.write(data);
    });
    socket.on('close', function(had_error) {
      res.end();
    });
  });
 
  tcpServer.maxConnections = 1;
 
  tcpServer.listen(function() {
    var cmd = 'gst-launch-0.10';
    var options = null;
    var args =
      ['videotestsrc', 'horizontal-speed=1', 'is-live=1',
      '!', 'video/x-raw-rgb,framerate=30/1',
      '!', 'ffmpegcolorspace',
      '!', 'vp8enc', 'speed=2',
      '!', 'queue2',
      '!', 'm.', 'audiotestsrc', 'is-live=1',
      '!', 'audioconvert',
      '!', 'vorbisenc',
      '!', 'queue2',
      '!', 'm.', 'webmmux', 'name=m', 'streamable=true',
      '!', 'tcpclientsink', 'host=localhost',
      'port='+tcpServer.address().port];
 
    var gstMuxer = child.spawn(cmd, args, options);
 
    gstMuxer.stderr.on('data', onSpawnError);
    gstMuxer.on('exit', onSpawnExit);
 
    res.connection.on('close', function() {
      gstMuxer.kill();
    });
  });
});
 
httpServer.listen(9001);
 
function onSpawnError(data) {
  console.log(data.toString());
}
 
function onSpawnExit(code) {
  if (code != null) {
    console.error('GStreamer error, exit code ' + code);
  }
}
 
process.on('uncaughtException', function(err) {
  console.debug(err);
});
Execute
Assuming you have saved the script above to a file called script.js, run Node.js thus:
1 node script.js
Now, you can play the WebM stream in Chrome by accessing the following url:http://localhost:9001/
Debug
If you want to trace all system calls, especially if you change the args to GStreamer and get a cryptic message like:
1 execvp(): No such file or directory
you can execute Node.js with strace:
1 strace -fF -o strace.log node livewebm.js

Video and audio source elements

The GStreamer pipeline spawned above uses test video and audio source elements. You’ll need to obtain video and audio streams from real devices for any practical application.
Here’s a list of alternative video source elements:
1.       autovideosrc – automatically detects and chooses a video source
2.       v4l2src – obtains video stream from a Video 4 Linux 2 device, such as a webcam
3.       ximagesrc – video stream is produced from screenshots
Here’s a list of alternative audio source elements:
1.       autoaudiosrc – automatically detects and chooses an audio source
2.       alsasrc – captures audio stream from a specific device using alsa
3.       pulsesrc – captures audio stream from the default mic, based on system settings
An important point to note is that all these sources are live sources. GStreamer defines live sources as sources that discard data when paused, and produce data at a fixed rate thus providing a clock to publish this rate.

Limitations
The example above can support multiple viewers only because we use test video and audio streams. GStreamer pipelines cannot simultaneously capture streams using sources that access the same device, hence tcpServer.maxConnections has been restricted to 1. Even assuming that it can be done, the code above is CPU intensive, since audio and video encoding is done once per viewer.

Este é um espaço de opinião dos colaboradores do CESAR.
São visões pessoais que não necessariamente refletem o pensamento da organização.

Twitter

OFFICES

RECIFE
HEADQUARTERS | +55 81 3425.4700
Rua Bione, 220 - Cais do Apolo
Bairro do Recife - Recife/PE
ZIP CODE: 50.030-390
GENERAL TAXPAYER’S REGISTRY (CNPJ): 01.203.327/0001-23
Ver no mapa
SOROCABA
BRANCH | +55 15 3316.1400
Av. Itavuvu, 11777 – Salas 07 e 09
PTS – Polo Tecnológico de Sorocaba
Sorocaba/SP
ZIP CODE: 18078 -005
Ver no mapa
CURITIBA
BRANCH | +55 41 3016.5688 // 3022.3415
Rua Padre Anchieta, 2454
Salas 1602 a 1605, Bigorrilho
Curitiba/PR
Zip code: 80730 -000
Ver no mapa
MANAUS
BRANCH | +55 92 3346.2243
Rua Belo Horizonte, 19 - salas 1702 a 1707
Edf. The Place
Adrianópolis
Manaus/AM
ZIP CODE: 69057-060
Ver no mapa