跳至主要内容

發送 JSON 中繼資料

當外部檢視器、錄影器或服務透過 UDP 接收 UTF-8 JSON 中繼資料時,請使用 MetadataSender。Insight 是一個能夠理解此通訊協定的接收器。

通訊協定

  • 預設主機:127.0.0.1
  • 預設中繼資料連接埠基數:9100
  • 頻道連接埠規則:metadata_port_base + channel
  • 預設傳送模式:非阻塞模式 (MSG_DONTWAIT)
  • 負載編碼:UTF-8 JSON 文字
  • 必需的最上層欄位:typedata
  • 最大邏輯負載:65,507 位元組

MetadataSender 將每個 UDP 負載限制在 1200 位元組或更少。最多 1200 位元組的 JSON 負載將保持為一個未變更的資料包。較大的負載會分割成多個區塊,每個區塊都帶有這個 12 位元組的二進位標頭:

位元組大小
01魔術位元組 0x4e
11協定版本 0x01
28作為無符號 64 位元大端整數的消息 ID
101以零為基數的區塊索引
111總區塊數

每個區塊最多包含 1188 個 JSON 位元組。接收器會重新組裝具有相同發送者位址和消息 ID 的區塊,並按照區塊索引的順序進行解析 JSON。UDP 傳遞仍然是盡力而為:發送者不會重試失敗的區塊,並且 send_raw_json(...)send_metadata(...) 在第一次本地傳送失敗後會傳回 false

接收器應接受未變更的 JSON 資料包和帶有版本的區塊。在發布此 Neat Library 版本之前或同時,將 Insight 更新到具有區塊重新組裝功能的版本。較舊的 Insight 版本將繼續接收最多 1200 位元組的負載,但無法解碼較大的分塊負載。

對於 Insight,將中繼資料頻道 N 與影片 UDP 串流在 9000 + N 上的連接。如果 Insight 或其他接收器在容器連接埠重新映射後執行,則從應用程式中明確傳遞映射的主機和連接埠。

追蹤、追蹤目標和其他自訂中繼資料可以作為通用 JSON 傳送。檢視器疊加層支援取決於接收器;Insight 追蹤視覺化效果在 sima-neat/insight#8 中單獨追蹤。

C++

simaai::neat::MetadataSenderOptions opt;
opt.host = "127.0.0.1";
opt.channel = 0;
opt.metadata_port_base = 9100;

std::string err;
simaai::neat::MetadataSender sender(opt, &err);

sender.send_metadata(
"tracking",
R"({"tracks":[{"id":"trk-1","bbox":[10,20,30,40]}]})",
12345,
"frame-7",
&err);

send_metadata(...) 會驗證 data_json,並建立這個封包:

{
"type": "tracking",
"timestamp": 12345,
"frame_id": "frame-7",
"data": {
"tracks": [
{
"id": "trk-1",
"bbox": [10, 20, 30, 40]
}
]
}
}

僅在呼叫者已建立完整的頂層負載時,才使用 send_raw_json(...)

sender.send_raw_json(
R"({"type":"object-detection","data":{"objects":[{"id":"obj_1","label":"car","confidence":0.92,"bbox":[120,80,96,64]}]}})",
&err);

預設情況下,即時分派是非阻塞的

MetadataSender 預設會將 MSG_DONTWAIT 應用於每個資料封包,因此即使本機的傳送緩衝區壅塞,也不會延遲同時分派視訊或推論工作的執行緒。當核心無法立即接受資料封包時,傳送函數會傳回 false,而不是等待。將該中繼資料封包視為已丟棄,並繼續進行即時工作;無法保證 UDP 傳遞。

預設建構函式和預設傳送選項是等效的:

simaai::neat::MetadataSenderSendOptions send_opt;
simaai::neat::MetadataSender sender(opt, send_opt, &err);

來電者如果明確表示希望拒絕投遞,則可以選擇啟用此功能:

simaai::neat::MetadataSenderSendOptions send_opt;
send_opt.nonblocking = false;
simaai::neat::MetadataSender sender(opt, send_opt, &err);

使用 stats() 來區分網路壅塞和其他類型的錯誤,並且在明確的封鎖模式下,檢測通話速度慢的情況:

const auto stats = sender.stats();
std::cerr << "sent=" << stats.datagrams_sent
<< " would_block=" << stats.would_block
<< " enobufs=" << stats.no_buffer_space
<< " max_send_ns=" << stats.max_send_duration_ns << '\n';

在傳送過程中,您可以安全地讀取 stats()。將結果視為一個並行診斷快照,而不是單一時間點的交易快照。

Python

import json
import pyneat

opt = pyneat.MetadataSenderOptions()
opt.host = "127.0.0.1"
opt.channel = 0
opt.metadata_port_base = 9100

sender = pyneat.MetadataSender(opt)

sender.send_metadata(
"object-detection",
json.dumps(
{
"objects": [
{
"id": "obj_1",
"label": "car",
"confidence": 0.92,
"bbox": [120, 80, 96, 64],
}
]
}
),
12345,
"frame-7",
)

stats = sender.stats()
print(stats.datagrams_sent, stats.would_block, stats.max_send_duration_ns)

如同在 C++ 中,明確設定 send_opt.nonblocking = False,並且僅在需要同步行為時,將其作為第二個建構函式參數傳遞。