shichao-an / soundmeter

Simple real-time sound meter
https://soundmeter.shichao.io
BSD 2-Clause "Simplified" License
82 stars 27 forks source link

API and integration with a nodeJS app #21

Open Xyala opened 6 years ago

Xyala commented 6 years ago

Hi,

I'd like to integrate the readout from soundmeter into a nodeJS app I'm building. I'm actually not very familiar with Python so I wasn't able to figure exactly how to query which file in soundmeter using python-shell for example to retrieve the RMS value.

Right now I'm running soundmeter straight from the terminal. But ultimately I'd be calling it from my nodeJS app and use the value there.

Any advice ? Thanks

shichao-an commented 6 years ago

You can capture the live output from command-line soundmeter and get the value in your NodeJS. Since I don't know NodeJS, I can give you an example in Python that reads value from the live output of a running command:

import subprocess

process = subprocess.Popen("/usr/local/bin/soundmeter ", stdout=subprocess.PIPE,
                           stderr=None, shell=True)

while process.poll() is None:
    line = process.stdout.readline()
    # here each line is a RMS value
    print(line)
Xyala commented 6 years ago

Hm, I see. Tried the python code you put, terminal stays blank

Is there a way that I could call directly one of the soundmeter .py files with arguments and config (not using the cli call)

Then I could easily get the output that way maybe: https://ourcodeworld.com/articles/read/286/how-to-execute-a-python-script-and-retrieve-output-data-and-errors-in-node-js

shichao-an commented 6 years ago

Sorry. The code didn't work because the output from the soundmeter is starting with carriage return (\r) instead of newline (\n).

The following should work:

import subprocess

process = subprocess.Popen("bash echo.sh", stdout=subprocess.PIPE,
                           stderr=None, shell=True)

while process.poll() is None:
    line_buffer = []
    while True:
        c = process.stdout.read(1)
        line_buffer.append(c)
        if c == '\r':
            break
    print(''.join(line_buffer))

But to make things easier, I need to make some code changes:

  1. Check if sys.stdout is connected to TTY device (console) using isatty() and print newline instead of carriage return.
  2. Add a command-line option like --simple or --silent which only outputs the RMS without printing human-readable texts or messages.

Then, you can call soundmeter with arguments.

Xyala commented 6 years ago

Ha! thanks, that works now.

Yes indeed that would be perfect.

Or, if your lib has a .py script that can be called directly and outputs the data in JSON then it's even "cleaner" to pickup from other languages that might want to use the output. Could come with the likes of :

Another question - slightly related, if I want to perform more readouts (right now it seems it's like 1/sec or so) can it be set from parameters?

shichao-an commented 6 years ago

That's a good point. I can add some arguments to the soundmeter command to output JSON format and include RMS, timestamp, and other info (warning message, etc.).

For your second question, you can specify audio segment length in seconds by using --segment argument or audio_segment_length in config. For example, --segment 0.1 makes the segment length 0.1 second, which can output more frequently.

Xyala commented 6 years ago

ok that's perfect yes! Let me know if you need any testing with the API when you get to implement it. :)