如何使用PHP fsockopen连接Tapo C200 IP摄像头并实现网页推流
如何用PHP fsockopen实现Tapo C200摄像头网页视频流推送?
成功案例参考
我已通过Apache服务器+PHP代码,实现树莓派摄像头基于MJPEG-streamer的网页推流。树莓派摄像头的HTTP流地址为:
http://192.168.1.129:8080/?action=stream
以下PHP脚本可通过fsockopen代理该流,在网页中用<img>标签调用即可显示画面:
<?php $server = "192.168.1.129"; // 摄像头服务器地址 $port = 8080; // 摄像头服务端口 $url = "/?action=stream"; // 流路径 set_time_limit(0); $fp = fsockopen($server, $port, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br>\n"; // 错误处理 } else { $urlstring = "GET ".$url." HTTP/1.0\r\n\r\n"; fputs($fp, $urlstring); while ($str = trim(fgets($fp, 4096))) { header($str); } fpassthru($fp); fclose($fp); } ?>
问题分析
Tapo C200提供的是RTSP协议流,而上述成功代码是针对HTTP协议的MJPEG流开发的,两者协议完全不兼容,直接用HTTP GET请求RTSP端口必然失败。你的尝试代码存在以下问题:
- 错误地将完整RTSP URL作为HTTP请求路径,协议不匹配
- 端口设置错误,Tapo的RTSP默认端口是554,而非8090
解决方案:RTSP转HTTP MJPEG后代理
由于PHP原生处理RTSP协议较为复杂,最实用的方式是用ffmpeg将RTSP流转换为HTTP MJPEG流,再用类似之前的PHP代码代理该转换后的流。
步骤1:安装ffmpeg
在服务器(树莓派或PC)上安装ffmpeg,确保能通过命令行调用。
步骤2:启动RTSP转流进程
执行以下命令,将Tapo的RTSP流转换为本地HTTP MJPEG流:
ffmpeg -i rtsp://administrator:adminpw@192.168.1.181:554/stream1 -f mjpeg -q:v 1 http://localhost:8090/stream
-i:指定输入的RTSP流地址(替换为你的Tapo账号、密码和IP)-f mjpeg:输出格式为MJPEG-q:v 1:视频质量(1为最高,可根据需求调整)http://localhost:8090/stream:转换后本地HTTP流的地址
步骤3:PHP代理脚本
使用以下PHP脚本代理转换后的HTTP MJPEG流,网页中用<img src="此脚本路径">即可显示画面:
<?php $server = "localhost"; // 转流服务的本地地址 $port = 8090; // 转流服务的端口 $url = "/stream"; // 转流后的流路径 set_time_limit(0); $fp = fsockopen($server, $port, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br>\n"; } else { $urlstring = "GET ".$url." HTTP/1.0\r\n\r\n"; fputs($fp, $urlstring); // 传递响应头 while ($str = trim(fgets($fp, 4096))) { header($str); } // 输出流内容 fpassthru($fp); fclose($fp); } ?>
可选:PHP内启动ffmpeg进程
如果不想手动启动ffmpeg,可以在PHP中用proc_open启动转流进程(需确保服务器有执行权限):
<?php // 启动ffmpeg转流 $cmd = 'ffmpeg -i rtsp://administrator:adminpw@192.168.1.181:554/stream1 -f mjpeg -q:v 1 http://localhost:8090/stream'; $descriptorspec = [ 0 => ["pipe", "r"], 1 => ["pipe", "w"], 2 => ["pipe", "w"] ]; $process = proc_open($cmd, $descriptorspec, $pipes); // 等待几秒让转流服务启动 sleep(3); // 代理流的代码(同步骤3) $server = "localhost"; $port = 8090; $url = "/stream"; set_time_limit(0); $fp = fsockopen($server, $port, $errno, $errstr, 30); if (!$fp) { echo "$errstr ($errno)<br>\n"; } else { $urlstring = "GET ".$url." HTTP/1.0\r\n\r\n"; fputs($fp, $urlstring); while ($str = trim(fgets($fp, 4096))) { header($str); } fpassthru($fp); fclose($fp); } // 关闭ffmpeg进程(可选,若需要持续运行则不要关闭) proc_close($process); ?>
内容的提问来源于stack exchange,提问作者ron16103
相关产品推荐
相关产品推荐

