ArtskydJ / node-sox-stream

:mega: A stream-friendly wrapper around SoX
53 stars 14 forks source link

Empty file #9

Closed tuarrep closed 7 years ago

tuarrep commented 7 years ago

Hi!

I'm trying to transcode an audio http stream from ogg to wav.

Here is my code:

const fs = require('fs')
const http = require('http')
const sox = require('sox-stream')

const transcode = sox({
  input: {
    type: 'ogg'
  },
  output: {
    type: 'wav',
    rate: 44100
  }
})

const dest = fs.createWriteStream('transcoded.wav')

http.get('http://listen.oma-radio.fr/paj.ogg', res => res.pipe(transcode).pipe(dest))

transcode.on('error', err => console.log('Transcode:', err))

The output file remain empty with no error message in the console.

I've tried to pipe directly the http stream to the file, it's working.

I've tried to convert a real ogg file from file system with this code:

const fs = require('fs')
const http = require('http')
const sox = require('sox-stream')

const transcode = sox({
  input: {
    type: 'ogg'
  },
  output: {
    type: 'wav',
    rate: 44100
  }
})

const src = fs.createReadStream('source.ogg')

const dest = fs.createWriteStream('transcoded.wav')

src.pipe(transcode).pipe(dest)

transcode.on('error', err => console.log('Transcode:', err))

I encounter the following errors in my terminal:

▶ npm start

> icecast-transcode@0.0.0 start /run/media/nicolas/DATA/ovp/icecast-transcode
> node server.js

Transcode: Error: sox WARN wav: Length in output .wav header will be wrong since can't seek to fix it

    at Socket.<anonymous> (/run/media/nicolas/DATA/ovp/icecast-transcode/node_modules/sox-stream/index.js:33:23)
    at emitOne (events.js:115:13)
    at Socket.emit (events.js:210:7)
    at addChunk (_stream_readable.js:264:12)
    at readableAddChunk (_stream_readable.js:251:11)
    at Socket.Readable.push (_stream_readable.js:209:10)
    at Pipe.onread (net.js:587:20)
Transcode: { Error: ENOENT: no such file or directory, unlink '/tmp/ff65d55d-9f22-431e-836c-153c3fa5969a'
  errno: -2,
  code: 'ENOENT',
  syscall: 'unlink',
  path: '/tmp/ff65d55d-9f22-431e-836c-153c3fa5969a' }
Transcode: { Error: ENOENT: no such file or directory, unlink '/tmp/ff65d55d-9f22-431e-836c-153c3fa5969a'
  errno: -2,
  code: 'ENOENT',
  syscall: 'unlink',
  path: '/tmp/ff65d55d-9f22-431e-836c-153c3fa5969a' }

And the file re'mains empty

ArtskydJ commented 7 years ago

Does it work from the command line?

E.g.

cat myfile.ogg | sox --type=ogg - --rate=44100 --type=wav newfile.wav
curl http://listen.oma-radio.fr/paj.ogg | sox --type=ogg  - --rate=44100 --type=wav newfile.wav

If something is working from the command line, and not in the sox-stream module, then it's probably an issue with the module.

If it's broken in both, it's probably an issue with sox support of the attempted action.

tuarrep commented 7 years ago

I've typed exactly your commands and it's working like a charm

ArtskydJ commented 7 years ago

When I created this module, I was having issues with streaming certain inputs since sox was then unable to go back and read the headers. So I made the decision to pipe the input to a temporary file, and then run sox when that completes. I don't like the solution, but it's what made it work at the time.

I wish it was, but this module is not currently a great all-around module. From what I can tell, the way you and I use it are pretty different. :grimacing: If you're wanting to use node.js for this operation, you can use child_process, and the command I wrote above.

// untested
const fs = require('fs')
const http = require('http')
const cp = require('child_process')

const dest = fs.createWriteStream('transcoded.wav')

// If you have the argument '-' instead of a filename, sox will use stdin or stdout instead of a file
// http://sox.sourceforge.net/sox.html#FILENAMES
const transcode = cp.spawn('sox', [ '--type=ogg', '-', '--rate=44100', '--type=wav', '-' ])

http.get('http://listen.oma-radio.fr/paj.ogg', res => {
    res.pipe(transcode).pipe(dest)
})

Sorry this module isn't working out for you.

tuarrep commented 7 years ago

Thanks for your help, I'll try this

vidicunt commented 2 years ago

I would like to pipe a arecord/pulse audio stream in node using the script you wrote above but I can't seem to get it to work...

    // a pulseaudio client opening a recording stream
    const rate = 44100, channels = 2, format = PA_SAMPLE_FORMAT.S16LE;
    const stream = await pa.createRecordStream({
      sampleSpec: { rate, format, channels }
    });
    const writer = new wav.Writer({
      sampleRate: rate,
      channels,
      bitDepth: sampleSize[format] * 8
    });

    stream.pipe(writer);
    const dest = fs.createWriteStream('transcoded.wav')
    const transcode = cp.spawn('sox', [ '--type=wav', '-', '--rate=44100', '--type=wav', '-' ])
    writer.pipe(transcode.stdin).pipe(process.stdout, { end: false });

I'm getting an empty file...

ArtskydJ commented 2 years ago

@tommyzat you're not piping anything into your write stream for transcoded.wav.

I'm not sure exactly what will work, but maybe this will:

- writer.pipe(transcode.stdin).pipe(process.stdout, { end: false });
+ writer.pipe(transcode.stdin);
+ transcode.stdout.pipe(dest);
vidicunt commented 2 years ago

Thank you so much! I missed the stdout... On an unrelated note, do you know if it's possible to determine amplitude values from a stream? "sox stat" doesn't seem to be working with: cp.spawn('sox', [ '--type=wav', '-', '-n', 'stat' ]) (i read both stderr and stdout and both aren't returning)

Thank you once again!!

ArtskydJ commented 2 years ago

On an unrelated note, do you know if it's possible to determine amplitude values from a stream?

I don't know.

"sox stat" doesn't seem to be working with: cp.spawn('sox', [ '--type=wav', '-', '-n', 'stat' ])

What do you see in the console if you run that command directly?

cat myfile.wav | sox --type=wav - -n stat
vidicunt commented 2 years ago

On an unrelated note, do you know if it's possible to determine amplitude values from a stream?

I don't know.

"sox stat" doesn't seem to be working with: cp.spawn('sox', [ '--type=wav', '-', '-n', 'stat' ])

What do you see in the console if you run that command directly?

cat myfile.wav | sox --type=wav - -n stat

It does work, indeed! However I wanted to do it with a stream because I need to get the amplitude of sound at 60fps without writing to disk at all

ArtskydJ commented 2 years ago

I wonder if sox stat is trying to read the entire "file", so it doesn't write to stdout until the stream is finished?