[MacOS API] Is there a way to set an audiofile as input instead of mic recording?

Hi, i’m using a snips audio server on my mac.
Then i have a python mqtt Client in python to get message from microphone to snips NLU and get the output.
But what i want to do is to take an external wav (or whatever the format ) file in snips, process it and get the output.
I can’t find a working tricks to do that on internet, and i won’t emulate microphone with some stuff like soundflower.
Thanks.

Yes, look at the --hijack and --no-mike parameters.

It does use a file but allows you to inject directly the content of a wave file (16bits, 16000samples/sec) on a tcp socket.

Thank’s for your reply, i’ve heard about this on forum, i saw something like this on a github : --nomike --hijack 0.0.0.0:1234 &
And then cat a wav file content and redirect output with netcat to the specified port (1234)
cat myWavFile.wav | nc localhost 1234

But nothing happened on my mqtt client ( no “onmessage” event received )
Isn’t there a way with mqtt publish or something like that ?
Or maybe i’ve missed something with the --nomike command.
Thank’s.

Hello @timo,

Should work as we use this feature for automated testing everyday.

You need to make sure of few things before hand.

  • Your wave file should be encoded at S16LE Mono 16000 samples per seconds
  • Also your snips-audio-server process must be authorised to accept incoming network connection from your MacOS firewall. (you should get a pop up or go to Security and Privacy => Firewall => Firewall options to check that)

For a minimal tests

Execute those commands in a terminal

snips-audio-server --no-mike --hijack=0.0.0.0:8888 -v
snips-hotword -v

And then

cat your_wave_file.wav | nc localhost 8888

If your wave file contains a hotword, you should see the wake word detector trigger.

Notes

  • Use 0.0.0.0 if you want to send audio data to your snips-audio-server over your local network

  • Use 127.0.0.1 if you want it to be accessible only from your mac

  • instead of nc, you can also use a python script using

import socket
import os

def inject_audio(audio_file_path: str, host: str = '127.0.0.1', hijack_port: str = `8888`) -> None:
        """Inject audio file into the audio server. (hijack MUST be enabled)

        Args:
            audio_file_path: Path to the audio file (Format: 16-kHz 16-bit Signed Integer PCM)
            host: audio server IP address (default: 127.0.0.1)
            port: audio server port (default:8888)

        Returns:
            None
        """
        if not os.path.exists(audio_file_path):
            msg = "File does not exist: {}".format(audio_file_path)
            raise FileNotFoundError(msg)

        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            s.connect((host, hijack_port))
        except ConnectionRefusedError:
            msg = "Cannot connect to {}:{}".format(host, hijack_port)
            raise ConnectionRefusedError(msg)

        msg = "Streaming {} to {}:{}".format(audio_file_path, host, hijack_port)
        print(msg)
        with open(audio_file_path, 'rb') as f:
            s.send(f.read())
        msg = "Stream finished."
        print(msg)

Wow thank’s, i’m gonna try this out asap. Thank’s all for your help, cdt.

Works like charm, thanks a lot.

1 Like