pymumble icon indicating copy to clipboard operation
pymumble copied to clipboard

Stereo audio capture

Open AdelKS opened this issue 3 years ago • 2 comments

Hello,

I am trying to capture the audio of my machine using the example from music_bot.py, and modified it accordingly:

#!/usr/bin/env python

#!/usr/bin/python3

import pymumble_py3
import subprocess as sp
import audioop, time
import argparse

parser = argparse.ArgumentParser(description='get parameters.')

parser.add_argument('--server', '-s', required=True)
parser.add_argument('--port', '-P', type=int, default=64738)
parser.add_argument('--name', '-n', required=True)
parser.add_argument('--passwd', '-p', default="")
args = parser.parse_args()

server = args.server
nick = args.name
passwd = args.passwd
port = args.port

mumble = pymumble_py3.Mumble(server, nick, password=passwd, port=port, stereo=False)
mumble.set_receive_sound(True)
mumble.start()
mumble.is_ready()   #wait for Mumble to get ready to avoid errors after startup

while True:
    print("start Processing")
    command = ["ffmpeg", "-f", "pulse", "-i", "alsa_output.usb-SteelSeries_SteelSeries_GameDAC_000000000000-00.pro-output-0.monitor", "-f", "s16le", "-ab", "320k", "-ac", "1", "-ar", "48000",  "-"]
    sound = sp.Popen(command, stdout=sp.PIPE, stderr=sp.DEVNULL, bufsize=1024)
    print("playing")
    while True:
        raw_music = sound.stdout.read(1024)
        if not raw_music:
            break
        #mumble.sound_output.add_sound(audioop.mul(raw_music, 2, vol))   #adjusting volume
        mumble.sound_output.add_sound(raw_music)
    print("finished")
    while mumble.sound_output.get_buffer_size() > 0.5:  #
        time.sleep(0.01)
    print("sleep")
    time.sleep(2)

and this script works. However, if I try to do stereo capturing like this

#!/usr/bin/env python

#!/usr/bin/python3

import pymumble_py3
import subprocess as sp
import audioop, time
import argparse

parser = argparse.ArgumentParser(description='get parameters.')

parser.add_argument('--server', '-s', required=True)
parser.add_argument('--port', '-P', type=int, default=64738)
parser.add_argument('--name', '-n', required=True)
parser.add_argument('--passwd', '-p', default="")
args = parser.parse_args()

server = args.server
nick = args.name
passwd = args.passwd
port = args.port

mumble = pymumble_py3.Mumble(server, nick, password=passwd, port=port, stereo=True)
mumble.set_receive_sound(True)
mumble.start()
mumble.is_ready()   #wait for Mumble to get ready to avoid errors after startup

while True:
    print("start Processing")
    command = ["ffmpeg", "-f", "pulse", "-i", "alsa_output.usb-SteelSeries_SteelSeries_GameDAC_000000000000-00.pro-output-0.monitor", "-f", "s16le", "-ab", "320k", "-ac", "2", "-ar", "48000",  "-"]
    sound = sp.Popen(command, stdout=sp.PIPE, stderr=sp.DEVNULL, bufsize=1024)
    print("playing")
    while True:
        raw_music = sound.stdout.read(1024)
        if not raw_music:
            break
        #mumble.sound_output.add_sound(audioop.mul(raw_music, 2, vol))   #adjusting volume
        mumble.sound_output.add_sound(raw_music)
    print("finished")
    while mumble.sound_output.get_buffer_size() > 0.5:  #
        time.sleep(0.01)
    print("sleep")
    time.sleep(2)

it does not work anymore: the bot does connect but plays no sound and doesn't appear to be playing sound. Some insights would be very helpful ! The audio card I am capturing from is stereo and is receiving stereo audio.

Thanks!

Adel

AdelKS avatar Jan 29 '22 23:01 AdelKS

Hi, I had the same problem and spend quite some time debugging in various places.

The trick that finally did it for me was to set the audio bandwidth using

mumble.set_bandwidth(115600)

after mumble.is_ready() (Any value that is also a valid value in the mumble ui worked without trouble for me, I was even able to increase it further but for too high values I experienced dropouts until the Audio was gone completely)

It seems the opus encoder default bitrate is set too high for mumble to handle.

Edit: The command above sets the total bandwidth used by tha audio stream including the overhead. The actual opus bitrate is calculated in https://github.com/azlux/pymumble/blob/6aa2085157bee5db66d85a059dfc9ac9f770d4dd/pymumble_py3/soundoutput.py#L138 Doing tha calculation backwards allows us to calculate which bandwidth we need to set for a specific opus bitrate:

  • For a UDP connection with default settings you need to add 14000b/s to your bitrate
  • For a TCP Tunneling connection, add 19600b/s

So if you need 96kb/s audio over a TCP connection, you should set the bandwidth to 115600

ModellbahnFreak avatar Oct 18 '23 18:10 ModellbahnFreak

Oh thanks for your feedback ! I will report back as soon as I try it !

AdelKS avatar Oct 29 '23 21:10 AdelKS