Выбор программного обеспечения
Сканирование диска программой DVR Examiner (обычно её использовал для подобных целей) показало, что на диске всего 4 видеофрагмента с одной камеры. То есть программа не очень отработала.
Дальше просканировал диск программой myCCTV Recovery – демо версия нашла все камеры и все ролики. Правда восстановить ничего не позволяет, а за однократное использование программа просит 200 Евро. Слишком много вообще-то. Не могу себе позволить. Но я убедился, что видео на диске есть. Будем копать дальше.
Нашёл ещё одну китайскую программу – аналогично myCCTV Recovery, все видео нашла, но восстановить тоже 200 Евро. Активированную не нашёл. Что же дальше.
Ручное восстановление
Посовещавшись со знакомыми экспертами в этой области я решил попробовать выковырять видеопоток вручную.
Снял образ с диска (на всякий случай) и посмотрел начало диска в HEX-редакторе:
Сигнатура ZHILING1.0 – спецификацию не этот формат я не нашёл, но мне подсказали опорные моменты.
Итак, идёт сигнатура вышеупомянутая, затем большая область нулей.
Начиная со смещения 0x0008F60000 пошёл видеопоток.
Формат следующий:
И такая ситуация циклична…
То есть мне по сути надо читать содержимое диска, искать по сигнатуре ZLAV, затем прочитать номер канала – если это нужная камера, то выгрузить фрейм в выходной файл. Далее нужно будет упорядочить по номеру последовательности и сконвертировать в mpeg например бесплатной ffmpeg.exe.
Python-скрипт
На 500 Гб образе скрипт работал примерно неделю. На выходе получил множество .h264 файлов видеопотока.
После чего запустил батник:
FOR %%f IN (*.h264) DO ffmpeg.exe -i %%f -vcodec copy %%f.mpeg
И файлы преобразуются в mpeg. Их уже можно просмотреть в обычном проигрывателе Media Player Classic. Осталось найти нужный фрагмент и при желании склеить отдельные куски.
P.S. Скрипт мне подсказал коллега, который пожелал остаться неизвестным)
Сканирование диска программой DVR Examiner (обычно её использовал для подобных целей) показало, что на диске всего 4 видеофрагмента с одной камеры. То есть программа не очень отработала.
Дальше просканировал диск программой myCCTV Recovery – демо версия нашла все камеры и все ролики. Правда восстановить ничего не позволяет, а за однократное использование программа просит 200 Евро. Слишком много вообще-то. Не могу себе позволить. Но я убедился, что видео на диске есть. Будем копать дальше.
Нашёл ещё одну китайскую программу – аналогично myCCTV Recovery, все видео нашла, но восстановить тоже 200 Евро. Активированную не нашёл. Что же дальше.
Ручное восстановление
Посовещавшись со знакомыми экспертами в этой области я решил попробовать выковырять видеопоток вручную.
Снял образ с диска (на всякий случай) и посмотрел начало диска в HEX-редакторе:
Сигнатура ZHILING1.0 – спецификацию не этот формат я не нашёл, но мне подсказали опорные моменты.
Итак, идёт сигнатура вышеупомянутая, затем большая область нулей.
Начиная со смещения 0x0008F60000 пошёл видеопоток.
Формат следующий:
- Начало фрейма: 4 байта (5A 4C 41 56) “ZLAV”;
- Тип фрейма: 2 байта (00 FC);
- Номер канала (камера, нумерация с 0): 2 байта (00 00);
- Номер последовательности: 4 байта (00 00 00 3E);
- Секунды: 4 байта (00 00 06 0F);
- Далее неизвестное поле и данные фрейма в формате h264;
- Окончание фрейма: 4 байта (7A 6C 61 76) “zlav”;
И такая ситуация циклична…
Python-скрипт
Python:
import io
import os
f_input = open(r'1.dd', 'rb')
f_input.seek(0, io.SEEK_END)
file_size = f_input.tell()
print('file size = {}'.format(file_size))
START_OFFSET = 0x0008F60000
CHUNK_SIZE = 1024 * 1024 * 16
frames_count = 0
channels_var = dict()
types_var = dict()
frame_seq_prev = -1
f_input.seek(START_OFFSET, io.SEEK_SET)
data_bytes = bytearray()
total_bytes_done = 0
f_output_ch_index = 0
f_output_ch = None
while f_input.tell() < file_size:
data_bytes.extend(bytearray(f_input.read(CHUNK_SIZE)))
frame_channel = -1
for i in range(0, len(data_bytes) - 64):
if b'ZLAV' in data_bytes[i:i + 4]:
frame_offset = i
frame_type = data_bytes[i + 4]
frame_channel = data_bytes[i + 6]
if frame_channel != 2:
continue
frame_seq = int.from_bytes(data_bytes[i + 8:i + 12], byteorder='little', signed=False)
frame_time_seconds = int.from_bytes(data_bytes[i + 16:i + 20], byteorder='little', signed=False)
if b'zlav' in data_bytes[i:i + 4]:
frames_count = frames_count + 1
frame_size = int.from_bytes(data_bytes[i + 4:i + 8], byteorder='little', signed=False)
if frame_channel == 2:
if frame_type == 0xfc or frame_type == 0xfd:
if f_output_ch is None:
f_output_ch = open('ch{}_{}_{}.h264'.format(frame_channel + 1, frame_time_seconds, f_output_ch_index), 'wb')
f_output_ch.write(data_bytes[frame_offset + 8:frame_offset + frame_size - 8])
f_output_ch.flush()
if frame_channel not in channels_var.keys():
channels_var[frame_channel] = 0
channels_var[frame_channel] = channels_var[frame_channel] + 1
if frame_seq_prev + 1 != frame_seq:
f_output_ch.close()
f_output_ch_index = f_output_ch_index + 1
f_output_ch = open('ch{}_{}_{}.h264'.format(frame_channel + 1, frame_time_seconds, f_output_ch_index), 'wb')
frame_seq_prev = frame_seq
frame_str = ''
total_bytes_done = total_bytes_done + 1
data_bytes = data_bytes[-64:]
print('chunk done, total bytes = {}'.format(START_OFFSET + total_bytes_done))
print('frames count = {}'.format(frames_count))
print('channels = {}'.format(channels_var))
f_input.close()
f_output_ch.close()
На 500 Гб образе скрипт работал примерно неделю. На выходе получил множество .h264 файлов видеопотока.
После чего запустил батник:
FOR %%f IN (*.h264) DO ffmpeg.exe -i %%f -vcodec copy %%f.mpeg
И файлы преобразуются в mpeg. Их уже можно просмотреть в обычном проигрывателе Media Player Classic. Осталось найти нужный фрагмент и при желании склеить отдельные куски.
P.S. Скрипт мне подсказал коллега, который пожелал остаться неизвестным)