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
(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.
|
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.