Send Video over TCP using OpenCV and sockets in Raspberry Pi
Solution 1
Create a file with code below, run server code in Powershell on Windows by running for example
python "C:\path\toFile\streamTestServer.py"
Code is:
import socket
import sys
import cv2
import pickle
import numpy as np
import struct
HOST = '127.0.0.1'
PORT = 8083
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
s.bind((HOST, PORT))
print('Socket bind complete')
s.listen(10)
print('Socket now listening')
conn, addr = s.accept()
data = b''
payload_size = struct.calcsize("L")
while True:
while len(data) < payload_size:
data += conn.recv(4096)
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("L", packed_msg_size)[0]
while len(data) < msg_size:
data += conn.recv(4096)
frame_data = data[:msg_size]
data = data[msg_size:]
frame=pickle.loads(frame_data)
print(frame.size)
cv2.imshow('frame', frame)
cv2.waitKey(10)
Then run client in Python IDLE or in another window of Powershell. Client code is:
import cv2
import numpy as np
import socket
import sys
import pickle
import struct
cap = cv2.VideoCapture(0)
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect(('127.0.0.1', 8083))
while True:
ret,frame = cap.read()
data = pickle.dumps(frame)
clientsocket.sendall(struct.pack("L", len(data)) + data)
Now you are streaming from localhost client to localhost server.
Solution 2
According to my understanding, you should use the same ports for client and server, but you are using two different ones, 8083 and 8081.
Have you checked that the firewall is opened for the port used?
Solution 3
After hours of analysis why the server.py and client.py weren't working(even after the firewall was disabled), there was an error in the server.py code: "word should not be a string". Therefore, word = "" (which is a string) should be changed to word = b'' (these are two single quotes to represent a byte).
Solution 4
Using this same program, I have had problems receiving data on my raspberry pi. I found out that this was because of the difference between how "L" for unsigned long is used on the different machines. At least for me, their native representations on the different machines were different. I fixed this by adding a "=" in the format string to force struct to unpack using the standard size of "L" (4).
payload_size = struct.calcsize("=L")
and
clientsocket.sendall(struct.pack("=L", len(data)) + data)
and so on
Shinchan
Updated on June 16, 2022Comments
-
Shinchan almost 2 years
I have been trying to send live video frame from my client (Raspberry Pi) to a server hosted on Laptop. Both these devices are connected to the same network.
Server.py
import socket import sys import cv2 import pickle import numpy as np import struct HOST = '192.168.1.3' PORT = 8083 s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) print 'Socket created' s.bind((HOST, PORT)) print 'Socket bind complete' s.listen(10) print 'Socket now listening' conn, addr = s.accept() data = "" payload_size = struct.calcsize("L") while True: while len(data) < payload_size: data += conn.recv(4096) packed_msg_size = data[:payload_size] data = data[payload_size:] msg_size = struct.unpack("L", packed_msg_size)[0] while len(data) < msg_size: data += conn.recv(4096) frame_data = data[:msg_size] data = data[msg_size:] frame=pickle.loads(frame_data) print frame.size # cv2.imshow('frame', frame) # cv2.waitKey(10)
Client.py
import cv2 import numpy as np import socket import sys import pickle import struct cap = cv2.VideoCapture(0) clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) clientsocket.connect(('192.168.1.3', 8081)) while True: ret,frame = cap.read() data = pickle.dumps(frame) clientsocket.sendall(struct.pack("L", len(data)) + data)
My server on laptop is not receiving any data. But when I run this client and server on same devices (e.g. server and client on laptop) then it is working properly.
I am able to send data from raspberry to laptop (tested for echo application).
Can anyone help me with this ?
-
Shinchan about 8 yearsEven when I put my port numbers same, still it is the same problem. And all firewall rules allow connections on that port.
-
tfv about 8 yearsHave you checked that the actual IP of your host machine (as obtained by ipconfig) is the same as the one you use in your program? Does a ping work in both directions?
-
Shinchan about 8 yearsproblem i am getting is "payload_size" in server is getting a very big value (7898745431321384897974964) and because of this the program is in an infinite loop.
-
TaeWoo over 6 yearscan you share the full code? i dont see "word=" in your server.py code
-
Cristian Zumelzu over 3 yearsyou are right, after this little change works, thanks!