Web 预览 API

MJPEG streaming helpers - serve live JPEG frames over HTTP.

MjpegStream is a thread-safe latest-frame holder (slow clients simply miss frames instead of building latency); mjpeg_wsgi_app mounts it into any WSGI server (flask/waitress/gunicorn); MjpegServer is a zero-dependency standalone HTTP server for apps that do not run a web framework.

Pair with AppClient.register_web_url() so the platform web console can reach the app container’s MJPEG page.

platform_stream_url() is the zero-server alternative: it composes the WebSocket URL of a PLATFORM camera stream (the same /api/v1/h264/{id} endpoint the console plays), so an app that pushes frames through FramePublisher can hand viewers a URL without opening any port of its own - the platform gateway already serves the stream.

Example (flask):

source = MjpegStream() app = Flask(__name__) app.route(“/video”)(mjpeg_wsgi_app(source, fps=15)) # push frames from a worker: source.push_frame(frame)

Example (standalone):

server = MjpegServer(port=8080, source=source) server.start() … server.stop()

Example (no own server at all):

# inject frames into the platform’s sub stream, then: url = platform_stream_url(“sub”, host=”192.168.1.10”, token=jwt)

neoruntime_ipc_sdk.web.WEB_HOST_ENV = 'AIPC_WEB_HOST'

Environment variable consulted when host is not passed explicitly to platform_stream_url(). Nothing injects it yet - set it in the app container or shell when the SDK runs somewhere that needs a non-default host (the SDK itself talks to the daemon over a local socket and never learns the device’s external address).

neoruntime_ipc_sdk.web.H264_WS_PATH = '/api/v1/h264'

Path the platform gateway serves encoded camera streams on (WebSocket, proxied to platform-api; the web console’s player consumes the same URL).

neoruntime_ipc_sdk.web.platform_stream_url(stream_id='sub', host=None, scheme=None, token=None)[source]

Compose the WebSocket URL of a platform camera stream.

The platform gateway (HTTPS on 443) already reverse-proxies encoded camera streams at /api/v1/h264/{stream_id}; the web console plays this URL. Apps that publish frames via FramePublisher (REPLACE or OVERLAY) can hand this URL to any viewer instead of running their own MJPEG server.

Parameters:
  • stream_id (str) – Platform stream name (main / sub / third).

  • host (str | None) – Device host, optionally with a port ("192.168.1.10", "localhost:8080"). Full origins ("https://...") are accepted - the scheme is mapped to ws/wss. Resolved from the AIPC_WEB_HOST environment variable when omitted, else localhost.

  • scheme (str | None) – "wss" (default - the TLS gateway) or "ws" for a plain-HTTP face (e.g. platform-api directly on localhost:8080). An explicit value overrides any scheme inferred from a full-origin host.

  • token (str | None) – Auth token appended as ?token=... - network access to /api/v1 requires one (the console passes its JWT here).

Returns:

The stream URL, e.g. wss://192.168.1.10/api/v1/h264/sub.

Raises:

ValueError – If stream_id is empty.

Return type:

str

class neoruntime_ipc_sdk.web.MjpegStream[source]

Bases: object

Thread-safe holder of the most recent JPEG frame.

__init__()[source]
push_jpeg(data)[source]

Publish an already-encoded JPEG frame (bytes).

push_frame(frame, quality=85)[source]

Encode a Frame to JPEG and publish it.

latest()[source]

Most recent JPEG bytes, or None before the first push.

latest_seq()[source]

Monotonic push counter (used with wait_new).

wait_new(after_seq, timeout=1.0)[source]

Block until a frame newer than after_seq arrives (or timeout).

neoruntime_ipc_sdk.web.mjpeg_wsgi_app(source, fps=15)[source]

Build a WSGI callable serving the stream as multipart/x-mixed-replace.

class neoruntime_ipc_sdk.web.MjpegServer(port=8080, host='0.0.0.0', source=None, path='/', fps=15)[source]

Bases: object

Standalone threaded HTTP server exposing one MJPEG stream.

__init__(port=8080, host='0.0.0.0', source=None, path='/', fps=15)[source]
property port: int

Actual bound port (useful when constructed with port=0).

start()[source]

Bind and start serving in a daemon thread.

stop()[source]

Stop serving and close the listening socket (idempotent).

MjpegServer

class neoruntime_ipc_sdk.MjpegServer(port=8080, host='0.0.0.0', source=None, path='/', fps=15)[source]

Bases: object

Standalone threaded HTTP server exposing one MJPEG stream.

__init__(port=8080, host='0.0.0.0', source=None, path='/', fps=15)[source]
property port: int

Actual bound port (useful when constructed with port=0).

start()[source]

Bind and start serving in a daemon thread.

stop()[source]

Stop serving and close the listening socket (idempotent).

MjpegStream

class neoruntime_ipc_sdk.MjpegStream[source]

Thread-safe holder of the most recent JPEG frame.

__init__()[source]
push_jpeg(data)[source]

Publish an already-encoded JPEG frame (bytes).

push_frame(frame, quality=85)[source]

Encode a Frame to JPEG and publish it.

latest()[source]

Most recent JPEG bytes, or None before the first push.

latest_seq()[source]

Monotonic push counter (used with wait_new).

wait_new(after_seq, timeout=1.0)[source]

Block until a frame newer than after_seq arrives (or timeout).

mjpeg_wsgi_app

neoruntime_ipc_sdk.mjpeg_wsgi_app(source, fps=15)[source]

Build a WSGI callable serving the stream as multipart/x-mixed-replace.

platform_stream_url

neoruntime_ipc_sdk.platform_stream_url(stream_id='sub', host=None, scheme=None, token=None)[source]

Compose the WebSocket URL of a platform camera stream.

The platform gateway (HTTPS on 443) already reverse-proxies encoded camera streams at /api/v1/h264/{stream_id}; the web console plays this URL. Apps that publish frames via FramePublisher (REPLACE or OVERLAY) can hand this URL to any viewer instead of running their own MJPEG server.

Parameters:
  • stream_id (str) – Platform stream name (main / sub / third).

  • host (str | None) – Device host, optionally with a port ("192.168.1.10", "localhost:8080"). Full origins ("https://...") are accepted - the scheme is mapped to ws/wss. Resolved from the AIPC_WEB_HOST environment variable when omitted, else localhost.

  • scheme (str | None) – "wss" (default - the TLS gateway) or "ws" for a plain-HTTP face (e.g. platform-api directly on localhost:8080). An explicit value overrides any scheme inferred from a full-origin host.

  • token (str | None) – Auth token appended as ?token=... - network access to /api/v1 requires one (the console passes its JWT here).

Returns:

The stream URL, e.g. wss://192.168.1.10/api/v1/h264/sub.

Raises:

ValueError – If stream_id is empty.

Return type:

str

使用示例

独立 MJPEG 预览服务器

from neoruntime_ipc_sdk import FdMediaClient, MjpegServer, MjpegStream

media = FdMediaClient()
stream = MjpegStream()

# 独立线程 HTTP 服务器,浏览器打开 http://<ip>:8080/ 即可预览
server = MjpegServer(port=8080, source=stream, fps=15)
server.start()

for frame in media.subscribe("main"):
    stream.push_frame(frame, quality=85)

server.stop()

推入已有 JPEG

# 应用侧已编码好的 JPEG 直接推送
import cv2

ok, jpeg = cv2.imencode(".jpg", annotated)
if ok:
    stream.push_jpeg(jpeg.tobytes())

配合 WSGI 应用(Flask / 内置服务器)

from wsgiref.simple_server import make_server
from neoruntime_ipc_sdk import MjpegStream, mjpeg_wsgi_app

stream = MjpegStream()
app = mjpeg_wsgi_app(stream, fps=15)

make_server("0.0.0.0", 8080, app).serve_forever()

低延迟读取最新帧

# latest/wait_new 适合自实现推送逻辑
seq = stream.latest_seq()
data = stream.latest()          # bytes | None
newer = stream.wait_new(seq, timeout=1.0)
if newer is not None:
    send_to_client(newer)

零服务器预览(复用平台流地址)

# 应用经 FramePublisher 把内容注入平台流(REPLACE 或 OVERLAY)后,
# 不需要自建任何服务器:平台网关已在 /api/v1/h264/{stream_id}
# 反向代理编码流,Web 控制台的播放器消费的就是同一 URL。
import os
from neoruntime_ipc_sdk import FramePublisher, platform_stream_url

with FramePublisher(camera, dsp, stream_id="sub") as pub:
    pub.publish(frame)
    # host 默认取环境变量 AIPC_WEB_HOST,其次 localhost
    url = platform_stream_url("sub", host="192.168.1.10", token=jwt)
    # 'wss://192.168.1.10/api/v1/h264/sub?token=...'
    pub.publish_eos()   # 恢复纯 ISP 路径(下个 IDR 生效)

# token 必填:网络面访问 /api/v1 需要认证(与控制台同一 JWT);
# 完整地址可作 host 传入,http(s):// 前缀会映射为 ws(s)。