samirkumardas / opus-to-pcm

Decode raw opus packet to PCM without using any external library in your browser.
Other
73 stars 15 forks source link

Only noise.. #14

Closed amunhoz closed 5 years ago

amunhoz commented 5 years ago

I'm trying to stream a pulseaudio pcm to web browser, but i only get noise. Any help? Thanks in advance

Here is the code: nodejs

var path = require('path');
const WebSocket = require('ws');
const Pulse = require('pulseaudio2');
const prism = require('prism-media');

async function main() {
  const ctx = new Pulse();
  const rate = 24000
  ctx.on('state', (state) => {
      console.log('context:', state);
  });
  ctx.on('error', function(error){
    console.log(error)
    //
  });

  const opts = {
    channels: 1,
    rate:rate,
    format:'s16le',
    flags:'adjust_latency',
    latency:1000,
    properties: {
        'filter.want': 'echo-cancel',
        'application.id': 'node-stream-echo-cancelled',
    }
  };

  var rec = ctx.createRecordStream(opts)
  rec.on('state', (state) => {
    console.log('record:', state);
  });

  const express = require('express')
  const app = express()
  const server = require('http').createServer(app)
  app.use(express.static(path.resolve(__dirname, "./receiver")));
  server.listen(8080, function(){
    console.log('listening on port 8080')
  })
  var wss = new WebSocket.Server({server: server });
  wss.binaryType = "arraybuffer";
  console.log('Server ready...');
  wss.on('connection', function connection(ws) {
          console.log('Socket connected. sending data...');
  });

  const opus = new prism.opus.Encoder({ rate: rate, channels: 1, frameSize: rate/100});
  rec.pipe(opus)  
  opus.on("data", (buff) =>{
    wss.clients.forEach(function each(client) {
      if (client.readyState === WebSocket.OPEN) {
          client.send(buff);
      }
    });
  }) 

}

main();

html client

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Opus to PCM</title>
    <script type="text/javascript" src="./pcm-player.min.js"></script>
    <script type="text/javascript" src="./dist/opus_to_pcm.js"></script>
</head>
<body>
<div id="container" style="width: 400px; margin: 0 auto;">
    <h2>It should play audio if everying went well!</h2>
</div>
<script>
 window.onload = function() {
   var socketURL = 'ws://localhost:8080';
    var channels = 1;
   var decoder = new OpusToPCM({
        channels: channels,
        fallback: true,
        libopusPath: './dist/libopus/opus.min.js' 
    });
    var srate = decoder.getSampleRate()
    /*
    var player = new PCMPlayer({
        encoding: '16bitInt',
        channels: channels,
        sampleRate: decoder.getSampleRate(),
        flushingTime: 500
   });
   */
   var player = new PCMPlayer(channels, decoder.getSampleRate());   
    decoder.on('decode', function(pcmData) {
        player.feed(pcmData);    
    });

    var ws = new WebSocket(socketURL);
       ws.binaryType = 'arraybuffer';
       ws.addEventListener('message',function(event) {
                var data = new Uint8Array(event.data);
                decoder.decode(data)
    });

 }   

</script>
</body>
</html>

** Updated to 1 channel everywhere

samirkumardas commented 5 years ago

Getting noise means it was not converted into PCM properly Or number of channel issue. According to the server code, number of channels are two but in client side it is one.

Note this library convert raw opus packet (without ogg container ) into PCM. If you have already ogg container, you don't need this library, you can directly use decodeAudioData to convert into PCM

amunhoz commented 5 years ago

Thanks for the answer... however i've changed to one channel and same thing. About de encoding, i'm using https://www.npmjs.com/package/prism-media, wich i believe does raw encoding with a separated function to use ogg container. Tried too with https://www.npmjs.com/package/cjopus, wich is a direct interface to libopus.

Any ideas?

amunhoz commented 5 years ago

I've found a way to make it work. I was using your player from: https://github.com/samirkumardas/pcm-player

When i used the player from the example, everything worked fine. Is there any specific config to use it with the previous player?

samirkumardas commented 5 years ago

then it must be encoding issue. In the example I took 32bitFloat as my example data was so.

Anyways, you can define encoding 32bitFloat while PCM player instantiating. For example:

var player = new PCMPlayer({
    encoding: '32bitFloat',
    channels: 2,
    sampleRate: 8000,
    flushingTime: 2000
});