pyaudio是否可以与tkinter一起使用?

时间:2019-04-12 09:13:19

标签: python python-3.x sockets tkinter pyaudio

我正在开发一个与Twitch(https://www.twitch.tv/)类似的python项目。 问题是我用tkinter显示图像,用pyaudio显示音频,只有音频可以工作。 有人有主意吗?

我尝试检查数据是否实际发送,并发现它已发送。但是,您只能听到音频而看不到图像。我不知道是什么问题。

"""
Server code
"""

import pyaudio
from socket import socket, error
from threading import Thread
from PIL import Image
from mss import mss
from io import BytesIO


CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
IP = '0.0.0.0'
PORT = 5000
MONITOR = {"top": 200, "left": 800, "width": 600, "height": 500}
SCREEN_PROTOCOL = 'S'
MICROPHONE_PROTOCOL = 'M'


class Server(object):
    def __init__(self, ip, port, chunk, format1, channels, rate, monitor):
        self.sock = socket()
        self.sock.bind((ip, port))
        self.conn = None
        self.monitor = monitor
        self.chunk = chunk
        self.format = format1
        self.channels = channels
        self.rate = rate
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(format=self.format, channels=self.channels,
                                  rate=self.rate, input=True, frames_per_buffer=self.chunk)
        self.data = ''

    def send_data(self, data):
        # Send the size of the pixels length
        size = len(data)
        size_len = (size.bit_length() + 7) // 8
        print('size len: ' + str(size_len))
        self.conn.send(bytes([size_len]))

        # Send the actual pixels length
        size_bytes = size.to_bytes(size_len, 'big')
        self.conn.send(size_bytes)

        print('size: ' + str(size))

        # Send pixels
        self.conn.sendall(data)

    def send_all(self):
        while True:
            with mss() as sct:
                screen = sct.grab(self.monitor)
            im = Image.frombytes('RGB', (600, 500), screen.rgb)
            buf = BytesIO()
            im.save(buf, format='JPEG', quality=75)
            self.data = buf.getvalue()
            self.send_data(self.data)

            self.data = self.stream.read(self.chunk)
            self.send_data(self.data)

    def start(self):
        self.sock.listen(5)
        print('Server started.')
        while True:
            self.conn, addr = self.sock.accept()
            print('Client connected IP:', addr)

            t = Thread(target=self.send_all)
            t.start()

    def close_connection(self):
        self.sock.close()


def main():
    """
    Add Documentation here
    """
    server = Server(IP, PORT, CHUNK, FORMAT, CHANNELS, RATE, MONITOR)
    try:
        server.start()
    except error as msg:
        print(msg)
    finally:
        server.close_connection()


if __name__ == '__main__':
    main()


"""
Client code
"""

import pyaudio
from socket import socket, error
from io import BytesIO
from PIL import Image, ImageTk
import tkinter


IP = '127.0.0.1'
PORT = 5000
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
WIDTH = 600
HEIGHT = 500


class Client:
    def __init__(self, ip, port, width, height, chunk, format1, channels, rate):
        self.sock = socket()
        self.sock.connect((ip, port))
        self.root = tkinter.Tk()
        self.size = str(width) + 'x' + str(height)
        self.root.geometry(self.size)
        self.panel = None
        self.protocol = ''
        self.chunk = chunk
        self.format = format1
        self.channels = channels
        self.rate = rate
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(format=self.format, channels=self.channels,
                                  rate=self.rate, output=True, frames_per_buffer=self.chunk)
        self.data = ''

    def recvall(self, length):
        """ Retreive all pixels. """

        buf = b''
        while len(buf) < length:
            data = self.sock.recv(length - len(buf))
            if not data:
                return data
            buf += data
        return buf

    def recv_and_display(self):
        print('screen shot')
        size_len = int.from_bytes(self.sock.recv(1), byteorder='big')
        print('size len: ' + str(size_len))
        size = int.from_bytes(self.sock.recv(size_len), byteorder='big')
        print('size: ' + str(size))
        self.data = self.recvall(size)
        # Create the Surface from raw pixels
        buf = BytesIO()
        buf.write(self.data)
        img = Image.open(buf).convert('RGB')
        tk_img = ImageTk.PhotoImage(image=img)
        if self.panel is None:
            print('a')
            self.panel = tkinter.Label(self.root, image=tk_img)
            self.panel.pack(side="bottom", fill="both", expand="yes")
        else:
            print('b')
            self.panel.configure(image=tk_img)

        print('audio')
        size_len = int.from_bytes(self.sock.recv(1), byteorder='big')
        print('size len: ' + str(size_len))
        size = int.from_bytes(self.sock.recv(size_len), byteorder='big')
        print('size: ' + str(size))
        self.data = self.recvall(size)

        self.stream.write(self.data)

        self.root.after(1, self.recv_and_display)

    def start(self):
        self.root.after(1, self.recv_and_display)
        self.root.mainloop()

    def close_connection(self):
        self.stream.stop_stream()
        self.stream.close()

        self.p.terminate()

        self.sock.close()


def main():
    """
    Add Documentation here
    """
    stream_client = Client(IP, PORT, WIDTH, HEIGHT, CHUNK, FORMAT, CHANNELS, RATE)
    try:
        stream_client.start()
    except error as msg:
        print(msg)
    finally:
        stream_client.close_connection()


if __name__ == '__main__':
    main()

我希望音频和图像都将显示在客户端。

0 个答案:

没有答案