разрешить нескольким клиентам прослушивать ThreadedHTTPServer python 3 - PullRequest
0 голосов
/ 14 января 2019

Мне нужно передать изображения с веб-камеры на локальный хост, чтобы просматривать веб-камеру в браузере. В то же время мне нужно использовать веб-камеру для подачи потока 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...