The following two functions will stream just about any audio or video file to any browsers supporting mp3 and/or webm. Due to the unknown number of bytes, a custom html5 audio/video player will have to be written (my next step) to allow seeking.
For w/e reason node.js didn't want to spawn a child process with a unix pipe in it. This could be so that they can keep support for windows computers. As such I've created the following bash script:
#!/bin/bash
START_TIME=${2:-0}
VARIABLE_BIT_RATE=${3:-4}
ABSOLUTE_PATH=$1
if [ -z $ABSOLUTE_PATH ];
then
echo "{ \"ERROR\" : \"Not given an absolute path to the media file\" }"
else
ffmpeg -ss $START_TIME -i $ABSOLUTE_PATH -f wav - | lame --vbr-new -V $VARIABLE_BIT_RATE - -
fi
The relavent node.js code to transcode and stream audio/video on the fly
exports.sendVideoFile = function(params, res) {
res.writeHead({
'X-Content-Duration' : params.source.duration, //in seconds
'Content-Duration' : params.source.duration, //in seconds
'Content-Type' : 'video/webm'
});
var ffmpeg = childProcess.spawn('ffmpeg', [
'-i', params.location, //location of our video file (use absolute, else you'll have a bad time)
'-ss', '0', //starting time offset
'-c:v', 'libvpx', //video using vpx (webm) codec
'-b:v', '1M', //1Mb/s bitrate for the video
'-cpu-used', '2', //total # of cpus used
'-threads', '4', //number of threads shared between all cpu-used
'-deadline', 'realtime', //speeds up transcode time (necessary unless you want frames dropped)
'-strict', '-2', //ffmpeg complains about using vorbis, and wanted this param
'-c:a', 'libvorbis', //audio using the vorbis (ogg) codec
"-f", "webm", //filetype for the pipe
'pipe:1' //send output to stdout
]);
ffmpeg.stdout.pipe(res);
res.on('close', function() {
ffmpeg.kill();
});
}
exports.sendAudioFile = function(params, res) {
res.writeHead({
'X-Content-Duration' : params.source.duration,
'Content-Duration' : params.source.duration,
'Content-Type' : 'audio/mp3'
});
var audioConv = childProcess.spawn(__dirname + '/audioConv.sh',[
params.location, //first parameter is the file's location relative to the bash script
0, //second parameter specifies a start time offset
3, //third parameter specifies which variable encoding to use 0-9, with 0 being the best 9 the worst
]);
audioConv.stdout.pipe(res);
res.on('close', function() {
audioConv.kill();
});
audioConv.stderr.on('data', function(d) {
console.log(d.toString());
});
};