-   Programming (
-   -   Accessing v4l devices from PHP (

Napalm Llama 02-03-2006 05:37 PM

Accessing v4l devices from PHP
How's it done?

I've written a simple javascript webcam application, which uses a very basic PHP backend for framegrabbing. My script looks like this:

PHP Code:

$tempfile "webcam-frametemp.jpeg";
$cmd "streamer -c /dev/video0 -b 24 -o $tempfile";
$shell_out shell_exec($cmd);
$frame imagecreatefromjpeg$tempfile );
header('Content-type: image/jpeg');

But for some reason this doesn't work - the shell command fails and I get absolutely *no* information thrown back at me as to what I did wrong. I've tried using absolute file paths, and I've made sure that the apache user has access rights to /dev/v4l/video0. The command works as my normal user, and I even temporarily modified /etc/passwd just enough for me to su to apache, and the command works from the shell there, too.

My httpd.conf file says this:

User apache
Group apache

So I know I've added the permissions to the proper user.

I can't think of anything else, and so I turn to you wonderfully knowledgable people - what can I do?

graemef 02-04-2006 08:49 AM

What are you safe-mode settings in you php.ini file?

shell_exec() is disabled in safe mode

Does the streamer command have any switch to display more output, like connection errors etc?

Napalm Llama 02-04-2006 09:46 AM

Thanks for your reply.

I'm fairly sure I'm not running in safe mode - another project of mine uses shell_exec() it and it works fine.

And sure enough, php.ini says this:

; Safe Mode
safe_mode = Off

This is the normal (Bash shell) output of the command:

apache@splig ~ $ streamer -c /dev/video0 -b 24 -o webcam-frametemp.jpeg
files / video: JPEG (JFIF) / audio: none

So when run normally, it saves the JPEG and I do get a message. It's just that for some reason when PHP runs it, it doesn't and I don't...

graemef 02-04-2006 10:50 AM

What do you get when you echo $shell_out?
Does the webcam-frametemp.jpeg file exist
a) before
b) after
What happens when you run the command as user apache?

tonyfreeman 02-04-2006 11:32 AM

Absolute Path Needed ... Possibly
Using su to test things still doesn't work exactly as you would expect. Sometimes your environment get's passed to your su ... if you don't call su correctly. I suggest that it may still be a permission problem. The web server needs to create the image in a directory that it has write access to.

So ... as a test:


$tempfile = "/tmp/webcam-frametemp.jpeg";
The web server can almost always write to the temp directory. If it works, then you'll need to change the permission of the directory that you really want it to sit in and call it with a full path. Example:


chown apache:apache /var/www/html/webcam
chmod 775 /var/www/html/webcam

$tempfile = "/var/www/html/webcam/webcam-frametemp.jpeg";

-- Tony

Napalm Llama 02-05-2006 08:07 AM

OK, I get absolutely *nothing* when I echo $shell_out - I added the following line underneath the shell_exec() call:
PHP Code:

echo "<pre>start:$shell_out:end</pre>"

And it resulted in this:

If I edit /etc/passwd so I can "su - apache" then running the command works fine, I get the output detailed in my pevious post, and the file appears/changes. When I run the PHP script, I don't get any output and no file operation occurs.

I've already tried full paths - that is /usr/bin/streamer and /srv/www/htdocs/webcam-frametemp.jpeg. The destination file is definately owned by apache:apache, and chmodded to 664 (it doesn't need to be executable) - and I just changed /srv/www/htdocs to 775 (from 755) but it didn't make any difference.

The only thing that I can think of is if PHP isn't actually running the command for some reason - and then refusing to tell me why :(

I can post my php.ini if you think that'd be useful...

tonyfreeman 02-05-2006 09:56 AM

Use system command
OK ... it doesn't appear that you are using the information in $shell_out ... so how about trying the system() php call. To keep the system call from printing stuff to the screen you'll have to change the command to redirect stdout to /dev/null as well as stderr.


$cmd = "streamer -c /dev/video0 -b 24 -o $tempfile 2>/dev/null";
$shell_out = system($cmd, $retval);

if ($retval) {
    print "Successful system call!";
} else {
    print "Unsuccessful system call ... crap!";

-- Tony

Napalm Llama 02-05-2006 10:18 AM

OK, I've stuck that in like this:
PHP Code:

$tempfile "/srv/www/htdocs/webcam-frametemp.jpeg";
$cmd "streamer -c /dev/video0 -b 24 -o $tempfile 2>/dev/null";
$shell_out system($cmd$retval);

if (
$retval) {
"Successful system call!";
} else {
"Unsuccessful system call ... crap!";

$tempfile isn't modified, but I get this:

Successful system call!
streamer -c /dev/video0 -b 24 -o /srv/www/htdocs/webcam-frametemp.jpeg 2>/dev/null


If I remove the 2>/dev/null part, the exit code (I'm guessing that's what it is) becomes an 11... and we all know what that means :mad:

tonyfreeman 02-05-2006 03:55 PM

Closer Still
OK ... I think we're getting close.

How about providing the full path to 'streamer' in the command:


$cmd = "/usr/local/bin/streamer -c /dev/video0 -b 24 -o $tempfile
-- Tony

Napalm Llama 02-05-2006 04:49 PM

No such luck:

Successful system call!
/usr/bin/streamer -c /dev/video0 -b 24 -o /srv/www/htdocs/webcam-frametemp.jpeg 2>/dev/null


(no typo - streamer is definately at /usr/bin on my system)

graemef 02-05-2006 05:38 PM

What do you get when you try different commands?

Such as:
streamer --version
streamer --help

I know it's not going to solve the problem but it may shake something else up.

Napalm Llama 02-06-2006 09:51 AM

OK, the 2 streamer commands you said still don't work, but I got these:


/srv/www/htdocs Unsuccessful system call ... crap!



eth0 Link encap:Ethernet HWaddr 00:04:61:78:0F:82 inet addr: Bcast: Mask: inet6 addr: fe80::204:61ff:fe78:f82/64 Scope:Link UP BROADCAST NOTRAILERS RUNNING MULTICAST MTU:1500 Metric:1 RX packets:1127354 errors:0 dropped:0 overruns:0 frame:0 TX packets:1145762 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:667975229 (637.0 Mb) TX bytes:224896918 (214.4 Mb) Interrupt:5 Base address:0x6000 lo Link encap:Local Loopback inet addr: Mask: inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:36691 errors:0 dropped:0 overruns:0 frame:0 TX packets:36691 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:2787249 (2.6 Mb) TX bytes:2787249 (2.6 Mb) Unsuccessful system call ... crap!


Looks like there's something that PHP/Apache doesn't like about streamer...

graemef 02-06-2006 10:05 AM

I have never used it but you may want to look at the passthru() function, it may help.

Napalm Llama 02-06-2006 01:28 PM

Well I tried substituting passthru() instead of system(), but it didn't seem to make any difference - unless I've done it wrong and it needs different syntax? I had a look at the PHP function list and it seemed the same.

All times are GMT -5. The time now is 12:39 PM.