Skip to content

Instantly share code, notes, and snippets.

@auchenberg
Created November 5, 2014 22:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save auchenberg/6bbc521fa68398e29e7d to your computer and use it in GitHub Desktop.
Save auchenberg/6bbc521fa68398e29e7d to your computer and use it in GitHub Desktop.
nicercast + ffmpeg
var express = require('express');
var http = require('http');
var spawn = require("child_process").spawn;
var icecast = require('icecast-stack');
var Throttle = require('throttle');
var ip = require('ip');
var ffmpeg = require('fluent-ffmpeg');
var Server = function(inStream, opts) {
var app = express();
this.app = app;
this.serverPort = false;
app.disable('x-powered-by');
opts.name = opts.name || 'Nicercast';
var outputStream = new require('stream').PassThrough(); //new Throttle(BYTES_PER_SECOND);
// // stream playlist (points to other endpoint)
var playlistEndpoint = function(req, res) {
var addr = ip.address();
res.status(200);
res.set('Content-Type', 'audio/x-mpegurl');
res.send('http://' + addr + ':' + this.serverPort + '/listen');
console.log('http://' + addr + ':' + this.serverPort + '/listen');
}.bind(this);
app.get('/', playlistEndpoint);
app.get('/listen.m3u', playlistEndpoint);
app.get('/listen', function(req, res, next) {
ffmpeg({ source: inStream, nolog: true })
.on('end', function() {
console.log('done processing input stream');
})
.on('error', function(err) {
console.log('an error happened: ' + err.message);
})
.pipe(outputStream);
var acceptsMetadata = req.headers['icy-metadata'] == 1;
var parsed = require('url').parse(req.url, true);
// generate response header
var headers = {
"Content-Type": 'audio/mpeg',
"Connection" : 'close'
};
if (acceptsMetadata) {
headers['icy-metaint'] = 8192;
}
res.writeHead(200, headers);
// setup metadata transport
if (acceptsMetadata) {
res = new icecast.IcecastWriteStack(res, 8192);
res.queueMetadata(this.metadata || opts.name);
}
var prevMetadata = 0;
var callback = function(chunk) {
if (acceptsMetadata && prevMetadata != this.metadata) {
res.queueMetadata(this.metadata || opts.name);
prevMetadata = this.metadata;
}
res.write(chunk);
}.bind(this)
outputStream.on("data", callback);
req.connection.on("close", function() {
outputStream.removeListener("data", callback);
});
}.bind(this));
}
Server.prototype.start = function(port) {
this.serverPort = port || 8001;
this.server = http.createServer(this.app).listen(this.serverPort);
}
Server.prototype.setMetadata = function(metadata) {
this.metadata = metadata;
};
Server.prototype.stop = function() {
try {
this.server.close();
} catch (err) {
}
}
module.exports = Server;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment