我需要将网络摄像头图像传递给本地主机,以便在浏览器中查看网络摄像头。同时,我需要使用网络摄像头来提供YouTube流。我的语言是python3。
当我从网络摄像头cv2.capture('/dev/video0')
捕获时,网络摄像头已锁定,因此直到释放它我才能第二次接触它。我不想每秒释放并重新捕获它60次。
我将以下代码用于http服务器:
server = ThreadedHTTPServer(('localhost', port), CamHandler)
在这里,CamHandler是一个类,其功能do_GET(self)
每秒从网络摄像头中获取60次静止图像,并一起发送正确的标头。
因此,它会在浏览器中显示,并在流到youtube的流中(通过ffmpeg)起作用,但不能同时出现。
我该怎么办?如果您的答案是“使用插座”,请在上面详细说明。
更新
这是完整的代码:
#!/usr/bin/env python3
import sys
sys.path.append("cv2")
import cv2
from PIL import Image
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
from socketserver import ThreadingMixIn
from io import BytesIO
import time
capture=None
class CamHandler(BaseHTTPRequestHandler):
def do_GET(self):
global capture
if self.path.endswith('stream.mjpeg'):
self.send_response(200)
self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
self.end_headers()
camId = "http://localhost:8091/camera.mjpeg"
font = cv2.FONT_HERSHEY_SIMPLEX
fontsize = .8
while True:
try:
with open("currentCamera.txt","r") as f:
newCamId = f.read().splitlines()
if newCamId != camId:
capture.release();
capture = cv2.VideoCapture(''.join(newCamId))
print ("camera changed from ", camId, " to ", newCamId)
camId = newCamId
rc,img = capture.read()
if not rc:
continue
with open("subtitle.txt","r") as f:
subtitle = f.read().splitlines()
subtitle = ''.join(subtitle).strip()
if len(subtitle) > 2:
textsize = cv2.getTextSize(subtitle, font, fontsize, 2)[0]
textX = (img.shape[1] - textsize[0]) // 2
textY = img.shape[0] - textsize[1] - 30
cv2.rectangle(img,(textX-10,textY-20),(textX+textsize[0]+10,textY+textsize[1]),(255,255,255),-1)
cv2.putText(img,subtitle,(textX,textY+8),font,fontsize,(0,0,0),2)
imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
jpg = Image.fromarray(imgRGB)
tmpFile = BytesIO()
jpg.save(tmpFile,'JPEG')
self.wfile.write(b"--jpgboundary")
self.send_header('Content-type','image/jpeg')
self.send_header('Content-length',str(tmpFile.getbuffer().nbytes))
self.end_headers()
jpg.save(self.wfile,'JPEG')
time.sleep(1/60)
except KeyboardInterrupt:
break
return
if self.path.endswith('camera.mjpeg'):
self.send_response(200)
self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
self.end_headers()
camId = "/dev/video0"
font = cv2.FONT_HERSHEY_SIMPLEX
fontsize = .8
while True:
try:
rc,img = capture.read()
if not rc:
continue
imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
jpg = Image.fromarray(imgRGB)
tmpFile = BytesIO()
jpg.save(tmpFile,'JPEG')
self.wfile.write(b"--jpgboundary")
self.send_header('Content-type','image/jpeg')
self.send_header('Content-length',str(tmpFile.getbuffer().nbytes))
self.end_headers()
jpg.save(self.wfile,'JPEG')
time.sleep(1/60)
except KeyboardInterrupt:
break
return
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""Handle requests in a separate thread."""
def main():
global capture
capture = cv2.VideoCapture("/dev/video0")
capture.set(3,1920)
capture.set(4,1080)
global img
try:
server = ThreadedHTTPServer(('localhost', 8091), CamHandler)
print ("server started on port 8091")
server.serve_forever()
except KeyboardInterrupt:
capture.release()
server.socket.close()
if __name__ == '__main__':
main()
我无法在浏览器中同时显示http://localhost:8091/stream.mjpeg和http://localhost:8091/camera.mjpeg。此外,当我尝试使用http://localhost:8091/stream.mjpeg作为ffmpeg的输入时,python脚本崩溃了。
更新2 错误是:
[mpjpeg @ 0xaa4148c0] Expected boundary '--' not found, instead found a line of # bytes
Segmentation fault