通过Autobahn WebSocket流式传输视频

时间:2014-05-06 12:20:25

标签: opencv websocket twisted autobahn

我从 OpenCV VideoCapture.read()捕获视频帧,并将帧发送到 WebSocket 服务器(扭曲 Autobahn WebSocket API),我还使用Twisted IPushProducer接口将数据流式传输到WebSocket,最终在发送回客户端时清理相机。

这是我的代码。

server.py

import cv2
import cv2.cv as cv
import numpy as np
from autobahn.twisted.websocket import  WebSocketServerProtocol, \
                                    WebSocketServerFactory, \
                                    listenWS
from VideoStreamClient import BATH_SIZE

class VideoStreamServerProtocol(WebSocketServerProtocol):
    def onConnect(self,request):
        print("Client connecting: {0}".format(request.peer))

    def onOpen(self):
        print("WebSocket connection open.")

    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {0}".format(reason))

    def onMessageBegin(self, isBinary):
        WebSocketServerProtocol.onMessageBegin(self, isBinary)

    def onMessageFrameBegin(self, length):
        WebSocketServerProtocol.onMessageFrameBegin(self, length)
        self.received = 0
        self.next = BATCH_SIZE

    def onMessageFrameData(self, payload):
        self.received += len(payload)
        if self.received >= self.next:
            self.sendMessageFrameData(payload,isBinary=True)
            self.received = 0;

    def onMessageFrameEnd(self):
        pass

    def onMessageEnd(self):
        pass

class VideoStreamServerFactory(WebSocketServerFactory):
    protocol = VideoStreamServerProtocol

    def __init__(self):
        WebSocketServerFactory.__init__(self,"ws://localhost:9000", debug = False)

if __name__ == '__main__':
   import sys
   from twisted.python import log
   from twisted.internet import reactor

   log.startLogging(sys.stdout)

   factory = VideoStreamServerFactory()
   listenWS(factory)
   reactor.run()

client.py

from autobahn.twisted.websocket import WebSocketClientFactory, \
                                   WebSocketClientProtocol, \
                                   connectWS

from zope.interface import implementer
from twisted.internet import reactor, interfaces

import cv2
import numpy as np

FRAME_SIZE = 0x7FFFFFFFFFFFFFFF
BATCH_SIZE = 1 * 2**20

@implementer(interfaces.IPushProducer)
class VideoStreamProducer:
    def __init__(self,proto):
        self.proto = proto
        self.started = False
        self.paused = False

    def pauseProducing(self):
        self.paused = True

    def resumeProducing(self):
        self.paused = False
        if not self.started:
            self.cap = cv2.VideoCapture(0)
            self.cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 640)
            self.cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 480)

            self.proto.beginMessage(isBinary=True)
            self.proto.beginMessageFrame(FRAME_SIZE)
            self.started = True
        while not self.paused:
            isSuccess, frame = self.cap.read()
            _, data = cv2.imencode(".jpg",frame,encode_param)
            if isSuccess:
                if self.proto.sendMessageFrameData(data)<=0:
                    self.proto.beginMessageFrame(FRAME_SIZE)

    def stopProducing(self):
        self.cap.release()

class VideoStreamClientProtocol(WebSocketClientProtocol):
    def onConnect(self,response):
        pass

    def onOpen(self):
        producer = VideoStreamProducer(self)
        self.registerProducer(producer, True)
        producer.resumeProducing()

    def onMessage(self, payload, isBinary):
        print(len(payload))

if __name__ == '__main__':
    factory = WebSocketClientFactory("ws://localhost:9000")
    factory.protocol = VideoStreamClientProtocol
    connectWS(factory)
    reactor.run()

1 个答案:

答案 0 :(得分:2)

这是一个无限循环,可以防止任何事件处理开始后发生:

while not self.paused:
    isSuccess, frame = self.cap.read()
    _, data = cv2.imencode(".jpg",frame,encode_param)
    if isSuccess:
        if self.proto.sendMessageFrameData(data)<=0:
            self.proto.beginMessageFrame(FRAME_SIZE)

请记住,Twisted使用单线程协作式多任务处理方法来实现并发。这个循环束缚了(单个)反应器线程,并且不与其他任务配合。

如果您想重复运行某些代码,请查看twisted.internet.task.LoopingCalltwisted.internet.task.cooperate

相关问题