Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有一种方法可以使用Python同步实时音频和实时视频?_Python_Multithreading_Sockets_Audio_Synchronization - Fatal编程技术网

有没有一种方法可以使用Python同步实时音频和实时视频?

有没有一种方法可以使用Python同步实时音频和实时视频?,python,multithreading,sockets,audio,synchronization,Python,Multithreading,Sockets,Audio,Synchronization,我正试图编写一些代码来使用Python3创建一个2人实时聊天应用程序。该代码的工作原理是具有实时音频和实时视频(通过在同一设备上运行服务器和2个客户端进行测试),客户端代码运行大部分逻辑,并运行摄像头和音频馈送以通过服务器发送,(这也是两个客户端之间握手的一种形式,除了一个客户端发送视频和/或音频以将其发送给另一个客户端之外,没有什么逻辑),以便使用客户端代码来播放音频和视频 公平警告,此代码有点凌乱,未针对快速性能进行优化 客户端代码: import cv2 from socket impor

我正试图编写一些代码来使用Python3创建一个2人实时聊天应用程序。该代码的工作原理是具有实时音频和实时视频(通过在同一设备上运行服务器和2个客户端进行测试),客户端代码运行大部分逻辑,并运行摄像头和音频馈送以通过服务器发送,(这也是两个客户端之间握手的一种形式,除了一个客户端发送视频和/或音频以将其发送给另一个客户端之外,没有什么逻辑),以便使用客户端代码来播放音频和视频

公平警告,此代码有点凌乱,未针对快速性能进行优化

客户端代码:

import cv2
from socket import socket, AF_INET, SOCK_STREAM
from imutils.video import WebcamVideoStream
import pyaudio
from array import array
from threading import Thread
import numpy as np
import zlib
import struct

HOST = input("Enter Server IP\n")
PORT_VIDEO = 3000
PORT_AUDIO = 4000

BufferSize = 4096
CHUNK=1024
lnF = 640*480*3
FORMAT=pyaudio.paInt16
CHANNELS=2
RATE=44100

def SendAudio():
    while True:
        data = stream.read(CHUNK)
        dataChunk = array('h', data)
        vol = max(dataChunk)
        clientAudioSocket.sendall(data)

def RecieveAudio():
    while True:
        data = recvallAudio(BufferSize)
        stream.write(data)

def recvallAudio(size):
    databytes = b''
    while len(databytes) != size:
        to_read = size - len(databytes)
        if to_read > (4 * CHUNK):
            databytes += clientAudioSocket.recv(4 * CHUNK)
        else:
            databytes += clientAudioSocket.recv(to_read)
    return databytes

def SendFrame():
    while True:
        try:
            frame = wvs.read()
            cv2_im = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame = cv2.resize(frame, (640, 480))
            frame = np.array(frame, dtype = np.uint8).reshape(1, lnF)
            jpg_as_text = bytearray(frame)

            databytes = zlib.compress(jpg_as_text, 9)
            length = struct.pack('!I', len(databytes))
            bytesToBeSend = b''
            clientVideoSocket.sendall(length)
            while len(databytes) > 0:
                if (5000 * CHUNK) <= len(databytes):
                    bytesToBeSend = databytes[:(5000 * CHUNK)]
                    databytes = databytes[(5000 * CHUNK):]
                    clientVideoSocket.sendall(bytesToBeSend)
                else:
                    bytesToBeSend = databytes
                    clientVideoSocket.sendall(bytesToBeSend)
                    databytes = b''
            # ~ print("##### Data Sent!! #####")
        except:
            continue


def RecieveFrame():
    while True:
        try:
            lengthbuf = recvallVideo(4)
            length, = struct.unpack('!I', lengthbuf)
            databytes = recvallVideo(length)
            img = zlib.decompress(databytes)
            if len(databytes) == length:
                # ~ print("Recieving Media..")
                # ~ print("Image Frame Size:- {}".format(len(img)))
                img = np.array(list(img))
                img = np.array(img, dtype = np.uint8).reshape(480, 640, 3)
                cv2.imshow("Stream", img)
                if cv2.waitKey(1) == 27:
                    cv2.destroyAllWindows()
            else:
                print("Data CORRUPTED")
        except:
            continue


def recvallVideo(size):
    databytes = b''
    while len(databytes) != size:
        to_read = size - len(databytes)
        if to_read > (5000 * CHUNK):
            databytes += clientVideoSocket.recv(5000 * CHUNK)
        else:
            databytes += clientVideoSocket.recv(to_read)
    return databytes



clientVideoSocket = socket(family=AF_INET, type=SOCK_STREAM)
clientVideoSocket.connect((HOST, PORT_VIDEO))
wvs = WebcamVideoStream(0).start()

clientAudioSocket = socket(family=AF_INET, type=SOCK_STREAM)
clientAudioSocket.connect((HOST, PORT_AUDIO))

audio=pyaudio.PyAudio()
stream=audio.open(format=FORMAT,channels=CHANNELS, rate=RATE, input=True, output = True,frames_per_buffer=CHUNK)

initiation = clientVideoSocket.recv(5).decode()

if initiation == "start":
    SendFrameThread = Thread(target=SendFrame).start()
    SendAudioThread = Thread(target=SendAudio).start()
    RecieveFrameThread = Thread(target=RecieveFrame).start()
    RecieveAudioThread = Thread(target=RecieveAudio).start()
from socket import socket, AF_INET, SOCK_STREAM
from threading import Thread
import struct

HOST = input("Enter Host IP\n")
PORT_VIDEO = 3000
PORT_AUDIO = 4000
lnF = 640*480*3
CHUNK = 1024
BufferSize = 4096
addressesAudio = {}
addresses = {}
threads = {}

def ConnectionsVideo():
    while True:
        try:
            clientVideo, addr = serverVideo.accept()
            print("{} is connected!!".format(addr))
            addresses[clientVideo] = addr
            if len(addresses) > 1:
                for sockets in addresses:
                    if sockets not in threads:
                        threads[sockets] = True
                        sockets.send(("start").encode())
                        Thread(target=ClientConnectionVideo, args=(sockets, )).start()
            else:
                continue
        except:
            continue

def ConnectionsSound():
    while True:
        try:
            clientAudio, addr = serverAudio.accept()
            print("{} is connected!!".format(addr))
            addressesAudio[clientAudio] = addr
            Thread(target=ClientConnectionSound, args=(clientAudio, )).start()
        except:
            continue

def ClientConnectionVideo(clientVideo):
    while True:
        try:
            lengthbuf = recvall(clientVideo, 4)
            length, = struct.unpack('!I', lengthbuf)
            recvall(clientVideo, length)
        except:
            continue

def ClientConnectionSound(clientAudio):
    while True:
        try:
            data = clientAudio.recv(BufferSize)
            broadcastSound(clientAudio, data)
        except:
            continue

def recvall(clientVideo, BufferSize):
        databytes = b''
        i = 0
        while i != BufferSize:
            to_read = BufferSize - i
            if to_read > (1000 * CHUNK):
                databytes = clientVideo.recv(1000 * CHUNK)
                i += len(databytes)
                broadcastVideo(clientVideo, databytes)
            else:
                if BufferSize == 4:
                    databytes += clientVideo.recv(to_read)
                else:
                    databytes = clientVideo.recv(to_read)
                i += len(databytes)
                if BufferSize != 4:
                    broadcastVideo(clientVideo, databytes)
        # ~ print("YES!!!!!!!!!" if i == BufferSize else "NO!!!!!!!!!!!!")
        if BufferSize == 4:
            broadcastVideo(clientVideo, databytes)
            return databytes

def broadcastVideo(clientSocket, data_to_be_sent):
    for clientVideo in addresses:
        if clientVideo != clientSocket:
            clientVideo.sendall(data_to_be_sent)

def broadcastSound(clientSocket, data_to_be_sent):
    for clientAudio in addressesAudio:
        if clientAudio != clientSocket:
            clientAudio.sendall(data_to_be_sent)

serverVideo = socket(family=AF_INET, type=SOCK_STREAM)
try:
    serverVideo.bind((HOST, PORT_VIDEO))
except OSError:
    print("Server Busy")

serverAudio = socket(family=AF_INET, type=SOCK_STREAM)
try:
    serverAudio.bind((HOST, PORT_AUDIO))
except OSError:
    print("Server Busy")

serverAudio.listen(2)
print("Waiting for audio connection..")
AcceptThreadAudio = Thread(target=ConnectionsSound)
AcceptThreadAudio.start()


serverVideo.listen(2)
print("Waiting for video connection..")
AcceptThreadVideo = Thread(target=ConnectionsVideo)
AcceptThreadVideo.start()
AcceptThreadVideo.join()
serverVideo.close()

这两个代码都是我花了比我希望的时间长一点的时间拼凑起来的,但是我注意到,在使用这些代码进行一些测试时,音频和视频在3到7秒之间的任何地方都出现了问题。我尝试了一些故障排除,但除了看起来像一个kid把这一切都放在了一起。我可以导入一个新的Python包,但我更喜欢使用我已经准备好的Python包。请记住,我正在考虑最终将这两个代码转换为单独的.exe文件,以便轻松访问,将代码发送给个人。

为了减少延迟,请减小缓冲区然而,我看到你的缓冲区已经很小了,所以滞后是来自其他地方……作为一个编程挑战,我赞扬你,但是如果你的目标是实现最佳质量的直播音频/视频,我会尽量避免让服务器坐在中间的两党…WebRTC是一种现代的方式创建一个视频聊天直接连接两个人避免中间的任何服务器来减少滞后,使缓冲区更小,但我看到你的缓冲区已经很小了,所以滞后是来自其他地方……作为一个编程挑战,我赞扬你,但是如果你的目标是实现最佳质量的直播音频/视频,我会尽量避免让服务器坐在中间的TW之间。o……WebRTC是一种现代的方式来创建视频聊天,它直接连接两个人,避免中间的任何服务器。