0

Following on from Node - how can i pipe to a new READABLE stream?

I am trying to start a new ReadStream for my live-encoded MP3 file when it reaches a certain size (pre-buffering, essentially), by using fs.watch and fs.stat.

It works, but once the ReadStream has started, I don't know how to exit the watcher and keep the stream running.

I've tried a promise as below, but that is never resolved, so streamEncodedFile is called repeatedly:

var watcher = fs.watch(mp3RecordingFile);

watcher.on('change', (event, path) => {

  fs.stat(mp3RecordingFile, function (err, stats) {

    if (stats.size > 75533) {

        new Promise(function(resolve, reject) {
                streamEncodedFile(); 
        })
        .then(function(result) {
                watcher.close();
                console.log('watcher closed');
        });

    }

  });
});

function streamEncodedFile() {

  var mp3File = fs.createReadStream(mp3RecordingFile);

            mp3File.on('data', function(buffer){
                io.sockets.emit('audio', { buffer: buffer });
            });

}

My other pathetic attempt is to try and start the stream at a certain file size only:

watcher.on('change', (event, path) => {

  fs.stat(mp3RecordingFile, function (err, stats) {

    console.log(stats.size);

    if (stats.size > 75533 && stats.size < 75535) {
                streamEncodedFile(); 
    } else if (stats.size > 75535) {
                watcher.close(); 
    } 

  });
});
Community
  • 1
  • 1
user3174541
  • 59
  • 2
  • 9
  • `var watcher = fs.watch(mp3RecordingFile); watcher.on('change', (event, path) => { fs.stat(mp3RecordingFile, function(err, stats) { if (stats.size > 75533) { streamEncodedFile(); } }); }); function streamEncodedFile() { var mp3File = fs.createReadStream(mp3RecordingFile); mp3File.on('data', function(buffer) { io.sockets.emit('audio', { buffer: buffer }); }); watcher.close(); }` – dottodot Aug 02 '16 at 19:29
  • Thanks. I should have said that I tried that, but the ReadStream ended. This I believe is why https://github.com/jasontbradshaw/tailing-stream – user3174541 Aug 02 '16 at 19:46

1 Answers1

0

Try this solution, with buffering and writing to file.

const Writable = require('stream').Writable;
const fs = require('fs');

let mp3File = fs.createWriteStream('path/to/file.mp3');

var buffer = new Buffer([]);
//in bytes
const CHUNK_SIZE = 102400; //100kb

//Proxy for emitting and writing to file
const myWritable = new Writable({
  write(chunk, encoding, callback) {
    buffer = Buffer.concat([buffer, chunk]);
    if(buffer.length >= CHUNK_SIZE) {
       mp3File.write(buffer);
       io.sockets.emit('audio', { buffer: buffer});
       buffer = new Buffer([]);
    }

    callback();
  }
});

myWritable.on('finish', () => {
   //emit final part if there is data to emit
   if(buffer.length) {
       //write final chunk and close fd
       mp3File.end(buffer);
       io.sockets.emit('audio', { buffer: buffer});
   }
});


inbound_stream.pipe(encoder).pipe(myWritable);
Nazar Sakharenko
  • 1,007
  • 6
  • 11
  • Can't wait to try this. Thanks again! – user3174541 Aug 03 '16 at 06:25
  • Hi *again* @Nazar Sakharenko. I don't understand why you're appending to the buffer with `+=`. The chunks are ArrayBuffer objects, and need to stay that way to be decoded at the other end. Shouldn't we do `buffer.push(chunk)`? Then I'll need to iterate the array somehow to start sending the original ArrayBuffers from it. Unless I am missing something. Thanks! – user3174541 Aug 03 '16 at 08:16
  • Nope, i've just forgot that you manipulate buffer. Answer updated. – Nazar Sakharenko Aug 03 '16 at 18:50