CLI to extract playable video from EZVIZ/Hikvision SD cards' proprietary round-robin storage format. Works specifically for devices that use hiv<xxxxx>.mp4 and index00.bin files.
Project description
ezhikstract
CLI tool to extract playable video from EZVIZ and Hikvision SD cards' proprietary round-robin storage format.
It works specifically with security camera or video doorbell SD cards that contain files named hiv<xxxxx>.mp4 and an index00.bin metadata/index file. The tool parses the index file, validates video segments, extracts the raw MPEG-PS streams, and remuxes them into standard .mp4 containers, merging segments from the same day into a single daily video file.
No full video re-encoding is performed; video streams (HEVC) are copied directly. Audio streams (e.g., PCM G.711 / Alaw) are re-encoded to Opus to ensure compatibility with standard media players.
Installation
Install the package directly from the repository directory:
pip install ezhikstract
Usage
The CLI provides two main commands: list and extract.
Command: list
Lists all valid recordings found on the SD card without extracting them.
Usage
ezhikstract list INPUT_DIR
Arguments
INPUT_DIR(Required): Root directory of the SD card containingindex00.bin.
Command: extract
Extracts recording segments from the SD card, filters them by date/time if specified, and merges segments from the same day into a single file named by start time (DDMMYYYY HHMMSS.mp4).
Usage
ezhikstract extract INPUT_DIR [OPTIONS]
Arguments
INPUT_DIR(Required): Root directory of the SD card containingindex00.bin.
Options
-o, --output PATH: Output directory for the extracted and merged.mp4files. Default isrecordings.--from DATETIME: Inclusive start filter, UTC (format:YYYY-MM-DD HH:MM:SS).--to DATETIME: Exclusive end filter, UTC (format:YYYY-MM-DD HH:MM:SS).--replace / --no-replace: Whether to overwrite existing files in the output directory. Default is--replace.
How it Works
The SD cards of these cameras use a pre-allocated round-robin storage file format:
index00.bin(and the backup copyindex01.bin) contains pointers, timestamps, offsets, and checksums for the recorded video segments.- The video data is written to pre-allocated
hivxxxxx.mp4files, which are all exactly 268.4 MB (as are the index files). - Within the
hivxxxxx.mp4files, the videos are stored as raw MPEG-PS streams (MPEG Program Stream with HEVC video and G.711/PCM audio). ezhikstractparsesindex00.bin, verifies the boundaries and starts of the segments insidehivxxxxx.mp4(checking for valid MPEG-PS headers), extracts the segments, groups them by day, stream-copies the HEVC video tracks, re-encodes the audio to Opus, and concats the daily segments using the FFmpeg concat demuxer.
Storage Format
The security camera SD cards (typically EZVIZ / Hikvision) use a pre-allocated, round-robin storage format. All files (index00.bin, index01.bin, and the video files hivxxxxx.mp4) are pre-allocated to the exact same size of 268.4 MB (281,444,352 bytes). The same pre-allocation strategy applies to the mobile app thumbnails (index00p.bin and hivxxxxx.pic).
Files
index00.bin: The primary index file containing pointers, timestamps, offsets, and checksums for the recorded video segments.index01.bin: A redundant copy ofindex00.binused for backup and reliability.hivxxxxx.mp4: Pre-allocated video containers (numbered fromhiv00000.mp4upwards) containing segment-based raw MPEG-PS streams.index00p.bin: Metadata and index for the pictures/thumbnails used for mobile app push notifications (human/motion detection).hivxxxxx.pic: Pre-allocated picture containers (numbered fromhiv00000.picupwards) containing segment-based raw JPEG images.
Index File Layout (index00.bin / index00p.bin)
An index file consists of:
- A 1280-byte header (
HEADER_BUFFER_LENGTH). - An array of AV-File records (each 32 bytes).
- An array of Segment records (80 bytes for video, 96 bytes for pictures).
1. File Header (1280 Bytes)
The first 1280 bytes of the index file contains general settings, the number of files, and state flags. Both index00.bin and index00p.bin share this exact structure.
| Offset | Size (Bytes) | Field Name | Data Type | Description |
|---|---|---|---|---|
0 |
8 |
modify_counter |
uint64_t (LE) |
Number of times the video segments have been modified. |
8 |
4 |
index_version |
uint32_t (LE) |
Version of the index file (typically 2 or 3). |
12 |
4 |
av_files |
uint32_t (LE) |
Total number of pre-allocated .mp4 or .pic files. |
16 |
4 |
next_file_no |
uint32_t (LE) |
File number (xxxxx) of the next file to be written. |
20 |
4 |
last_file_no |
uint32_t (LE) |
File number of the last recording stored. |
24 |
1176 |
cur_file_info |
bytes |
Info about the current file (includes timestamps, write progress, and padding). |
1200 |
76 |
unknown |
bytes |
Reserved padding. |
1276 |
4 |
checksum |
uint32_t (LE) |
Custom checksum for header validation (not standard CRC32). |
2. AV-File Records Section
Immediately following the header at offset 1280, there is a contiguous array of AV-File records.
- Record Size: 32 bytes (
FILE_RECORD_LENGTH). - Total Records: Equal to
av_filesfrom the header. - Span: Offset
1280to1280 + (av_files * 32). - Note: In
index00p.bin, these blocks are primarily empty placeholder values (0xffff...).
3. Segment Records Section
The segment records list begins directly after the AV-File records section.
Video Segments (index00.bin)
Each segment record is exactly 80 bytes (SEGMENT_RECORD_LENGTH).
For each pre-allocated video file, the index contains space for up to 256 segment entries (MAX_SEGMENTS_PER_SOURCE_FILE).
| Offset | Size (Bytes) | Field Name | Data Type | Description |
|---|---|---|---|---|
0 |
8 |
Unused | bytes |
Contains segmentType, status, reservedA, and resolution. |
8 |
8 |
start_time_raw |
uint64_t (LE) |
Segment start timestamp. Lower 32 bits represent the Unix epoch. |
16 |
8 |
end_time_raw |
uint64_t (LE) |
Segment end timestamp. Lower 32 bits represent the Unix epoch. A value of 0 denotes an empty slot. |
24 |
16 |
Unused | bytes |
Contains keyframe timestamps (firstKeyFrameAbsTime, etc.). |
40 |
4 |
start_offset |
uint32_t (LE) |
Start byte offset of this segment inside its hivxxxxx.mp4 file. |
44 |
4 |
end_offset |
uint32_t (LE) |
End byte offset of this segment inside its hivxxxxx.mp4 file. |
48 |
32 |
Unused | bytes |
Reserved fields and metadata info segments. |
Picture Segments (index00p.bin)
Each segment record is exactly 96 bytes. Unused segment slots are padded with zero bytes (0x0000...).
| Offset | Size (Bytes) | Field Name | Data Type | Description |
|---|---|---|---|---|
0 |
8 |
flags |
bytes |
Type/Status flag for the segment (e.g. 0x0d00010000000000). |
8 |
8 |
start_time_raw |
uint64_t (LE) |
Segment timestamp. Lower 32 bits represent the Unix epoch. |
16 |
8 |
end_time_raw |
uint64_t (LE) |
Segment end timestamp (usually matches start_time_raw for pictures). |
24 |
16 |
Unused | bytes |
Reserved timestamp block. |
40 |
4 |
start_offset |
uint32_t (LE) |
Start byte offset of this segment inside its hivxxxxx.pic file. |
44 |
4 |
end_offset |
uint32_t (LE) |
End byte offset of this segment inside its hivxxxxx.pic file. |
48 |
32 |
info |
bytes |
Contains INFO string and related info offsets. |
80 |
16 |
watermark |
bytes |
ASCII camera ID/Watermark string appended at the end of the segment (e.g., BK1721071). |
Media Container Structures
Video File Structure (hivxxxxx.mp4)
Despite the .mp4 file extension, these files are not standard MP4 containers. Instead, they are pre-allocated byte blocks containing raw MPEG Program Streams (MPEG-PS):
- Streams:
- Video Codec: HEVC (H.265).
- Audio Codec: PCM (G.711 A-law /
pcm_alaw). Note: Original recordings do not use AAC.
- Segment Storage:
- Multiple recordings are written sequentially into these containers, mapped by the offsets defined in the segment tables in
index00.bin.
- Multiple recordings are written sequentially into these containers, mapped by the offsets defined in the segment tables in
- MPEG-PS Validation:
- Valid segments start with the standard MPEG Program Stream Pack Start Code
0x000001BA(with MPEG-2 marker prefix byte0x40at offset 4). - A System Header sequence
0x000001BBis present within the first 2KB of any valid segment. - When a device is abruptly powered down or files are overwritten, segment blocks can become corrupted or partially written, which requires checking these magic bytes to prevent loading corrupt recordings.
- Valid segments start with the standard MPEG Program Stream Pack Start Code
Picture File Structure (hivxxxxx.pic)
These files act identically to the .mp4 files but are used exclusively for storing raw JPEG images (snapshots/thumbnails).
- Format:
- Standard JPEG binary images containing SOI (Start of Image) magic bytes
0xFF 0xD8 0xFF.
- Standard JPEG binary images containing SOI (Start of Image) magic bytes
- Segment Storage:
- Successive snapshots are dumped sequentially into the 256.4 MB block.
- Offsets mapping to exact byte locations in the
.picblock are found withinindex00p.bin.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ezhikstract-1.0.0.tar.gz.
File metadata
- Download URL: ezhikstract-1.0.0.tar.gz
- Upload date:
- Size: 25.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d1715ff9e482000adf6575c1ada62beaf8b31d895d65b953a84d7d29e065d57
|
|
| MD5 |
49e2cf9da17437255e3f69f7c6df8064
|
|
| BLAKE2b-256 |
e5800babfffa13380cb0272f14b13dab315c867f3557baf42eae8a27fc4797f7
|
Provenance
The following attestation bundles were made for ezhikstract-1.0.0.tar.gz:
Publisher:
release.yml on damianjude/ezhikstract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ezhikstract-1.0.0.tar.gz -
Subject digest:
1d1715ff9e482000adf6575c1ada62beaf8b31d895d65b953a84d7d29e065d57 - Sigstore transparency entry: 2194263723
- Sigstore integration time:
-
Permalink:
damianjude/ezhikstract@466a0b3edfaa52f20dc66316f5dd8535fc40572a -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/damianjude
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@466a0b3edfaa52f20dc66316f5dd8535fc40572a -
Trigger Event:
release
-
Statement type:
File details
Details for the file ezhikstract-1.0.0-py3-none-any.whl.
File metadata
- Download URL: ezhikstract-1.0.0-py3-none-any.whl
- Upload date:
- Size: 18.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fea80a66345c6561c9b45af7345d8f9633e340c5ff7dc0500f9b268860f5bb2c
|
|
| MD5 |
3c19929645c1887f8aeecdf09749c2ff
|
|
| BLAKE2b-256 |
7ed5574b59c6b63da521e4df5d651c165a1227637e8f86a8c9b5e5843d9c2ec9
|
Provenance
The following attestation bundles were made for ezhikstract-1.0.0-py3-none-any.whl:
Publisher:
release.yml on damianjude/ezhikstract
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ezhikstract-1.0.0-py3-none-any.whl -
Subject digest:
fea80a66345c6561c9b45af7345d8f9633e340c5ff7dc0500f9b268860f5bb2c - Sigstore transparency entry: 2194263756
- Sigstore integration time:
-
Permalink:
damianjude/ezhikstract@466a0b3edfaa52f20dc66316f5dd8535fc40572a -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/damianjude
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@466a0b3edfaa52f20dc66316f5dd8535fc40572a -
Trigger Event:
release
-
Statement type: