def label_image(stream_id, image_bytes, delivery_function, settings=None):
    if not settings:
        settings = {}

    # Get region in order from settings, environment, default to us-east-1
    region_name = settings.setdefault('rekognition_region_name', os.environ.get('AWS_DEFAULT_REGION', 'us-east-1'))
    client = boto3.client('rekognition', region_name=region_name)
    faces = client.detect_faces(
        Image={
            'Bytes': image_bytes
        },
        Attributes=["ALL"]
    )

    labels = client.detect_labels(
        Image={
            'Bytes': image_bytes
        }
    )

    result = process_labeling_result(stream_id, {
        "faces": faces['FaceDetails'],
        "labels": labels['Labels']
    }, int(time.time()), settings)

    logger.debug("Found {0} faces and {1} labels in image data".format(
        len(faces['FaceDetails']), len(labels['Labels'])))

    if result:
        logger.debug("Sending JSON API formatted document regarding ML event")
        delivery_function.remote(result)
Exemplo n.º 2
0
    def extract_frames_from_hls(self,
                                stream_id,
                                hls_url,
                                label_function,
                                delivery_function,
                                settings=None):
        if not settings:
            settings = {}

        label_delay = settings.setdefault('label_delay', 5)
        last_frame_time = 0

        capture = cv2.VideoCapture(hls_url)
        try:
            while True:
                success, frame = capture.read()
                if not success:
                    break

                if int(time.time()) > last_frame_time + label_delay:
                    did_encode, numpy_image = cv2.imencode('.png', frame)
                    logger.debug(
                        "Sending image to labeler.  Size: {:.2f} MB".format(
                            len(numpy_image.tobytes()) / 1024))
                    label_function.remote(stream_id, numpy_image.tobytes(),
                                          delivery_function, settings)
                    last_frame_time = int(time.time())
        finally:
            logger.info(
                "Informing HLS manager that stream {0} is finished.".format(
                    stream_id))
            set_completed_stream(stream_id)
Exemplo n.º 3
0
def deliver_etl(result):
    queue_name = 'ml_events'

    with rabbitpy.Connection() as conn:
        logger.debug("Connected to RabbitMQ")
        with conn.channel() as channel:
            channel.enable_publisher_confirms()
            queue = rabbitpy.Queue(channel, queue_name)
            queue.durable = True
            queue.declare()

            message = rabbitpy.Message(channel, json.dumps(result))
            logger.info("ML Event message pushed to RabbitMQ")
            if not message.publish('', queue_name, mandatory=True):
                logger.error("Message failed to publish data for stream id: {0}")
Exemplo n.º 4
0
    def processing_complete(self, stream_id):
        """Removes a stream ID from the pending/processing pipeline.

        Should be called after a frame_extractor has finished with an HLS endpoint so that if this ID needs to be
        processed later get_hls_endpoints can find it again.
        """
        try:
            del (self.pending_endpoints[stream_id])
        except KeyError:
            logger.debug(
                "Stream {0} wasn't found in processing endpoints.".format(
                    stream_id))

        try:
            self.processing_endpoints.remove(stream_id)
        except KeyError:
            logger.debug(
                "Stream {0} wasn't found in processing endpoints.".format(
                    stream_id))
        logger.info("Stream {0} has been marked complete".format(stream_id))
Exemplo n.º 5
0
    def start(self, endpoint_finder_function, label_function,
              delivery_function):
        while True:
            for stream in get_completed_streams():
                logger.info("Marking stream {0} as complete".format(stream))
                self.processing_complete(stream)

            self.get_hls_urls(endpoint_finder_function)
            processing_endpoints = []
            logger.debug("There are {0} endpoints pending.".format(
                len(self.pending_endpoints)))
            for stream_id, stream_url in self.pending_endpoints.items():
                try:
                    self.frame_extractor.extract_frames_from_hls.remote(
                        stream_id, stream_url, label_function,
                        delivery_function)
                    processing_endpoints.append(stream_id)
                except Exception as e:
                    logger.error(e)
                    pass
            for id in processing_endpoints:
                self.processing_started(id)
            time.sleep(5)
Exemplo n.º 6
0
def get_hls_streaming_session_urls(pending_streams,
                                   processing_streams,
                                   settings=None):
    """Returns list of HLS endpoints from a list of Kinesis Video Streams.

    Needs AWS_DEFAULT_REGION somewhere in the environment. Will only return HLS url's for video streams that
    have fragments available when this function is called (i.e. the stream must be created AND currently
    have video being streamed to it before AWS will cough up the URL for it).
    """

    if not settings:
        settings = {}

    region_name = settings.setdefault(
        'kvs_region_name', os.environ.get('AWS_DEFAULT_REGION', 'us-east-1'))

    # A little weird with the two clients created in this method, kinesisvideo gets the data endpoint
    # needed by kinesis-video-archived-media later in the function to actually get the HLS url.
    video_client = boto3.client('kinesisvideo', region_name=region_name)
    logger.debug("Started boto3 KVS client in {0}".format(region_name))
    streams = video_client.list_streams()

    # Discard streams that aren't ready to be checked or have been marked for deletion.
    active_steams = [
        stream for stream in streams['StreamInfoList']
        if stream['Status'] == 'ACTIVE'
    ]

    endpoints = []
    for stream in active_steams:
        if stream['StreamName'] in pending_streams or stream[
                'StreamName'] in processing_streams:
            continue
        try:
            # Get the data endpoint for this stream ID, need this later to get the HLS endpoint.
            endpoint = video_client.get_data_endpoint(
                APIName="GET_HLS_STREAMING_SESSION_URL",
                StreamName=stream['StreamName'])['DataEndpoint']
        except Exception as e:
            logger.error("Failed to get data endpoint: {0}\n{1}".format(
                stream['StreamName'], e))
            continue

        # Build a client using the data endpoint retrieved by kinesisvideo
        streaming_client = boto3.client("kinesis-video-archived-media",
                                        endpoint_url=endpoint,
                                        region_name=region_name)
        try:
            # Get the HLS endpoint URL and append it to our endpoints list.
            endpoints.append({
                "stream_id":
                stream['StreamName'],
                "url":
                streaming_client.get_hls_streaming_session_url(
                    StreamName=stream['StreamName'],
                    PlaybackMode="LIVE",
                    Expires=3600)['HLSStreamingSessionURL']
            })
        except streaming_client.exceptions.ResourceNotFoundException:
            continue

    logger.debug("Found {0} endpoints with streaming data.".format(
        len(endpoints)))
    return endpoints