Skip to content

Instantly share code, notes, and snippets.

@cobookman
Last active August 17, 2021 12:39
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 cobookman/c1a9856a4588496b021a to your computer and use it in GitHub Desktop.
Save cobookman/c1a9856a4588496b021a to your computer and use it in GitHub Desktop.
HTML5 Audio (mp3) and Video (webm) live transcoding streams

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());
    });
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment