| The Following 4 Users Say Thank You to Spastic For This Useful Post: | ||
|
|
2008-09-08
, 07:02
|
|
Posts: 2,102 |
Thanked: 1,309 times |
Joined on Sep 2006
|
#2
|
I can actually hear what the cam is recording, but there is popping over it about every half second or so. I'm not sure if there is some extra data in the stream that needs to be ignored or what. It's too bad because it's so close. The audio does seem to be behind a few seconds, but that's not a big deal with a baby monitor.
|
|
2008-09-14
, 23:45
|
|
Posts: 3 |
Thanked: 4 times |
Joined on Dec 2007
|
#3
|
import urllib2
import subprocess
ServerAddr = '192.168.1.100'
UserName = 'admin'
Password = 'admin'
AudioUrl = 'http://' + ServerAddr + '/cgi/audio/audio.cgi'
VideoUrl = 'http://' + ServerAddr + '/cgi/mjpg/mjpeg.cgi'
VideoCmd = 'mplayer -demuxer lavf -'
AudioCmd = 'mplayer -rawaudio channels=1:rate=8000:bitrate=128 -demuxer rawaudio -'
# Passing the username and password with the URL doesn't seem to work
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, ServerName, UserName, Password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(authhandler)
urllib2.install_opener(opener)
def playStream(url, cmdLine, strip=0):
print 'Opening ' + url
stream = urllib2.urlopen(url)
goodData = True
p = subprocess.Popen(cmdLine, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while goodData:
boundaryStr = stream.readline()
if boundaryStr != '--myboundary\r\n':
print 'Bad boundary: ' + boundaryStr
break
lengthStr = stream.readline()
if not lengthStr.startswith('Content-Length: '):
print 'Bad length: ' + lengthStr
break
length = int(lengthStr.strip().split()[1])
emptyStr = stream.readline()
print 'Good frame, length %d' % length
rawData = stream.read(length)
if len(rawData) == length:
try:
p.stdin.write(rawData[strip:])
except IOError:
break
else:
print 'Bad read length: %d' % len(rawData)
break
p.stdin.close()
print p.stdout.read()
p.stdout.close()
p.wait()
videoCmd = 'mplayer -demuxer lavf http://%s:%s@%s/cgi/mjpg/mjpeg.cgi?foo.mjpg' % (UserName, Password, ServerAddr)
p = subprocess.Popen(videoCmd, shell=True)
#playStream(VideoUrl, VideoCmd)
playStream(AudioUrl, AudioCmd, 24)
|
|
2008-09-15
, 00:45
|
|
Posts: 51 |
Thanked: 0 times |
Joined on Apr 2008
@ Ontario, Canada
|
#4
|
It will be very cool to just prop the N800 on my nightstand when I go to bed and be able to watch the baby
Actually, the audio is rather important, and you'll need to be able to turn it up. Just to check and make sure they are still breathing. They can lie so still sometimes, it's scary. But they're so adorable when they're sleeping! 
(when it gets here in a few weeks).
Even if I don't get the audio working I'm guessing I'll be able to hear the baby screaming without it.
(Not to mention prompting the neighbours to either turn you into the police for abuse or threaten to sue for keeping them awake too.)|
|
2009-01-16
, 03:31
|
|
Posts: 16 |
Thanked: 1 time |
Joined on Apr 2008
|
#5
|
|
|
2009-01-16
, 19:35
|
|
Posts: 16 |
Thanked: 1 time |
Joined on Apr 2008
|
#6
|
|
|
2009-01-16
, 23:27
|
|
Posts: 1,096 |
Thanked: 760 times |
Joined on Dec 2008
|
#7
|
|
|
2009-01-18
, 01:02
|
|
Posts: 3 |
Thanked: 4 times |
Joined on Dec 2007
|
#8
|
import urllib2
import socket
import pygame
from pygame.locals import *
import cStringIO
import sys
import wave
import struct
ServerAddr = '192.168.1.13'
UserName = 'admin'
Password = 'admin'
AudioUrl = 'http://' + ServerAddr + '/cgi/audio/audio.cgi'
VideoUrl = 'http://' + ServerAddr + '/cgi/mjpg/mjpeg.cgi'
# Passing the username and password with the URL doesn't seem to work, so setup a password manager
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, ServerAddr, UserName, Password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(authhandler)
urllib2.install_opener(opener)
class ScreenHelper:
screen = None
fullScreen = True
windowedRes = (640, 480)
fullScreenRes = windowedRes
curScreenRes = windowedRes
def __init__(self):
pygame.display.set_caption('CamViewer')
# If the current screen res is a fullscreen mode, set our fullscreen res to that
info = pygame.display.Info()
if (info.current_w, info.current_h) in pygame.display.list_modes():
self.fullScreenRes = (info.current_w, info.current_h)
self.toggleFullscreen()
def toggleFullscreen(self):
if self.fullScreen:
self.screen = pygame.display.set_mode(self.windowedRes)
self.curScreenRes = self.windowedRes
self.fullScreen = False
else:
self.screen = pygame.display.set_mode(self.fullScreenRes, pygame.FULLSCREEN)
self.curScreenRes = self.fullScreenRes
self.fullScreen = True
def blit(self, surface):
offset = (0, 0)
# If the surface doesn't match our res, scale it, maintaining aspect ratio
if surface.get_size() != self.curScreenRes:
widthRatio = float(self.curScreenRes[0]) / float(surface.get_width())
heightRatio = float(self.curScreenRes[1]) / float(surface.get_height())
scaledSize = None
if widthRatio > heightRatio:
scaledSize = (int(surface.get_width() * heightRatio), int(surface.get_height() * heightRatio))
offset = ((self.curScreenRes[0] - scaledSize[0]) / 2, 0)
else:
scaledSize = (int(surface.get_width() * widthRatio), int(surface.get_height() * widthRatio))
offset = (0, (self.curScreenRes[1] - scaledSize[1]) / 2)
surface = pygame.transform.smoothscale(surface, scaledSize)
# Blit the surface and update the display
self.screen.blit(surface, offset)
pygame.display.update()
# Reads a chunk of data from an Airlink camera http stream
class CamDataChunk:
frame = 0
size = 0
tag1 = 0
time = 0
unknown1 = 0
tag2 = 0
unknown2 = 0
data = ''
def read(self, stream):
try:
boundaryStr = stream.readline().decode()
if boundaryStr != '--myboundary\r\n':
print('Bad boundary: ' + boundaryStr)
return False
lengthStr = stream.readline().decode()
if not lengthStr.startswith('Content-Length: '):
print('Bad length: ' + lengthStr)
return False
length = int(lengthStr.strip().split()[1])
emptyStr = stream.readline()
#print('Good frame, length %d' % length)
dataLeft = length
chunkData = ''
while dataLeft > 0:
data = stream.read(dataLeft)
amtRead = len(data)
dataLeft -= amtRead
if amtRead == 0:
print('Ran out of data')
return False
chunkData += data
headerSize = 28
# Header format:
# int ~synched, +1 per frame
# int data size? varies jpg, constant audio
# int J000 for JPG, A000 for wav
# int ~synched, +1 per sec?
# int ???
# int constant (0x00990201 video, 0x12d20700 audio)
# int constant (0 both)
chunkHeader = struct.unpack('iiiiiii', chunkData[:headerSize])
self.frame = chunkHeader[0]
self.size = chunkHeader[1]
self.tag1 = chunkHeader[2]
self.time = chunkHeader[3]
self.unknown1 = chunkHeader[4]
self.tag2 = chunkHeader[5]
self.unknown2 = chunkHeader[6]
self.data = chunkData[headerSize:]
return True
except socket.error, (errno, strerror):
print "Socket error(%s): %s" % (errno, strerror)
return False
def play(screen):
videoStream = urllib2.urlopen(VideoUrl)
#audioStream = urllib2.urlopen(AudioUrl)
videoChunk = CamDataChunk()
#audioChunk = CamDataChunk()
while True:
for event in pygame.event.get():
if event.type == QUIT:
return
if event.type == pygame.KEYDOWN:
if event.key == K_f:
screen.toggleFullscreen()
elif event.key == K_ESCAPE:
return
if videoChunk.read(videoStream) == False:
print 'Bad video chunk'
return
#if audioChunk.read(audioStream) == False:
# print 'Bad audio chunk'
# return
# Display the current frame
frameSurface = pygame.image.load(cStringIO.StringIO(videoChunk.data)).convert()
screen.blit(frameSurface)
# Play the current audio sample
#soundObj = pygame.mixer.Sound(waveFile.getvalue())
#soundObj.play()
pygame.init()
screen = ScreenHelper()
play(screen)
pygame.display.quit()
The camera is a SkyIPCam500 by Airlink. It has sound and nightvision, and I've got it set up as a baby cam. You access it through a webpage, and there's a Java or ActiveX viewer. Unfortunately, I can't use either of those on the N800. Even if I installed Debian for Java, the sound only works with the ActiveX control. I did some sniffing with Wireshark and found the URL's that ActiveX is calling. One is for a MJPEG stream. I can plug that into MicroB, but it only displays the first frame. However, I did get it working with mplayer, here is the command line I used:
I'm still having some issues with the audio though. The stream is raw PCM data, so I had some trouble figuring out the details. Thankfully, the ActiveX control has an option to record to an AVI file, and using that I figured out it was 8000Hz mono at 128K bitrate. This command line decodes that:
Anyway, just wanted to share what I've got and see if anyone has any suggestions. It will be very cool to just prop the N800 on my nightstand when I go to bed and be able to watch the baby (when it gets here in a few weeks). Even if I don't get the audio working I'm guessing I'll be able to hear the baby screaming without it.