|Think about Loose Coupling|
Webcam Streaming to Perl/Tk with ffmpegby Kirsle (Pilgrim)
|on Sep 01, 2009 at 23:20 UTC||Need Help??|
Kirsle has asked for the
wisdom of the Perl Monks concerning the following question:
Greetings, fellow monks:
For a whole couple of days I've been thinking of ways in which I could get access to a user's webcam using Perl. Specifically my short-term goal was to be able to display a Perl/Tk window displaying a live video preview from the user's webcam.
The approach I took was to bang on ffmpeg for a while until it gives me what I want (as ffmpeg has also been ported to Win32, this might also mean my code would be reasonable portable to Windows as well). After stumbling on a few different examples of ffmpeg sorcery (such as streaming the webcam over SSH into mplayer on another system), I finally figured a way to grab images out of it from within Perl.
I eventually pieced together the following ffmpeg command which activates the user's camera and streams the output as a motion jpeg (which seems to really be just a bunch of jpegs concatenated together, each one beginning with the jpeg magic number \xFF\xD8):ffmpeg -b 100K -an -f video4linux2 -s 640x480 -r 10 -i /dev/video0 -b 100K -f image2pipe -vcodec mjpeg -
With this I was able to open it as a filehandle and read all the jpegs out of it... and once I got a script put together that would write said jpegs into individual files, I started putting together my Tk webcam viewer! The code follows:
I tacked onto the end of that ffmpeg command a pipe that ran it through Perl to substitute each JPEG magic number so that they each have "KIRSLESEP" before them. This made the task of splitting the jpegs much easier, as I'm not quite up to snuff on my regexp skills and don't recall the syntax for how to split while keeping the split delimiter as part of the output.
So, I'm submitting this to Perlmonks for your review. When I thought about starting this project I came here first to have a search around and haven't seen that anyone had done this (though I did see one node where the vidcat app was used, but vidcat is a dinosaur and doesn't run on my Fedora 11 system).
When I run this script on my Dell Mini 9 with built-in webcam, I get a Tk window that shows myself, in a live video stream. The framerate seems to be on par with every other video app I've ever used, with maybe a half-second delay or less.
However, over time the app starts to slow down, because Perl/Tk doesn't seem to be freeing up memory after each image is destroyed (I've tried manually destroying each photo object before creating the new one, but it didn't help).
Please post any comments or suggestions on this. :)
Update (Sep 2 09) I've fixed the memory leak using a delete() method that I found here. I played with it before but it was terribly slow (resulting in a 5 to 10 second lag in video), but I found out it's because it actually is working and just takes a while to delete a 640x480 pixel image. Lowering the resolution to 320x240 and the video stream is fast and snappy again, and no more memory leaks!
I've updated the code with my final proof-of-concept version.