Files
detections/_docs/02_document/modules/streaming_buffer.md
T
Oleksandr Bezdieniezhnykh be4cab4fcb [AZ-178] Implement streaming video detection endpoint
- Added `/detect/video` endpoint for true streaming video detection, allowing inference to start as upload bytes arrive.
- Introduced `run_detect_video_stream` method in the inference module to handle video processing from a file-like object.
- Updated media hashing to include a new function for computing hashes directly from files with minimal I/O.
- Enhanced documentation to reflect changes in video processing and API behavior.

Made-with: Cursor
2026-04-01 03:11:43 +03:00

3.7 KiB

Module: streaming_buffer

Purpose

File-like object backed by a temp file that supports concurrent append (write) and read+seek (read) from separate threads. Designed for true streaming video detection: the HTTP handler appends incoming chunks while the inference thread reads and decodes frames via PyAV — simultaneously, without buffering the entire file in memory.

Public Interface

Class: StreamingBuffer

Method Signature Description
__init__ (temp_dir: str | None = None) Creates a temp file in temp_dir; opens separate write and read handles
append (data: bytes) -> None Writes data to temp file, flushes, notifies waiting readers
close_writer () -> None Signals EOF — wakes all blocked readers
read (size: int = -1) -> bytes Reads up to size bytes; blocks if data not yet available; returns b"" on EOF
seek (offset: int, whence: int = 0) -> int Seeks reader position; SEEK_END blocks until EOF is signaled
tell () -> int Returns current reader position
readable () -> bool Always returns True
seekable () -> bool Always returns True
writable () -> bool Always returns False
close () -> None Closes both file handles

Properties

Property Type Description
path str Absolute path to the backing temp file
written int Total bytes appended so far

Internal Logic

Thread Coordination

Uses threading.Condition to synchronize one writer (HTTP handler) and one reader (PyAV/inference thread):

  • append(): acquires lock → writes to file → flushes → increments _writtennotify_all() → releases lock
  • read(size): acquires lock → checks if data available → if not and not EOF, calls wait() (releases lock, sleeps) → woken by notify_all() → calculates bytes to read → releases lock → reads from file (outside lock)
  • seek(0, 2) (SEEK_END): acquires lock → if EOF not signaled, calls wait() in loop → once EOF, delegates to _reader.seek(offset, 2)

The file read itself happens outside the lock to avoid holding the lock during I/O.

File Handle Separation

Two independent file descriptors on the same temp file:

  • _writer opened with "wb" — append-only, used by the HTTP handler
  • _reader opened with "rb" — seekable, used by PyAV

On POSIX systems, writes flushed by one fd are immediately visible to reads on another fd of the same inode (shared kernel page cache). os.rename() on the path while the reader fd is open is safe — the fd retains access to the underlying inode.

SEEK_END Behavior

When PyAV tries to seek to the end of the file (e.g. to find MP4 moov atom), seek(0, 2) blocks until close_writer() is called. This provides graceful degradation for non-faststart MP4 files: the decoder waits for the full upload, then processes normally. For faststart MP4/MKV/WebM, SEEK_END is never called and frames are decoded immediately.

Dependencies

  • External: os, tempfile, threading
  • Internal: none (leaf module)

Consumers

  • main — creates StreamingBuffer in POST /detect/video, feeds chunks via append(), passes buffer to inference

Data Models

None.

Configuration

None.

External Integrations

None.

Security

None. Temp file permissions follow OS defaults (tempfile.mkstemp).

Tests

  • tests/test_az178_streaming_video.py::TestStreamingBuffer — sequential write/read, blocking read, EOF, concurrent chunked read/write, seek set, seek end blocking, tell, file persistence, written property, seekable/readable flags