Repository navigation
Add ndr.reader.video: native video reader (port of NDR-matlab #140) - #33
Merged
Merged
Conversation
Ports +ndr/+reader/video.m (NDR-matlab 794a0e8). MATLAB reads video with VideoReader; the Python port uses PyAV (the FFmpeg binding, an optional dependency in [formats] and [dev], imported lazily). - One video file per epoch; companion files ignored, directories expanded. - Frame API only: numframes, framesize, dimensionorder, datatype, frametimes, readframes, epochclock, t0_t1, getchannelsepoch, metadata, plus the static helpers videoextensions, videonumframes, channelsanddatatype, checkframeind, endtimes, scanframetimes. - Frame times are measured per decoded frame (correct for VFR) and cached per file by path/size/mtime; t0_t1 seeks near the end instead of scanning. readframes seeks by pts located from demuxed packets. - Grey pixel formats and grey-palette pal8 (MATLAB 'Grayscale AVI') give C=1; >8-bit video gives uint16. - Registers the video/videoreader/mp4/avi/mov aliases, records the class in the reader bridge YAML, and ports TestVideo.m, with extra cases for variable frame rate, header-less frame counts and 16-bit grey. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjkvVXsdCVw6NNe5SnGNyX
…'videoreader' alias) NDR-matlab #143 rewords the video reader's help so the 'video' type is defined by the file format and each frame's stored presentation time, not by VideoReader, and removes the MATLAB-specific 'videoreader' alias. No change to how frames are read. Mirror the wording in the module docstring, drop the alias from the registry and its tests, and bump the bridge hash so the drift check passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjkvVXsdCVw6NNe5SnGNyX
… rows
Symmetry:
- tools/make_example_data.py now also writes example_video.avi (6-frame
12x16 uncompressed 24-bit RGB) and example_video_grey.avi (8-bit with a
grey palette, MATLAB's 'Grayscale AVI' storage). The AVI is written by
hand, laid out as MATLAB's VideoWriter writes it: BI_RGB frames stored
bottom-up. Uncompressed so VideoReader reads it on every platform and the
two ports must agree pixel for pixel. Committed byte-identically to
NDR-matlab's example_data.
- tests/symmetry/{make,read}_artifacts/reader/test_read_video.py, mirroring
NDR-matlab's +makeArtifacts/+readArtifacts/+reader/readVideo.m (same
branch name, so the symmetry workflow pairs them). Frame times compare to
1e-6 s, since each port measures them through its own decoder.
Fix found by the new fixture: FFmpeg decodes a bottom-up 8-bit DIB with a
negative line stride, and the pal8 path read the plane in memory order, so
MATLAB-written greyscale AVIs came back upside down. FFmpeg-written test
files are top-down and could not show it; a unit test on the checked-in
bottom-up file now does (it fails without the fix).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjkvVXsdCVw6NNe5SnGNyX
This was referenced Oct 21, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ports
+ndr/+reader/video.mfrom VH-Lab/NDR-matlab#140, synced through VH-Lab/NDR-matlab#143 (d2ebe98). Adds cross-language symmetry tests for it, paired with VH-Lab/NDR-matlab#144 (same branch name,claude/clever-bardeen-hf5jgx, sotest-symmetry.ymlchecks it out).The reader
src/ndr/reader/video.py:ndr_reader_videomirrors every method ofvideo.munder the same names, frame API only. Where MATLAB usesVideoReader, Python uses PyAV (av, the FFmpeg binding). It is an optional dependency in[formats]and[dev]and is only imported when a video is read. PyAV wheels bundle FFmpeg.YXCZTorder.t0_t1seeks near the end instead of decoding the whole file.pal8(MATLAB's 'Grayscale AVI') give C=1. Video above 8 bits givesuint16.video,mp4,aviandmov. The MATLAB-specificvideoreaderalias was dropped upstream in #143, so it is dropped here too.videoentry (regular_port,d2ebe98). Itsdecision_logcovers where Python differs: a PyAV container stands in forVideoReader;readframesseeks by pts read from the demuxed packets (Python-only_framepts); and MATLAB error IDs map toValueError,IndexErrororFileNotFoundError.tests/test_video_reader.py(32 tests) portsTestVideo.m, plus cases for variable frame rate, a container with no frame count in its header, 16-bit grey, and the checked-in example files.Symmetry
tools/make_example_data.pynow also writesexample_video.avi(6-frame 12×16 uncompressed 24-bit RGB, 10 fps) andexample_video_grey.avi(8-bit, grey palette).VideoWriterwrites it: BI_RGB frames stored bottom-up.VideoReaderreads them on every platform and the ports must agree pixel for pixel.example_data/, and the README is updated in both repos.tests/symmetry/{make,read}_artifacts/reader/test_read_video.py, paired with NDR-matlab's+makeArtifacts/+readArtifacts/+reader/readVideo.m. They compare:numframes,framesize,dimensionorder,datatype,frametimes,t0_t1,epochclock, channels and image metadata;SelectCread, and an out-of-order greyscale read.Bug fixed by the new fixture
FFmpeg decodes a bottom-up 8-bit DIB with a negative line stride. The
pal8path read the plane in memory order, so MATLAB-written greyscale AVIs came back upside down. Test files written by FFmpeg are top-down, so they could not show this. A unit test on the checked-in bottom-up file now covers it, and that test fails without the fix.Verification
pytest: 723 passed, 15 skipped (same skips as before), 24 xfailed.NDR_BRIDGE_CHECK_STRICT=1bridge completeness + conventions, run against a full NDR-matlab clone: 191 passed.blackandruff checkare clean.claude/clever-bardeen-hf5jgx:VideoReaderreads the grey-palette AVI as one channel, matching Python pixel for pixel.mainbecause the matching branch was pushed seconds later, so its video checks skipped. It was re-run rather than counted.🤖 Generated with Claude Code
https://claude.ai/code/session_01QjkvVXsdCVw6NNe5SnGNyX