fix: 修复时间戳显示

This commit is contained in:
nnbcccscdscdsc
2026-04-02 20:18:50 +08:00
parent 51ea86e887
commit 1a41905d4c

View File

@@ -22,6 +22,10 @@ OMNISOCKET_CONFIG_PATH = PROJECT_ROOT / "config" / "omnisocket_demo.yaml"
VIDEO_SOURCE_MODE = os.getenv("VIDEO_SOURCE_MODE", "auto").strip().lower()
OMNISOCKET_FRAME_FRESH_SECONDS = 2.0
VIDEO_TIMESTAMP_SAMPLE_SIZE = 10
VIDEO_TIMESTAMP_TRAILER_BYTES = 8
VIDEO_TIMESTAMP_ENDIANNESS = "little"
VIDEO_TIMESTAMP_UNIT = "ms"
VIDEO_TIMESTAMP_MULTIPLIER_NS = 1_000_000
VIDEO_TIMESTAMP_MAX_SKEW_NS = 7 * 24 * 60 * 60 * 1_000_000_000
@@ -211,16 +215,35 @@ class OmniSocketVideoReceiver:
return frame[8:]
return None
def _extract_jpeg_frame(self, frame: bytes) -> bytes | None:
def _split_jpeg_frame_and_trailer(self, frame: bytes) -> tuple[bytes, bytes] | None:
jpeg_payload = self._extract_jpeg_payload(frame)
if jpeg_payload is None:
return None
# 当前发送端协议是 JPEG 末尾固定追加 8 字节 little-endian 毫秒时间戳。
if jpeg_payload.endswith(b"\xff\xd9"):
return jpeg_payload, b""
if (
len(jpeg_payload) >= VIDEO_TIMESTAMP_TRAILER_BYTES + 2
and jpeg_payload[-(VIDEO_TIMESTAMP_TRAILER_BYTES + 2) : -VIDEO_TIMESTAMP_TRAILER_BYTES] == b"\xff\xd9"
):
return jpeg_payload[:-VIDEO_TIMESTAMP_TRAILER_BYTES], jpeg_payload[-VIDEO_TIMESTAMP_TRAILER_BYTES:]
# 兜底兼容旧格式,避免直接丢帧。
eoi_index = jpeg_payload.rfind(b"\xff\xd9")
if eoi_index < 0:
return jpeg_payload
return jpeg_payload, b""
return jpeg_payload[: eoi_index + 2]
trailer_start = eoi_index + 2
return jpeg_payload[:trailer_start], jpeg_payload[trailer_start:]
def _extract_jpeg_frame(self, frame: bytes) -> bytes | None:
split_payload = self._split_jpeg_frame_and_trailer(frame)
if split_payload is None:
return None
jpeg_frame, _ = split_payload
return jpeg_frame
def _extract_sequence(self, frame: bytes) -> int | None:
if len(frame) >= 8 and not frame.startswith(b"\xff\xd8"):
@@ -228,50 +251,26 @@ class OmniSocketVideoReceiver:
return None
def _extract_frame_tail(self, frame: bytes) -> bytes:
jpeg_payload = self._extract_jpeg_payload(frame)
if jpeg_payload is None:
split_payload = self._split_jpeg_frame_and_trailer(frame)
if split_payload is None:
return b""
eoi_index = jpeg_payload.rfind(b"\xff\xd9")
if eoi_index < 0:
return b""
trailer_start = eoi_index + 2
if trailer_start >= len(jpeg_payload):
return b""
return jpeg_payload[trailer_start:]
_, trailer = split_payload
return trailer
def _extract_frame_timestamp(self, frame: bytes) -> tuple[int, str, str] | None:
trailer = self._extract_frame_tail(frame)
if len(trailer) < 8:
if len(trailer) != VIDEO_TIMESTAMP_TRAILER_BYTES:
return None
now_ns = time.time_ns()
raw_timestamp = trailer[-8:]
best_candidate: tuple[int, str, str] | None = None
best_distance_ns: int | None = None
for endianness in ("big", "little"):
value = int.from_bytes(raw_timestamp, endianness, signed=True)
value = int.from_bytes(trailer, VIDEO_TIMESTAMP_ENDIANNESS, signed=False)
if value <= 0:
continue
return None
for unit, multiplier in (
("ns", 1),
("us", 1_000),
("ms", 1_000_000),
("s", 1_000_000_000),
):
timestamp_ns = value * multiplier
distance_ns = abs(now_ns - timestamp_ns)
if distance_ns > VIDEO_TIMESTAMP_MAX_SKEW_NS:
continue
if best_distance_ns is None or distance_ns < best_distance_ns:
best_distance_ns = distance_ns
best_candidate = (timestamp_ns, unit, endianness)
timestamp_ns = value * VIDEO_TIMESTAMP_MULTIPLIER_NS
if abs(time.time_ns() - timestamp_ns) > VIDEO_TIMESTAMP_MAX_SKEW_NS:
return None
return best_candidate
return timestamp_ns, VIDEO_TIMESTAMP_UNIT, VIDEO_TIMESTAMP_ENDIANNESS
def _run(self) -> None:
# 后台持续接收循环: