Задать вопрос
  • Как избавиться от лагов в sounddevice на python3?

    @Stariy_Volk Автор вопроса
    import sounddevice as sd
    import json
    import threading
    import time
    from datetime import datetime
    import socket
    
    
    f = open('config.json', 'r')
    config = json.loads(f.read())
    
    speaking = True
    
    blockCount = 4
    # b_size = 48000
    b_size = 150
    
    fs = 48000
     
    myData = []
    outputData = []
    clients = {}
    
    # print(sd.query_devices())
    
    
    def local_output(outdata, frames, time, status):
        if(len(myData)):
            outdata[:] = myData.pop(0)
        else:
            outdata[:] = b'\x00' * len(outdata)
            
    
    def inStream(indata, frames, time, status):
        global myData
        send_data(indata)
        myData.append(indata)
        # print('out', len(indata))
        # outdata[:] = indata
        # outdata[:] = b'\x00' * len(outdata)
    
    
    def send_data(data):
        # print(clients)
        for addr in clients:
            send_thread = threading.Thread(target=send_data_personal, args=(clients[addr]['config'],data))
            send_thread.start()
    
    
    def send_data_personal(conf, data):
        client = socket.socket()
        client.settimeout(1)
        # print((conf['interface'], conf['port'] + 10))
        try:
            client.connect((conf['interface'], conf['port'] + 10))
            client.send(data)
            client.close()
        except socket.timeout as err:
            er = err
            print(er)
        except socket.error as err:
            er = err
            print(er)
    
    
    def readData(data):
        for buf in data:
            global outputData
            outputData.append(buf)
    
    
    def serverReady():
        server = socket.socket()
        server.bind(('', config['port'] + 10))
        server.listen(100)
        print('Receive server started on port: ' + str(config['port'] + 10))
        while True:
            conn, addr = server.accept()
            data = conn.recv(b_size * 4)
            if len(data) > 0:
                if clients.get(addr[0]):
                    # print(clients[addr[0]].get('stream'))
                    if clients[addr[0]].get('stream'):
                        clients[addr[0]]['buffer'] = data
                    else:
                        def inside_output(outdata, frames, time, status):
                            # print(len(outdata), len(clients[addr[0]]['buffer']))
                            print('inbound', len(outdata), len(clients[addr[0]]['buffer']))
                            if len(clients[addr[0]]['buffer']):
                                if len(outdata) == len(clients[addr[0]]['buffer']):
                                    outdata[:] = clients[addr[0]]['buffer']
                                    clients[addr[0]]['buffer'] = b''
                                else:
                                    outdata[0:len(clients[addr[0]]['buffer'])] = clients[addr[0]]['buffer']
                                    outdata[len(clients[addr[0]]['buffer']):] = b'\x00' * (len(outdata) - len(clients[addr[0]]['buffer']))
                                    clients[addr[0]]['buffer'] = b''
                            else:
                                outdata[:] = b'\x00' * len(outdata)
    
                        clients[addr[0]]['buffer'] = b''
                        clients[addr[0]]['stream'] = sd.RawOutputStream(samplerate=fs, dtype='int16', channels=1, latency=0, callback=inside_output, blocksize=b_size)
                        clients[addr[0]]['stream'].start()
                else:
                    print('empty')
    
    
    def discover_server():
        discover = socket.socket()
        discover.bind(('', config['port']))
        discover.listen(10)
    
        while True:
            conn, addr = discover.accept()
            # print(addr)
            # data = conn.recv(1024)
            conn.send(json.dumps(config).encode())
            conn.close()
    
    
    def discover_client():
        while True:
            my_clients = {}
            for i in range(255):
                ip = '192.168.31.' + str(i)
                # print(ip == config['interface'])
                if ip != config['interface']:
                    client = socket.socket()
                    client.settimeout(0.05)
    
                    try:
                        client.connect((ip, config['port']))
                        data = client.recv(1024).decode()
                        # print(data)
                        my_clients[ip] = {}
                        my_clients[ip]['config'] = json.loads(data)
    
                    except socket.timeout as err:
                        er = err
                        # print(er)
                    except socket.error as err:
                        er = err
                        # print(er)        
            for addr in my_clients:
                if clients.get(addr):
                    clients[addr]['config'] = my_clients[addr]['config']
                else:
                    clients[addr] = my_clients[addr]
    
            # print(clients)
            time.sleep(4)
    
    
    input_stream = sd.RawInputStream(callback=inStream, samplerate=fs, channels=1, latency=0, dtype='int16', blocksize=b_size)
    input_stream.start()
    print('Input Stream started')
    
    # local_stream = sd.RawOutputStream(samplerate=fs, dtype='int16', channels=1, latency=0, callback=local_output, blocksize=b_size)
    # local_stream.start()
    # print('Output Stream started')
    
    discover_server_thread = threading.Thread(target=discover_server, args=())
    discover_server_thread.start()
    print('Discover server started')
    
    discover_client_thread = threading.Thread(target=discover_client, args=())
    discover_client_thread.start()
    print('Discover client started')
    
    receive_server_thread = threading.Thread(target=serverReady, args=())
    receive_server_thread.start()
    
    print('#' * 80)
    print('press Return to quit')
    print('#' * 80)
    input()