Я отправлю тебе сейчас код моей пародии на дискорд. Добавь побольше фишек из дискорда (очень большое количество добавь КРОМЕ ТЕКСТОВОГО ЧАТА! но чтобы все работало. Не добавляй регистрацию. Сделай что то очень крутое и сделай многоуровневый интерфейс с большим кол-вом вкладок). Код клиента:
import sys
import socket
import pyaudio
import threading
from PyQt5 import QtWidgets, QtCore, QtGui

Настройки
HOST = '26.189.118.250' # Замените на IP-адрес сервера
PORT = 12345 # Тот же порт, что и на сервере

Настройки аудио
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100

class VoiceChatClient(QtWidgets.QMainWindow):
def init(self):
super().init()
self.setWindowTitle("Голосовой чат")
self.setGeometry(100, 100, 300, 200)
self.init_ui()
self.client_socket = None
self.audio = pyaudio.PyAudio()
self.stream = None
self.receive_thread = None
self.send_thread = None
self.is_connected = False

def init_ui(self):
# Виджеты
self.connect_btn = QtWidgets.QPushButton("Подключиться", self)
self.connect_btn.setGeometry(50, 50, 200, 40)
self.connect_btn.clicked.connect(self.connect_to_server)


self.disconnect_btn = QtWidgets.QPushButton("Отключиться", self)
self.disconnect_btn.setGeometry(50, 100, 200, 40)
self.disconnect_btn.clicked.connect(self.disconnect_from_server)
self.disconnect_btn.setEnabled(False)

self.status_label = QtWidgets.QLabel("Статус: Отключен", self)
self.status_label.setGeometry(50, 150, 200, 20)
self.status_label.setAlignment(QtCore.Qt.AlignCenter)

# Стили
self.setStyleSheet("""
    QMainWindow {
        background-color: #2c3e50;
    }
    QPushButton {
        background-color: #1abc9c;
        color: white;
        font-size: 16px;
        border-radius: 5px;
    }
    QPushButton:pressed {
        background-color: #16a085;
    }
    QLabel {
        color: white;
        font-size: 14px;
    }
""")
def connect_to_server(self):
if not self.is_connected:
self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.client_socket.connect((HOST, PORT))
self.is_connected = True
self.status_label.setText("Статус: Подключен")
self.connect_btn.setEnabled(False)
self.disconnect_btn.setEnabled(True)
# Запуск потоков для отправки и получения аудио
self.receive_thread = threading.Thread(target=self.receive_audio)
self.receive_thread.start()
self.send_thread = threading.Thread(target=self.send_audio)
self.send_thread.start()
except Exception as e:
QtWidgets.QMessageBox.warning(self, "Ошибка", f"Не удалось подключиться к серверу:\n{e}")

def disconnect_from_server(self):
if self.is_connected:
self.is_connected = False
self.client_socket.close()
self.status_label.setText("Статус: Отключен")
self.connect_btn.setEnabled(True)
self.disconnect_btn.setEnabled(False)

def receive_audio(self):
stream = self.audio.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
output=True,
frames_per_buffer=CHUNK)
try:
while self.is_connected:
data = self.client_socket.recv(CHUNK)
if not data:
break
stream.write(data)
except:
pass
finally:
stream.stop_stream()
stream.close()

def send_audio(self):
stream = self.audio.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
try:
while self.is_connected:
data = stream.read(CHUNK)
self.client_socket.sendall(data)
except:
pass
finally:
stream.stop_stream()
stream.close()

def closeEvent(self, event):
self.disconnect_from_server()
self.audio.terminate()
event.accept()
if name == "main":
app = QtWidgets.QApplication(sys.argv)
window = VoiceChatClient()
window.show()
sys.exit(app.exec_())

Код сервера:
import socket
import pyaudio
import threading

Настройки
HOST = '26.189.118.250' # Слушать все интерфейсы
PORT = 12345 # Порт сервера

Настройки аудио
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100

Списки клиентов
clients = []

Инициализация аудио
audio = pyaudio.PyAudio()

Функция для обработки входящих соединений
def handle_client(conn, addr):
stream = audio.open(format=FORMAT, channels=CHANNELS, rate=RATE, output=True, frames_per_buffer=CHUNK)
clients.append(conn)
print(f"{addr} подключился.")
try:
while True:
data = conn.recv(CHUNK)
if not data:
break

Отправляем звук всем остальным клиентам
for client in clients:
if client != conn:
client.sendall(data)
except:
pass
finally:
stream.stop_stream()
stream.close()
clients.remove(conn)
conn.close()
print(f"{addr} отключился.")

Запуск сервера
def start_server():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()
print("Сервер запущен и ожидает подключений...")
try:
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
except KeyboardInterrupt:
server.close()

if name == "main":
start_server()