Я пытаюсь очистить видеокадры с trafficview.org и не могу понять, как декодировать данные.
Я написал несколько строк кода на основе руководств по этому websocket_client для доступа к веб-сайту потоковой передачи и получения сообщения напрямую.
Я отслеживал сообщения, поступающие через вкладку сети в Chrome, а также копался в выводе из приведенного ниже кода и вполне уверен, что данные передаются в виде фрагментированного MP4. Ниже приведены первые 100 или около того байтов / сообщений:
б '\ xfa \ x00 \ x02 \ x86 \ xf1B \ xc0 \ x1e \ x00 \ x00 \ x00 \ x18ftypiso5 \ x00 \ x00 \ x02 \ x00iso6mp41 \ x00 \ x00 \ x02jmoov \ x00 \ x00 \ x00lmvhd \ x00 \ x00 \ x00 \ x00 \ xdb \ x7f \ xeb \ xb2 \ xdb \ x7f \ xeb \ xb2 \ x00 \ x00 \ x03 \ xe8 \ x00 \ x00 \ x00 \ x00 \ x00 \ x01 \ x00 \ x00 \ x01 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x01 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 '
В этом выводе много пар moof и mdat. Допустим, я позволил этому коду работать в течение 30 секунд, как я могу преобразовать эту необработанную строку байтов в файл mp4?
import json
from websocket import create_connection
url = 'wss://cctv.trafficview.org:8420/DDOT_CAPTOP_13.vod?progressive'
headers = json.dumps({
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'en-US,en;q=0.9',
'Cache-Control': 'no-cache',
'Connection': 'Upgrade',
'Host': 'cctv.trafficview.org:8420',
'Origin': 'https://trafficview.org',
'Pragma': 'no-cache',
'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
'Sec-WebSocket-Key': 'FzWbrsoHFsJWzvWGJ04ffw==',
'Sec-WebSocket-Version': '13',
'Upgrade': 'websocket',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36',
})
ws = create_connection(url, headers=headers)
# Then send a message through the tunnel
ws.send('ping')
# Here you will view the message return from the tunnel
flag = 3000
output = b''
while flag > 0:
output += ws.recv()
flag -= 1
Обновление: я адаптировал некоторый код для переполнения стека, чтобы предположительно передать данные fmp4 и преобразовать их в фреймы. Чтобы добраться туда, я заметил, что первые 16 байтов вывода из веб-сокета не соответствуют другим файлам mp4, которые я проверил. Итак, я сначала обрезаю первые 16 байтов. Я также не знаю, как должен закончиться один из этих файлов, поэтому я обрезал его до последнего фрагмента файла.
Приведенный ниже код может нормально читать заголовок mp4 (также ниже), но не может декодировать ни один из байтов.
output = output[8:]
import re
moof_locs = [m.start() for m in re.finditer(b'moof', output)]
output = output[:moof_locs[-1]-1]
import subprocess as sp
import shlex
width, height = 640, 480
# FFmpeg input PIPE: WebM encoded data as stream of bytes.
# FFmpeg output PIPE: decoded video frames in BGR format.
process = sp.Popen(shlex.split('/usr/bin/ffmpeg -i pipe: -f hls -hls_segment_type fmp4 -c h264 -an -sn pipe:'), stdin=sp.PIPE, stdout=sp.PIPE, bufsize=10**8)
process.stdin.write(output)
process.stdin.close()
in_bytes = process.stdout.read(width * height * 3)
in_frame = (np.frombuffer(in_bytes, np.uint8).reshape([height, width, 3]))
Вывод из ffmpeg:
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x994600] Could not find codec parameters for stream 0 (Video: h264 (avc1 / 0x31637661), none, 640x480): unspecified pixel format
Consider increasing the value for the 'analyzeduration' and 'probesize' options
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'pipe:':
Metadata:
major_brand : iso5
minor_version : 512
compatible_brands: iso6mp41
creation_time : 2020-09-11T13:40:21.000000Z
Duration: N/A, bitrate: N/A
Stream #0:0(und): Video: h264 (avc1 / 0x31637661), none, 640x480, 1k tbr, 1k tbn, 2k tbc (default)
Metadata:
creation_time : 2020-09-11T13:40:21.000000Z
encoder : EvoStream Media Server
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
Finishing stream 0:0 without any data written to it.
Nothing was written into output file 0 (pipe:), because at least one of its streams received no packets.
frame= 0 fps=0.0 q=0.0 Lsize= 0kB time=-577014:32:22.77 bitrate= -0.0kbits/s speed=N/A
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Output file is empty, nothing was encoded (check -ss / -t / -frames parameters if used)
Обновление 2:
Изучив поток, поступающий из веб-сокета, я понял, что каждое сообщение начинается с определенного целого числа, которое определено в коде javascript из trafficview. Порядок этих кодов ВСЕГДА один и тот же, они бывают следующим образом:
Header MOOV (250)
PBT Begin (249)
Video Buffer (252)
Header MOOF (251)
Header MOOF (251)
Header MOOF (251)
Header MDAT (254)
PBT End (255)
PBT Begin (249)
Continues Forever
Некоторые из этих тегов всегда одинаковы, например, 249 сообщений всегда f900 0000, а 255 сообщений всегда ff00 0000.
Я предполагаю, что сообщения 249 и 255 обычно не находятся во фрагментированном потоке mp4 или hls, и поэтому я думаю, что мне нужно использовать эту информацию тега, чтобы создать правильный формат файла с нуля.