Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Windows Webcam access.

by Steve_BZ (Chaplain)
on Aug 30, 2009 at 13:19 UTC ( #792178=perlquestion: print w/replies, xml ) Need Help??

Steve_BZ has asked for the wisdom of the Perl Monks concerning the following question:

Hi Guys,

I've been trying to access my windows webcam for a little while now, the only way I have been able to do it is by using a standard package to boadcast it on 'localhost' like Broadcam or something. The issue with this is it's very heavy on the CPU and degrades the picture at the same time. Really what I'd like is a bit of Perl code that access the webcam directly, does anyone have something like this?


Update: What about EZTWAIN? There seems to be a perl module Win32::Scanner::EZTWAIN, but I've not been able to get a clean install.

It depends on Win32::API (note clean install)

C:\Perl>perl -MCPAN -e "install Win32::API" Set up gcc environment - 3.4.5 (mingw special) CPAN: Storable loaded ok (v2.16) Going to read C:\Perl\cpan\Metadata Database was generated on Sun, 30 Aug 2009 06:27:00 GMT Win32::API is up to date (0.59).

But the Win32::Scanner::EZTWAIN gives me:

C:\Perl>perl -MCPAN -e "install Win32::Scanner::EZTWAIN" Set up gcc environment - 3.4.5 (mingw special) CPAN: Storable loaded ok (v2.16) Going to read C:\Perl\cpan\Metadata Database was generated on Sun, 30 Aug 2009 06:27:00 GMT Running install for module 'Win32::Scanner::EZTWAIN' Running make for L/LE/LENNERTO/Win32-Scanner-EZTWAIN-0.01.tar.gz CPAN: Digest::SHA loaded ok (v5.47) CPAN: Compress::Zlib loaded ok (v2.015) Checksum for C:\Perl\cpan\sources\authors\id\L\LE\LENNERTO\Win32-Scann +er-EZTWAIN -0.01.tar.gz ok CPAN: Archive::Tar loaded ok (v1.42) Win32-Scanner-EZTWAIN-0.01/ Win32-Scanner-EZTWAIN-0.01/ Win32-Scanner-EZTWAIN-0.01/README Win32-Scanner-EZTWAIN-0.01/Makefile.PL Win32-Scanner-EZTWAIN-0.01/Changes Win32-Scanner-EZTWAIN-0.01/MANIFEST Win32-Scanner-EZTWAIN-0.01/ CPAN: File::Temp loaded ok (v0.21) Going to build L/LE/LENNERTO/Win32-Scanner-EZTWAIN-0.01.tar +.gz Set up gcc environment - 3.4.5 (mingw special) Checking if your kit is complete... Looks good Writing Makefile for Win32::Scanner::EZTWAIN Microsoft (R) Program Maintenance Utility Version 1.50 Copyright (c) Microsoft Corp 1988-94. All rights reserved. cp blib\lib\Win32\Scanner\ LENNERTO/Win32-Scanner-EZTWAIN-0.01.tar.gz nmake -- OK Warning (usually harmless): 'YAML' not installed, will not store persi +stent stat e Running make test Microsoft (R) Program Maintenance Utility Version 1.50 Copyright (c) Microsoft Corp 1988-94. All rights reserved. C:\Perl\bin\perl.exe "-Iblib\lib" "-Iblib\arch" 1..1 # Running under perl version 5.008008 for MSWin32 # Win32::BuildNumber 822 # Current time local: Mon Aug 31 15:10:31 2009 # Current time GMT: Mon Aug 31 18:10:31 2009 # Using version 1.25 Can't load 'C:/Perl/site/lib/auto/Win32/API/API.dll' for module Win32: +:API: load _file:Invalid access to memory location at C:/Perl/lib/ l +ine 229. at blib\lib/Win32/Scanner/ line 17 Compilation failed in require at blib\lib/Win32/Scanner/ lin +e 17. BEGIN failed--compilation aborted at blib\lib/Win32/Scanner/ + line 17. Compilation failed in require at line 10. BEGIN failed--compilation aborted at line 10. NMAKE : fatal error U1077: 'C:\WINDOWS\system32\cmd.exe' : return code + '0x2' Stop. LENNERTO/Win32-Scanner-EZTWAIN-0.01.tar.gz nmake test -- NOT OK Warning (usually harmless): 'YAML' not installed, will not store persi +stent stat e Running make install make test had returned bad status, won't install without force

Replies are listed 'Best First'.
Re: Windows Webcam access.
by Corion (Pope) on Aug 30, 2009 at 16:21 UTC

    In a (soon to be released version of) App::VideoMixer, I use ffmpeg.exe to capture the video and output as a raw bytestream to stdout. The essential command line is:

    my $pixel_format = 'rgb24'; my $file = 0; # device number 0, or .avi file, for reproducible te +sting my ($pid,$stream) = $self->spawn(sprintf qq{%s -f vfwcap -r 30 -i +%s -f rawvideo -pix_fmt %s - |}, $self->ffmpeg, $file, $pixel_format );

    It works like a charm with ffmpeg v0.5 and saves me the hassle of downloading and compiling a lot of hard to compile libraries and their prerequisites.

      In order to get the slider functions working I am planning to use something like:

      ffmpeg -f vfwcap -r 25 -i 0  -f image2 temp_photos\foo_-%03d.jpeg

      In order to give me a directory of "frames" without any exclusive lock. This works, although I'm not sure what the highest number is, or what it'll do to my disc fragmentation!

      Then I can just do a while loop through them, and they'll look like a video. On exit, I'll do the opposite and recombine them into a video.

      However, it's not the most elegant, if I could do it nearer to your method I would, however I do need to write something to a file, because wxMediaCtrl needs a filename or URL


        I'm not sure where a slider control can come in helpful, because for me, time is still linear. I'd be very interested if you could show me how to control/adjust the flow of time through a slider, especially if it works in both directions :).

        But if you want to farm out start/stop/rewind of a movie to another control (which is sensible), my approach of reading single frames won't work out unless the control has a way for you to feed it single frames. Maybe you can hand the control a filehandle instead of an URL or a filename, but (pipe) filehandles have the disadvantage of not being seekable...

      Hi Corion,

      I've had a look a VideoMixer, thanks for this. I'm using wxMediaCtrl to output. I've tried streaming FFMPEG to a file (which works) and then opening with wxMediaCtrl, (which doesn't, because the file is opened with an exclusive lock by FFMPEG). I need wxMediaCtrl to be able to work a bit like Youtube with a sliderbar to rewind and play parts of the video, I also want to take snaps and clips and stuff. This is all working if I play an .avi file. However, I've only made it work for a live source with a streaming Server like BraodCam, which degrades the quality as it assumes inet delivery.

      Your plan uses standard output and FFMPEG, which seems like a good idea. I think I can make it work with FFMPEG, but what command do you use to stop it?

      I've looked through VideoMixer, but I can't see where you stop the streaming process. I'm not familiar with GL, so maybe I just missed it.

      Thanks for your help.


        I simply kill the process upon exit. That's not the most grateful thing but it works:

        package App::VideoMixer::External::FFmpeg; use strict; use vars qw($VERSION); $VERSION = '0.02'; use parent 'Class::Accessor'; __PACKAGE__->mk_accessors(qw(width height depth pid stream texture_id +file pixel_format ffmpeg)); sub spawn { my ($self,$cmd) = @_; my $pid = open my $stream, $cmd or die "Couldn't spawn '$cmd': $!/$?"; binmode $stream; return ($pid,$stream) }; sub DESTROY { if (my $pid = $_[0]->pid) { kill 9, $pid }; };

        This will kill the external process once the object gets destroyed. You can read the data from $stream and you have to set $self->pid to the returned $pid (and looking at this code, I'm not sure why ->spawn does it that way instead of setting $pid instead - I guess it's because I turned a subroutine into an object later).

        As a side note, App::VideoMixer v0.02 is in a sad state, as even the distribution is incomplete, so I'll have to release a fixed version soonish.

      Hi Corion,

      It's very conventional of you you rely on time being linear: how else do you explain coincidence?

      However, I'm going to have a look at your code, maybe if I save each frame in a file AFTER it's displayed then I can use my video bar on it.

      I'll let you know


Re: Windows Webcam access.
by afoken (Canon) on Aug 30, 2009 at 15:48 UTC

    Perl isn't very good at low-level hardware access, even if it is possible. Typically, you need some C clue code packed in an XS. All current desktop operating systems prevent you from messing directly with the hardware, and they have good reasons to do so. Typically, you communicate with a OS specific and hardware specific driver that wraps the hardware access. Most of the times, the driver (or set of drivers) abstracts the differences between different hardware and give you a generic interface.

    Think about soundcards. When was the last time that you had to mess with hardware registers? Last century, I would bet. Today, you connect to a generic sound device driver and tell it to play your sound data.

    Exactly the same happens with web cams. They typically are USB devices. To access their hardware registers, you have to communicate with the USB controllers and ask them to mess with the cam's hardware registers. USB controllers have different standards and different vendors, and the OS abstract that for you. So you get a stack of hardware and drivers: Web cam - USB controller - PCI bus - PCI driver - USB driver - Web cam low level driver - video API driver.

    Unless you really want to get mad fiddling with the hardware, your best bet is the video API (e.g. V4L on Linux, VfW or some DirectX stuff on Windows).


    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://792178]
Approved by marto
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2021-10-21 15:20 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (83 votes). Check out past polls.