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
hostis 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 viaFramePublisher(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 theAIPC_WEB_HOSTenvironment variable when omitted, elselocalhost.scheme (str | None) –
"wss"(default - the TLS gateway) or"ws"for a plain-HTTP face (e.g. platform-api directly onlocalhost:8080). An explicit value overrides any scheme inferred from a full-originhost.token (str | None) – Auth token appended as
?token=...- network access to/api/v1requires 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_idis empty.- Return type:
- class neoruntime_ipc_sdk.web.MjpegStream[source]
Bases:
objectThread-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:
objectStandalone 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:
objectStandalone 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
mjpeg_wsgi_app
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 viaFramePublisher(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 theAIPC_WEB_HOSTenvironment variable when omitted, elselocalhost.scheme (str | None) –
"wss"(default - the TLS gateway) or"ws"for a plain-HTTP face (e.g. platform-api directly onlocalhost:8080). An explicit value overrides any scheme inferred from a full-originhost.token (str | None) – Auth token appended as
?token=...- network access to/api/v1requires 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_idis empty.- Return type:
使用示例
独立 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)。