Rtsp что это в видеорегистраторе
Что такое RTSP
- OPTIONS — возвращает список поддерживаемых методов (OPTIONS, DESCRIBE и т.д.);
- DESCRIBE — запрос описания контента, описывает каждый трек в формате SDP;
- SETUP — запрос установки соединений и транспорта для потоков;
- PLAY — старт вещания;
- TEARDOWN — остановка вещания.
Рабочей лошадкой является другой протокол: RTP — Real-time Transport Protocol — транспортный протокол реального времени. С его помощью и передаются нужные нам данные. Стоит отметить, что с этим протоколом очень даже приятно работать, дело в том, что он облегчает клиентскому ПО восстановление данных после их фрагментации на канальном уровне. А также несёт в себе ещё несколько полезных полей: формат передаваемых данных, временную метку и поле синхронизации (если передаётся, например, одновременно аудио и видео). Хотя этот протокол может работать по TCP, его обычно используют с UDP из-за его ориентированности на скорость. То есть RTP данные это UDP датаграмма с заголовком и полезными данными медиа-контента (payload).
Казалось бы нам больше ничего и не нужно. Подключаемся по RTSP, забираем по RTP. Но не тут-то было, умные дяди придумали третий протокол: RTCP — Real-time Transport Control Protocol — протокол контроля за транспортом в реальном времени. Этот протокол служит для определения качества сервиса, с его помощью клиент и сервер знают как хорошо или плохо идёт передача контента. В соответствии с этими данными сервер, например, может понизить битрейт или вообще перейти на другой кодек.
Принято, что RTP использует чётный номер порта, а RTCP следующий нечётный.
Пример общения по RTSP
У меня только один источник RTSP потока — камера eVidence APIX Box M1, поэтому все примеры относятся к ней.
Первым делом VLC спрашивает камеру:
— А что я вообще могу с тобой делать? (OPTIONS)
— И тебе привет. А можешь ты меня просить сделать любое из OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY и PAUSE.
— Ладно, тогда скажи мне что у тебя есть по запросу "/jpeg"? (DESCRIBE)
— Тут у меня видео первой дорожкой идёт, M-JPEG, а второй дорожкой идёт аудио простое.
— Интересно глянуть на видео, первую дорожку, отсыпь мне его, пожалуйста в карман номер 41760, а шелуху всякую можешь в карман номер 41761 скидывать. (SETUP track1)
— ОК, по твоей команде…
— И звук тоже хочу послушать, сыпь в 7878, 7879 карманы. (SETUP track2)
— Да без проблем.
— Ну, посыпали. (PLAY)
Через некоторое время:
— Ладно, хватит, насмотрелся. (TEARDOWN)
— Как скажешь.
А ответ от сервера начинается с " RTSP/1.0 200 OK ", это прямо как " HTTP/1.1 200 OK " — знак, что всё хорошо: запрос принят, запрос понятен и не было никаких проблем в его реализации. И прямым текстом следует перечисление всех доступных методов.
Далее мы собираем информацию о том, что нас ждёт по запросу /jpeg, ведь мы именно за ним и пришли по ссылке " rtsp://192.168.0.254/jpeg ". Также указываем, что хотим получить ответ в виде SDP (строка 12).
В ответ нам приходит RTSP заголовок с указанием Content-Type и Content-Length , а после заголовка через пустую строку непосредственно сам контент в формате SDP:
Здесь всё достаточно очевидно. Нужны нам следующие строки:
Если мы хотим получать только видео, то из аудио данных мы игнорируем всё, кроме названия трека. Он нам нужен, чтобы настроить поток, но нас никто не заставляет этот поток принимать, однако камера отказывается работать, если игнорировать аудио полностью (если делать SETUP только для видео трека).
Честно говоря, я не знаю как будут реагировать разные камеры, если пренебрегать номером порта для аудио потока (7878), ведь мы его указываем с командой SETUP .
Далее идут два запроса SETUP , c указанием портов, на которые мы бы хотели принимать видео и аудио потоки. Первое число — порт для RTP, второе — для RTCP. В ответе камеры содержится информация о портах, с ними можно сверяться, чтобы удостовериться, что всё настроено правильно. Ещё нам необходимо запомнить идентификатор Session . Мы должны будем указывать его во всех последующих вызовах.
После команды PLAY начнётся передача видео на порт 41760 и аудио на порт 7878. И по команде TEARDOWN вещание прекращается, соединение разрывается.
MJPEG over RTP
- V (Version): (2) версия протокола. Сейчас номер версии 2.
- P (Padding, Дополнение): (1) используется в случаях, когда RTP-пакет дополняется пустыми байтами в конце, например для алгоритмов шифрования.
- X (Extension, Расширение): (1) указывает на наличие расширенного заголовка, определяется приложением. В нашем случае это не используется.
- CC (CSRC Count): (4) содержит количество CSRC-идентификаторов. Нами тоже не используется.
- M (Marker): (1) используется на уровне приложения, в нашем случае этот бит выставляется в единицу, если RTP пакет содержит окончание JPEG кадра.
- PT (Payload Type): (7) указывает формат полезной нагрузки — передаваемых данных. Для MJPEG это 26.
- Sequence Number: (16) номер RTP пакета, используется для обнаружения потерянных пакетов.
- Timestamp (32): временная метка, в нашем случае 90000 герцовая (90000 = 1 секунда).
- SSRC (Synchronization Source): (32) идентификатор синхронизатора, как смешно бы это не звучало. Определяет источник потока.
- CSRC (Contributing Source): (32) идентификаторы дополнительных источников, используется когда у нас поток идёт с нескольких мест.
- Extension Header ID: (16) идентификатор расширения, если оно у нас есть надо знать что оно из себя представляет. В нашем случае не используется.
- Extension Header Length: (16) длинна этого заголовка в байтах.
- Extension Header (Заголовок Расширения): сам заголовок. Содержимое может быть самым разным, зависит от контекста.
- Payload (Нагрузка): полезные данные — те самые наши JPEG кадры. Фрагментированные, конечно.
- Type-specific (Зависит от типа): (8) смысл поля зависит от реализации, в нашем случае не применяется.
- Fragment Offset (Смещение фрагмента): (24) указывает на положение текущего фрагмента кадра во всём кадре.
- Type (Тип): (8) от типа зависит как восстанавливается изображение.
- Q (Quality): (8) качество изображения.
- Width: (8) ширина кадра.
- Height: (8) и высота.
- Restart Marker header (Заголовок маркеров RST): (32) используется при декодировании JPEG, если применяются RST маркеры. Не знаю используют их камеры или нет, но я этот заголовок игнорирую. Это поле появляется только при Type от 64 до 127.
- Quantization Table Data (Таблицы квантинизации): если они присутствуют, то не нужно их отдельно вычислять. А нужны они для правильного воссоздания картинки из JPEG данных. Если эти таблицы не правильные, то изображение будет с неправильными цветами и контрастами. Таблиц должно быть две: Luma и Chroma для яркости и цветности соответственно.
- MBZ, Precision, Length: (32) параметры таблиц квантинизации, я их игнорирую, Length задаю равным 128 — две таблицы по 64 байт. В ином случае я не знаю как с ними работать.
RTCP пакет содержит в себе некоторое подмножество, он бывает четырёх типов: 201 — отчёт источника, 202 — отчёт получателя, 203 — описание источников и 204 — назначение определяется приложением. Мы должны принимать в первую очередь 201 тип, затем отправлять 202 тип. 203 и 204 необязательны, но я их тоже учитываю. В одном UDP пакете может быть несколько RTCP пакетов.
- Version: (2) версия RTP.
- Padding: (1) то же самое, что и для RTP.
- SC or RC or Subtype: (5) в зависимости от типа может быть количеством источников (Sources Count) или количеством получателей (Receivers Count) включенных в отчёт получателя и источника соответсвенно. Если это APP пакет, то это поле определяет подтип такого пакета.
- Packet Type: (8) тип пакета, 201 — отчёт источника (Sender's Report SS), 202 — отчёт получателя (Receiver's Report RR), 203 — описание источников (Source Description SDES) и 204 — назначение определяется приложением (APP).
- Length: (16) размер следующих за заголовком данных, измеряется в 32 битных единицах.
На этом введение заканчивается.
Python MJPEG over RTSP client
Вот мы и добрались до питона. Клиент состоит из нескольких файлов, main.py содержит в себе callback функцию, которая обрабатывает получаемые изображения, также он запускает механизмы сетевого фреймворка Twisted и хранит в себе параметры подключения к камере. Все листинги я привожу укороченными, полную версию можно скачать по ссылке в конце статьи.
main.py
В принципе можно работать и без реализации RTCP протокола и приёма аудио данных. В этом случае камера разрывает соединение через примерно минуту. Приходится всё время переподключаться, это делается автоматически, поэтому проблем не доставляет. Однако для статьи я дописал RTCP часть и сделал заготовку для приёма аудио данных.
Следующим важным файлом является rtsp_client.py . Он самый запутанный, но его цель очевидна — правильно установить соединение, описанное выше.
rtsp_client.py
В случае присутсвия аудио трека, этот модуль также запускает rtp_audio_client.py и соответствующий RTCP клиент.
После успешного соединения за работу принимается rtp_mjpeg_client.py , обрабатывая входящий поток данных.
rtp_mjpeg_client.py
Он прост в понимании. Каждый раз, когда мы принимаем очередную датаграмму, мы парсим её с помощью модуля rtp_datagram.py , а результат скармливаем модулю rfc2435jpeg.py , который создаёт полноценное JPEG изображение. Далее мы ждём появления маркера rtp_dg.Marker и как он появится вызываем callback функцию с восстановленным изображением.
Парсер RTP датаграм выглядит вот так:
rtp_datagram.py
Модуль восстановления JPEG достаточно большой, так как содержит в себе несколько таблиц и довольно длинную функцию генерации заголовка. Поэтому я их здесь опущу, предоставив только функции парсинга полезной нагрузки RTP и создания окончательного JPEG изображения.
rfc2435jpeg.py
Я также реализовал модуль приёма аудио данных rtp_audio_client.py , но не стал их преобразовывать в проигрываемые данные. Если кому-нибудь это будет необходимо я в этом файле сделал набросок как всё должно быть. Нужно только организовать парсинг на подобии rfc2435jpeg.py . С аудио данными легче, так как они не фрагментированны. Каждая посылка несёт в себе достаточно данных для воспроизведения. Приводить этот модуль здесь не буду, так как статья и так уж очень длинная (поскорей бы реализовали хабрафолд).
Для корректной работы нам нужно принимать и отсылать RTCP пакеты, принимаем Sender's Reports, отсылаем Receiver's Reports. Для упрощения задачи мы будем отсылать наши RR сразу после приёма SR от камеры и будем в них закладывать идеализированные данные о том, что всё хорошо.
rtcp_client.py
А вот модуль работы непосредственно с RTCP датаграмами. Он получился тоже достаточно большим.
rtcp_datagram.py
Парсинг строго согласно RFC. Использую функцию unpack для конвертирования данных в численные переменные, по массиву данных перемещаюсь с помощью переменной off , которая содержит текущее смещение.
Делать версию листингов с русскими коментариями уже не было сил, так что простите если кому так не удобно.
Interleaved Mode.
Разница с Non-Interleaved Mode в том что все пакеты будут сыпаться в этот же порт.
Пример:
Запоминаем
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
Теперь смотрим что и как.
Камеры шлют видео и аудио в разные RTP потоки. 2n поток — данные, 2n+1 поток — RTCP.
На видео нам идет 0 и 1 канал, на аудио 2 и 3 канал.
Теперь смотрим
Transport: RTP/AVP;unicast;destination=10.112.28.33;source=10.112.28.231;client_port=49501-49502;server_port=6970-6971
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
В первом случае указаны порты, во втором каналы.
С с Non-Interleaved Mode всё понятно. Просто RTP пакеты сыпятся в порты и их можно читать как то так:
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
s.receive(packet);
Прочитать про SDP
Так как мода была mjpeg и текущая на h264, то рассмотрим их.
С MJpeg всё предельно ясно. А вот с H264 начинаются различия в камерах.
Формат h264 состоит из блоков с NAL заголовками (7.4.1 NAL unit semantics).
Чтобы можно было декодировать h264 необходимо помимо данных самого h264 иметь данные SPS (Sequence parameter set) и PPS(Picture parameter set). Первый описывает последовательность, второй параметры картинки. Так как сам кодек h264 знаю очень плохо, то большего описания не будет. SPS имеет тип 7, PPS 8. Без них невозможно декодировать h264.
Самое интересное — Qihan шлет SPS и PPS прям в RTP пакетах, Dlink не шлет их в RTP пакетах. Но SPS и PPS шлется в SDP пакете в параметре sprop-parameter-sets в кодировке base64.
sprop-parameter-sets=Z2QAKK2EBUViuKxUdCAqKxXFYqOhAVFYrisVHQgKisVxWKjoQFRWK4rFR0ICorFcVio6ECSFITk8nyfk/k/J8nm5s00IEkKQnJ5Pk/J/J+T5PNzZprQCgDLSpAAAAwHgAAAu4YEAAPQkAABEqjve+F4RCNQ=,aO48sA==
Шлются они через запятую
Вариант декодирования.
Так как камеры 720p или 1080p, то в 1 RTP пакет ни jpeg фрейм, ни h264 фрейм не поместится, то они режутся на пакеты.
RTP Payload Format for JPEG-compressed Video
RTP Payload Format for H.264 Video
JPEG
RTP пакет содержит main JPEG header
а дальше может варьироваться от Type и Q
Для декодирования jpeg нужно знать или вычислить quantization tables.
В моих камерах quantization tables шли в стартовом пакете Jpeg, по этому они просто брались оттуда.
Все вычисления есть в RFC.
Последний пакет фрейма вычисляется по RTP header Marker bit. Если он 1, то это последний пакет фрейма.
H264
NAL Header
Single NAL Unit Packet
Это как раз SPS и PPS. Type=7 или Type=8
Если фрейм h264 не влезает в RTP пакет (1448 байт), то фрейм режется на фрагменты. (5.8. Fragmentation Units (FUs))
Type = 28
Эти заголовки следуют сразу после RTP заголовка
Для декодера h264 NAL — нужная информация. Если идет фрагментация фрейма, то NAL нужно восстанавливать. (FU)
нужно взять первые 3 бита из FU indicator и слить их с 5 последними FU header.
Теперь самое главное — сохраняем поток.
Jpeg
в 2х словах. Получаем RTSP Interleaved Frame (например Channel: 0x00, 1448 bytes), читаем 1448 байт, делаем writeRawToStream, полиморфизм делает свое дело.
шлем его раз в 55 секунд и всё.
- Добавить
- Удалить
- Запустить
- Остановить
- Архив
- Настройка
- Выход
- Посмотреть — запускает Vlc
- Склеить и посмотреть — клеит файлы и запускает Vlc
- Выход
При простом просмотре генерируется m3u файл и кормится в VLC
4
При склеивании ffmpeg клеит, после запускается VLC
5
Программа нарезает поток на файлы, интервал задается в настройках
Что делает ffmpeg:
Клеит
На выходе куча файлов
6
По хорошему можно писать в любой OutputStream
Git hub
Дальнейшей жизни программы может и не быть. Возможно допишу когда нибудь RTP классы для звука. (так как увлекаюсь до сих пор SIP)
Ну и самое вкусное.
Есть стандарт видео наблюдения ONVIF
Есть профессиональные железки, которые с камерами работают только по нему.
Есть камеры, которые работают по нему (Qihan, он же Proline), а ссылки rtsp приходится гуглить.
Есть опенсорсный продукт Onvif device manager для управления подобными железяками.
Я же в программу добавил поддержку onvif без авторизации и с авторизацией.
7
Git hub
В 2х словах об Onvif: Это soap.
Работа простая. 1. Шлем POST-XML, 2. Получаем XML
Код на гитхабе. Ключ -s сохраняет все запросы и ответы XML.
пример запроса:
Если пройтись по ссылкам выше, то можно получить всю документацию по Onvif.
Ответ:
Дальнейшее общение по onvif без авторизации идет в этом же ключе.
А вот пример общения но уже с авторизацией
Т.е. нужно слать заголовок. (тестилось на D-link DCS-2103, остальные камеры без авторизации работали, китай).
и пароль (Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) ))
Всё было сделано в образовательных целях. Если есть вопросы и вдруг понадобиться более подробное описание чего либо — пишите.
Надеюсь кому нибудь пригодится.
Так как ребенок уже в том возрасте, когда уходит в школу и приходит из нее самостоятельно, при этом имеет ломаный график обучения, стала задача мониторинга, как он делает уроки, сколько времени занимается фортепиано и прочих задач воспитания.
Но денег не особо много, чтобы покупать какие-то специализированные решения, поэтому решено было поскрести по завалам хлама в серверной и с разрешения руководства утащить домой IP-камеру Xblitz iSee P2P IP WiFi.
Камера Xblitz iSee P2P IP WiFi
В камере была заявлена поддержка ONVIF, что автоматически наталкивало на мысль, что нужно ставить ZoneMinder и управлять устройством через него.
Установил, но, как оказалось, эта камера ни при каких настройках не хотела работать с ним.
В веб-интерфейсе камеры выяснилось, что изготовителем камеры до брендирования для польского рынка является китайский производитель netcam360.
Веб-интерфейс камеры
После определения настоящего производителя, через поисковик, выяснилось, что не только я имею проблемы с вышеуказанным форматом. И не только мне не удалось настроить на работу с указанным протоколом. Видимо, включение ONVIF в интерфейсе — это ни что иное как шутка от программистов из Китая.
Включение ONVIF в интерфейсе
Было решено, что захватывать буду через RTSP. Благо, этот метод работал.
Но, так как я заинтересовался темой написания сервиса в systemd, определил сделать не простой bash-скрипт для захвата потока, а такой себе сервис.
Содержание конфигурационного файла
Осталось только в cron добавить удаление устаревших файлов, так как один час записи — это файл примерно 1,5 ГБ.
И можно спокойно мониторить.
Но, через несколько дней я выяснил, что камера иногда перестает отвечать и видео прерывается.
Пришлось еще запланировать в cron проверку камеры с помощью скрипта, информирование об этом в slack и рестарт камеры. Опытным путем определил, что зависать она может один раз в 10-12 часов. Поэтому планировщик проверяет пишет ли камера один раз в полчаса. Потеря получаса записи для меня не критична.
Скрипт проверки камеры
Скрипт перезапуска камеры
Собственно все. Надеюсь кому-то еще мое решение поможет быстро и недорого организовать видеонаблюдение.
Установка IP камеры — удобный способ получения картинки в любом месте, где присутствует подключение к интернету. Но для работы с видеопотоком необходим соответствующий инструментарий. Существуют различные варианты поддерживаемых IP камерами протоколов трансляции, и один из самых удобных среди них — RTSP.
Что такое RTSP
Аббревиатура расшифровывается как Real Time Streaming Protocol, или потоковый протокол реального времени. Это решение прикладного уровня для работающих с мультимедийным контентом систем. Оно позволяет удаленно контролировать поток информации с медиасервера (которым может выступать IP камера), отправлять команды управления этим потоком. Также, если на сервере хранятся файлы записей, RTSP обеспечивает к ним доступ.
Сжатие в рамках RTSP не выполняется. Транспортные протоколы и способ инкапсуляции передаваемой информации он тоже не устанавливает. Упрощенно процесс выглядит следующим образом:
По умолчанию сервер RTSP работает на порту 544. Захват видео и звука можно выполнять с помощью таких программ, как плееры VLC или Windows Media Player, и иных клиентов с поддержкой протокола. Существуют также веб-приложения и программные решения для трансляции потока в интернет (например, стриминга на YouTube).
Как получить поток RTSP с камеры
Чтобы просматривать видео и захватывать звук посредством этой технологии, необходима поддержка RTSP на стороне камеры. Этот протокол поддерживают многие образцы имеющихся на рынке устройств, но в документации возможность описана не всегда.
Если поддержка заявлена, то в инструкции будут прописаны настройки для доступа к трансляции. Они представляют собой ссылку для подключения в следующем формате:
Перед выполнением дальнейших инструкций рекомендуем прочитать как узнать IP камеры видеонаблюдения.
Далее следуют user и password — логин пользователя и пароль для подключения (их может и не быть). После них указываются дополнительные параметры, который у разных камер могут отличаться.
Как узнать RTSP адрес
Ссылка может находиться в документации или явно указываться в веб-интерфейсе устройства. Если известно, что камера точно поддерживает RTSP, но параметры нигде явно не указаны, их придется выяснять:
- На сайте разработчика.
- Запросить напрямую у производителя или поставщика. Как правило, по запросу они такую информацию предоставляют, с этим нет проблем даже у китайских вендоров с AliExpress.
- Распознать камеру с помощью протокола ONVIF, который поддерживается практически всеми моделями.
Для последнего потребуется ПО Onvif Device Manager, компьютер под управлением Windows и сама камера.
Важно: она и ПК должны находиться в одной сети.
Device Manager умеет конфигурировать видеосервер, захватывать видео и так далее, но самая важная функция этой программы в данном случае — WS-Discovery, обнаружение устройств в сети.
Когда вы скачали и поставили программу, нужно сделать следующее:
- запустить ее и нажать внизу кнопку Refresh. Начнется процесс поиска;
- когда камера обнаружится, выбрать в меню пункт Live Video;
- под картинкой будет адрес rtsp-ссылки, который можно скопировать для дальнейшего использования.
Смотрим видео через RTSP
Для стриминга в интернет, существуют различные способы. Один из самых доступных — использовать связку VLC и программы OBS Studio, это бесплатное и достаточно простого решения.
Существуют также онлайн-сервисы вывода изображения в интернет, например, webcam.io, и прочие. Спецификации протокола открыты, поэтому специалисты могут написать и собственный проигрыватель RTSP.
Читайте также: