I want to stream a webcam feed using socket programming in Python
camera, pygame, python, sockets, streaming
Solution
The problem is not the camera.
The problem is that you send a very large string over the socket and you incorrectly assume that you can read the entire string at once with `conn.recv(921637)`.
You'll have to call `recv` multiple times to receive all over your data. Try printing the length of `data` you send in `client.py` and print the length of `data` in `server.py` before calling `pygame.image.fromstring` and you'll see.
There are several ways to solve this:
- make a new connection for each image you send
- send the size of your data so the server knows how much data to read
- use some kind of end marker
Here's a simple example:
sender:
import socket
import pygame
import time
host = "localhost"
port = 1890
pygame.init()
image = pygame.surface.Surface((640, 480))
i=0
j=0
while 1:
image.fill((i,j,0))
i+=10
j+=5
if i >= 255: i = 0
if j >= 255: j = 0
data = pygame.image.tostring(image,"RGB")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall(data)
s.close()
time.sleep(0.5)
receiver:
import socket
import pygame
host="localhost"
port=1890
screen = pygame.display.set_mode((640,480))
while 1:
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
conn, addr = s.accept()
message = []
while True:
d = conn.recv(1024*1024)
if not d: break
else: message.append(d)
data = ''.join(message)
image = pygame.image.fromstring(data,(640,480),"RGB")
screen.blit(image,(0,0))
pygame.display.update()
Problem
This is my code: server.py: ``` #The server receives the data import socket from PIL import Image import pygame,sys import pygame.camera from pygame.locals import * import time host = "localhost" port = 1890 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((host,port)) s.listen(1) conn, addr = s.accept() print "connected by",addr screen = pygame.display.set_mode((640,480)) while 1: data = conn.recv(921637) image = pygame.image.fromstring(data,(640,480),"RGB") screen.blit(image,(0,0)) pygame.display.update() if not image: break; conn.send(data) conn.close() ``` client.py ``` #The client sends the data import socket from PIL import Image import pygame,sys import pygame.camera from pygame.locals import * import time host = "localhost" port = 1890 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) pygame.init() pygame.camera.init() cam = pygame.camera.Camera("/dev/video0",(640,480)) cam.start() while 1: image = cam.get_image() data = pygame.image.tostring(image,"RGB") s.sendall(data) s.close() print "recieved", repr(data) ``` Just to test, I tried the following code and it's working fine, but the above does not... Working code when implemeted without sockets: camcapture.py ``` import sys import time import pygame import pygame.camera from pygame.locals import * pygame.init() pygame.camera.init() cam = pygame.camera.Camera("/dev/video0",(640,480)) cam.start() screen = pygame.display.set_mode((640,480)) while 1: image = cam.get_image() data = pygame.image.tostring(image,"RGB") img = pygame.image.fromstring(data,(640,480),"RGB") screen.blit(img,(0,0)) pygame.display.update() ``` The error is: ``` image = pygame.image.fromstring(data,(640,480),"RGB") ValueError: String length does not equal format and resolution size ``` Where did I go wrong?