Ejemplo n.º 1
0
async def async_get_still_stream(
    request: web.Request,
    image_cb: Callable[[], Awaitable[bytes | None]],
    content_type: str,
    interval: float,
) -> web.StreamResponse:
    """Generate an HTTP MJPEG stream from camera images.

    This method must be run in the event loop.
    """
    response = web.StreamResponse()
    response.content_type = CONTENT_TYPE_MULTIPART.format("--frameboundary")
    await response.prepare(request)

    async def write_to_mjpeg_stream(img_bytes: bytes) -> None:
        """Write image to stream."""
        await response.write(
            bytes(
                "--frameboundary\r\n"
                "Content-Type: {}\r\n"
                "Content-Length: {}\r\n\r\n".format(content_type, len(img_bytes)),
                "utf-8",
            )
            + img_bytes
            + b"\r\n"
        )

    last_image = None

    while True:
        img_bytes = await image_cb()
        if not img_bytes:
            break

        if img_bytes != last_image:
            await write_to_mjpeg_stream(img_bytes)

            # Chrome seems to always ignore first picture,
            # print it twice.
            if last_image is None:
                await write_to_mjpeg_stream(img_bytes)
            last_image = img_bytes

        await asyncio.sleep(interval)

    return response
Ejemplo n.º 2
0
async def async_get_still_stream(request, image_cb, content_type, interval):
    """Generate an HTTP MJPEG stream from camera images.
    The original implementation in the HA core camera
    component, had some issues in displaying the images
    The view was always 1 frame behind
    so thats why it was in the original code to send twice at start.
    Normally not a problem, but in this component it is essential that the
    image that is served is also displayed
    """
    response = web.StreamResponse()
    response.content_type = CONTENT_TYPE_MULTIPART.format("--frameboundary")
    await response.prepare(request)

    async def write_to_mjpeg_stream(img_bytes):
        """Write image to stream."""
        await response.write(
            bytes(
                "--frameboundary\r\n"
                "Content-Type: {}\r\n"
                "Content-Length: {}\r\n\r\n".format(content_type, len(
                    img_bytes)),
                "utf-8",
            ) + img_bytes + b"\r\n")

    LastImage = None
    SameImagecount = 0
    while True:
        img_bytes = await image_cb()
        if not img_bytes:
            break
        # Send same image max 2 times, to fix browserproblem
        if img_bytes == LastImage:
            SameImagecount += 1
        else:
            SameImagecount = 0

        if SameImagecount < 2:
            await write_to_mjpeg_stream(img_bytes)
            LastImage = img_bytes

        await asyncio.sleep(interval)
    return response
Ejemplo n.º 3
0
    def ffmpeg_stream_content_type(self):
        """Return HTTP content type for ffmpeg stream."""
        if self._major_version is not None and self._major_version > 3:
            return CONTENT_TYPE_MULTIPART.format("ffmpeg")

        return CONTENT_TYPE_MULTIPART.format("ffserver")