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?

Original source

Related problems