Мне нужно передать изображения с веб-камеры на локальный хост, чтобы просматривать веб-камеру в браузере. В то же время мне нужно использовать веб-камеру для подачи потока YouTube. У меня есть Python3 в качестве моего языка.
Когда я снимаю с веб-камеры cv2.capture('/dev/video0')
, веб-камера заблокирована, поэтому я не могу связаться с ней во второй раз, пока не отпущу ее. Я предпочитаю не выпускать и захватывать его 60 раз в секунду.
Я использую следующий код для http-сервера:
server = ThreadedHTTPServer(('localhost', port), CamHandler)
здесь CamHandler - это класс с функцией do_GET(self)
, получающий 60 раз в секунду стоп-кадр с веб-камеры и отправляющий правильные заголовки.
Таким образом, в браузере он отображается, а в потоке на YouTube (через ffmpeg) он работает, но не в обоих случаях одновременно.
Что я могу с этим сделать? Если ваш ответ «использовать сокеты», пожалуйста, уточните это.
UPDATE
Вот полный код:
#!/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