Moderators: Despellanion, Dr. Best

Stream Video Over Network With Python

Sothh
Forum God
Sothh
Forum God
Joined: March 25th, 2009, 4:12 pm

August 1st, 2010, 8:01 pm #1

I have been trying (with not success) to stream video over my home network. I am using this code for the server:

Code: Select all

import socket
from VideoCapture import *
from PIL import *

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((socket.gethostname(),5000))
server_socket.listen(5)

camera = Device()

image = camera.getImage()

print "Server Waiting for client on port 5000"

while 1:
        client_socket, address = server_socket.accept()
        print "I got a connection from ", address

        while 1:

                image = camera.getImage().convert("RGB")

                data = image.tostring()
                
                client_socket.send(data)
And this for the client:

Code: Select all

import socket
import pygame

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((socket.gethostname(),5000))

pygame.init()
screen = pygame.display.set_mode((320,240))
pygame.display.set_caption('Remote Webcam Viewer')
font = pygame.font.SysFont("Arial",14)
clock = pygame.time.Clock()

while 1:

  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      sys.exit()

  data = client_socket.recv(1024)

  image = pygame.image.frombuffer(data,(320,240),"RGB")

  output = image
                            
  screen.blit(output,(0,0))
  
  clock.tick(60)
  pygame.display.flip()
But I get this error:

Code: Select all

Traceback (most recent call last):
  File "C:\Users\Sothh\Desktop\Python\Programs\Other\Webcam\Remote Viewer\Client.py", line 21, in <module>
    image = pygame.image.frombuffer(data,(320,240),"RGB")
ValueError: Buffer length does not equal format and resolution size
Does anyone see the problem?
?You can?t outrun Death forever.
But you can make the Bastard work for it.?

Major Korgo Korgar
?Last of The Lancers? - AFC 32
(Andromeda Ascendant Record Database)
Quote
Like
Share

Despellanion
Forum God
Joined: March 26th, 2006, 8:41 pm

August 1st, 2010, 8:20 pm #2

Sothh wrote:Does anyone see the problem?
It tells you right here

Code: Select all

ValueError: Buffer length does not equal format and resolution size
Quote
Like
Share

Sothh
Forum God
Sothh
Forum God
Joined: March 25th, 2009, 4:12 pm

August 1st, 2010, 8:27 pm #3

Yes, but I want to know why it does not equal the correct format and resolution.
?You can?t outrun Death forever.
But you can make the Bastard work for it.?

Major Korgo Korgar
?Last of The Lancers? - AFC 32
(Andromeda Ascendant Record Database)
Quote
Like
Share

Sothh
Forum God
Sothh
Forum God
Joined: March 25th, 2009, 4:12 pm

August 2nd, 2010, 4:18 pm #4

I found the problem. I was sending way too much data over the port, so must of it never got to the other end.

I am having a new problem now. I get the image at the other end, but it is just a still; the image does not update (video).

Here the server:

Code: Select all

import socket
from VideoCapture import *
from PIL import *

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((socket.gethostname(),5000))
server_socket.listen(5)

camera = Device()

image = camera.getImage()

print "Server Waiting for client on port 5000"

while 1:

    client_socket, address = server_socket.accept()
    print "I got a connection from ", address

    image = camera.getImage().convert("RGB")

    image = image.resize((80,60))

    data = image.tostring()

    client_socket.sendall(data)
And the client:

Code: Select all

import socket
import pygame


client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((socket.gethostname(),5000))

pygame.init()
screen = pygame.display.set_mode((640,480))
pygame.display.set_caption('Remote Webcam Viewer')
font = pygame.font.SysFont("Arial",14)
clock = pygame.time.Clock()

while 1:

  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      sys.exit()
      
  data = client_socket.recv(409600000)
  
  image = pygame.image.frombuffer(data,(80,60),"RGB")
  
  output = image
                            
  screen.blit(output,(0,0))
  
  clock.tick(60)
  pygame.display.flip()
Why to I get the feeling that no one will have any idea what the problem is?
?You can?t outrun Death forever.
But you can make the Bastard work for it.?

Major Korgo Korgar
?Last of The Lancers? - AFC 32
(Andromeda Ascendant Record Database)
Quote
Like
Share

Sothh
Forum God
Sothh
Forum God
Joined: March 25th, 2009, 4:12 pm

August 3rd, 2010, 3:05 pm #5

Fixed it.
?You can?t outrun Death forever.
But you can make the Bastard work for it.?

Major Korgo Korgar
?Last of The Lancers? - AFC 32
(Andromeda Ascendant Record Database)
Quote
Like
Share

ayasakr
Newbie
ayasakr
Newbie
Joined: April 17th, 2011, 1:50 pm

April 17th, 2011, 1:53 pm #6

Can you pleas state how you solved this problem?
Quote
Like
Share

Sothh
Forum God
Sothh
Forum God
Joined: March 25th, 2009, 4:12 pm

April 17th, 2011, 2:30 pm #7

Sure, its been a long time, but here is my code:


Server:

Code: Select all

import socket
from VideoCapture import *
from PIL import *

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((socket.gethostname(),5000))
server_socket.listen(5)


print "Your IP address is: ", socket.gethostbyname(socket.gethostname())

camera = Device()

image = camera.getImage()

print "Server Waiting for client on port 5000"

while 1:


    client_socket, address = server_socket.accept()
    
    image = camera.getImage().convert("RGB")

    image = image.resize((120,90))

    #image.save("webcam.jpg")

    data = image.tostring()

    client_socket.sendall(data)

Code: Select all

import socket
import pygame
import Image

#Create a var for storing an IP address:
ip = raw_input("Please enter the IP address: ")

#Start PyGame:
pygame.init()
#Create a PyGame screen, and set its size to 640x480L
screen = pygame.display.set_mode((640,480))
#Set the window caption:
pygame.display.set_caption('Remote Webcam Viewer')
#Load a font:
font = pygame.font.SysFont("Arial",14)
#Create a PyGame clock which will be used to limit the fps:
clock = pygame.time.Clock()

#Create some more var's:
timer = 0
previousImage = ""
image = ""

#Main program loop:
while 1:

  #Check if the exit button has been pressed:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      sys.exit()
      
  #We use a timer to limit how many images we request from the server each second:
  if timer < 1:

    #Create a socket connection for connecting to the server:
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((str(ip),5000))

    #Recieve data from the server:
    data = client_socket.recv(1024000)

    #Set the timer back to 30:
    timer = 30

  else:

    #Count down the timer:
    timer -= 1

  #We store the previous recieved image incase the client fails to recive all of the data for the new image:
  previousImage = image

  #We use a try clause to the program will not abort if there is an error:
  try:

    #We turn the data we revieved into a 120x90 PIL image:
    image = Image.fromstring("RGB",(120,90),data)

    #We resize the image to 640x480:
    image = image.resize((640,480))

    #We turn the PIL image into a surface that PyGame can display:
    image = pygame.image.frombuffer(image.tostring(),(640,480),"RGB")

  except:

    #If we failed to recieve a new image we display the last image we revieved:
    image = previousImage

  #Set the var output to our image:    
  output = image

  #We use PyGame to blit the output image to the screen:
  screen.blit(output,(0,0))

  #We set our clock to tick 60 times a second, which limits the frame rate to that amount:
  clock.tick(60)
  #We update the screen:
  pygame.display.flip()
I think the solution lies in this after this comment:

#We use a timer to limit how many images we request from the server each second:

I had to make create a new socket connection for each frame, but do it based on a timer, or you will flood the stream.

Oh, and remember if you use a larger video size, you might need to tweak the size of data you receive, and the PyGame window size.

By the way, I am currently playing around with something similar to send audio over a network.
?You can?t outrun Death forever.
But you can make the Bastard work for it.?

Major Korgo Korgar
?Last of The Lancers? - AFC 32
(Andromeda Ascendant Record Database)
Quote
Like
Share

ayasakr
Newbie
ayasakr
Newbie
Joined: April 17th, 2011, 1:50 pm

April 18th, 2011, 9:21 am #8

THANKS A LOT!

Right now I will be trying to stream this video from this python server to a java client. As soon as this works I'll work on sending audio over from python server to python client and switch to the java client for audio as well.

But if you get to it first please do share it :)

Thanks again !
Quote
Like
Share

Sothh
Forum God
Sothh
Forum God
Joined: March 25th, 2009, 4:12 pm

April 18th, 2011, 1:16 pm #9

Your welcome.

I have audio streaming working, though I started using Pyro for the networking, which wont work it you need to use a Java client.

I might redo the code using sockets today, and upload it a bit later.

Once you get a Java client working would you mind sharing the code? I dont do very much in Java, so it would be quite interesting to see how a Java client works with a Python server.
?You can?t outrun Death forever.
But you can make the Bastard work for it.?

Major Korgo Korgar
?Last of The Lancers? - AFC 32
(Andromeda Ascendant Record Database)
Quote
Like
Share

Sothh
Forum God
Sothh
Forum God
Joined: March 25th, 2009, 4:12 pm

April 18th, 2011, 4:46 pm #10

Do you need one way audio or two way? I have code for both, but I will post the one way audio:

Server:

Code: Select all

import pyaudio
import sys
import socket


chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 15000
timer = 0

p = pyaudio.PyAudio()

stream = p.open(format = FORMAT,channels = CHANNELS,rate = RATE,input = True,output = True,frames_per_buffer = chunk)

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((socket.gethostname(),5000))
server_socket.listen(5)


print "Your IP address is: ", socket.gethostbyname(socket.gethostname())

print "Server Waiting for client on port 5000"

while 1:

    client_socket, address = server_socket.accept()

    client_socket.sendall(stream.read(chunk))
Client:

Code: Select all

import pyaudio
import sys
import socket

ip = "192.168.2.1"

chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 15000
timer = 0

p = pyaudio.PyAudio()

stream = p.open(format = FORMAT,channels = CHANNELS,rate = RATE,input = True,output = True,frames_per_buffer = chunk)

while 1:

    #Create a socket connection for connecting to the server:
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect((str(ip),5000))

    #Recieve data from the server:
    data = client_socket.recv(1024)

    stream.write(data,chunk)
This uses PyAdudio, so you will need that. Check out its website, so you will understand what its doing.

Quality is effect by the RATE var. Use a value between 1100 and 44000. The chunk size will need to be increased if you increase the rate. Playing with the chunk size will effect latency.
?You can?t outrun Death forever.
But you can make the Bastard work for it.?

Major Korgo Korgar
?Last of The Lancers? - AFC 32
(Andromeda Ascendant Record Database)
Quote
Like
Share