FFMPEG: 'Несоответствующий транспорт в ответе сервера' Но openRTSP работает
Купил дешевую китайскую ip камеру (бренд Yoosee). Я хочу записать его поток с помощью ffmpeg.
Мне удается заставить его работать только с использованием транспортного протокола RTSP / UDP , например:
ffmpeg -rtsp_transport udp -i rtsp://admin:pass@192.168.0.103:554/onvif1 streamfile.mkv
pass
- пароль, определенный в клиенте приложения камеры Android.
Но я очень предпочитаю транспорт RTSP / TCP, потому что при использовании UDP изображения часто повреждаются. Изображения кажутся размазанными и растрепанными. Так что я практически все протестировал и даже скомпилировал
FFMPEG
из источника с использованием последнего репозитория . Но ничто не заставляет работать ffmpeg, android или windows. Я всегда получаю:
[rtsp @ 0xxxxxxx] Nonmatching transport in server reply
Наконец обнаружил openRTSP, который использует ту же библиотеку, что и VLC. С его помощью мне удалось подключить RTSP / TCP ( после компиляции из исходников ).
openRTSP -n -D 1 -c -B 10000000 -b 10000000 -q -Q -F cam_file \
-d 60 -P 30 -t -u admin pass rtsp://192.168.0.103:554/onvif1
Подробнее о
openRTSP
параметры здесь .
Самая странная часть - это сравнение сообщений настройки RTSP (FFMPEG и openRTSP). Кажется очевидным, что сервер ip-камеры поддерживает RTP / AVP / TCP. RTP перемежается с существующим TCP-соединением.
И глядя на исходный код
ffmpeg/libavformat/rtsp.c
швы, у ffmpeg проблемы с его идентификацией?
...
if (reply->transports[0].lower_transport != lower_transport) {
av_log(s, AV_LOG_ERROR, "Nonmatching transport in server reply\n");
err = AVERROR_INVALIDDATA;
goto fail;
}
...
1 ответ
Цитата мудрости
IP-камеры разного качества, некоторые из них, по моему опыту, ведут себя нестабильно. Работа с их потоками RTSP требует определенной отказоустойчивости.
Это, по-видимому, побочный продукт низкокачественной индустрии видеонаблюдения, которая играет быстро и свободно со стандартами, причем RTSP и ONVIF являются двумя наиболее частыми злоупотреблениями. К счастью, эти проблемы обычно можно обойти. Если ваши IP-камеры и контроллер не предназначены для совместной работы, используйте ONVIF только для однократного обнаружения и управления настройками.
FFMPEG не очень терпим в настройке RTSP
После борьбы я начал сравнивать сообщения RTSP / SETUP между и
ffmpeg
. по умолчанию уже выводит много подробной диагностики.
openRTSP
отправляет команды
OPTIONS
, а потом
SETUP
. Сообщения SETUP были:
Sending request: SETUP rtsp://192.168.0.103:554/onvif1/track2 RTSP/1.0
CSeq: 6
Authorization: Digest username="admin", realm="HIipCamera", nonce="ddd21dbd0620b6fb4b1f9bcbb06340a0", uri="rtsp://192.168.0.103:554/onvif1", response="91d9c611aa004eeb1390b3fbb9373648"
User-Agent: ./openRTSP (LIVE555 Streaming Media v2021.02.11)
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
Session: 3a4d2e6d
ответ камеры:
Received a complete SETUP response:
RTSP/1.0 200 OK
CSeq: 6
Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=2-3
Session: 3a4d2e6d;timeout=60
FFMPEG
За
FFMPEG
ты должен использовать
-v 9 and -loglevel 99
params, чтобы увидеть сообщения RTSP. Он только отправил
DESCRIBE
запрос:
DESCRIBE rtsp://192.168.0.103:554/onvif1 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf58.67.100
ответ камеры:
Transport: RTP/AVP;unicast;destination=192.168.0.100;source=192.168.0.103;interleaved=0-1
Session: 37287775;timeout=60
Злоупотребление RTSP и решение для взлома FFMPEG
Сравнивая сообщения, становится ясно, что камера может подключаться с использованием протокола TCP с чередованием RTSP / AVP / TCP. Но по ответу камеры мы видим, что в строке «Транспорт:» он не включает «TCP» после «RTP / AVP», как это было запрошено. Нравиться:
Transport: RTP/AVP/('TCP' missing here);....
Я проанализировал код и нашел следующую интуитивно понятную последовательность вызовов:
ff_rtsp_connect
,
ff_rtsp_make_setup_request
,
ff_rtsp_send_cmd
,
ff_rtsp_read_reply
и
ff_rtsp_parse_line
. Внутри этого последнего я нашел
rtsp_parse_transport
и следующий код:
if (!av_strcasecmp(lower_transport, "TCP"))
th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
else
th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
текст анализируется после
'RTP/AVP;'
в моем случае
""
пустая строка символа, так как сервер камеры не включил ее.
Я вставил
|| !av_strcasecmp(lower_transport, "")
в коде. Предполагая, что транспорт
RTSP_LOWER_TRANSPORT_TCP
когда
lower_transport
опущено. Как показано ниже:
if (!av_strcasecmp(lower_transport, "TCP") || !av_strcasecmp(lower_transport, ""))
th->lower_transport = RTSP_LOWER_TRANSPORT_TCP;
else
th->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
После перекомпиляции: FFMPEG работает отлично!
Я взломал FFMPEG, сделав его терпимым к злоупотреблениям RTSP, которые совершал сервер камеры. Поскольку моя версия FFMPEG будет работать только на моем неиспользуемом телевизоре Android (как сервер камеры видеонаблюдения / видеонаблюдения), других проблем не возникнет.
Лучшим решением была бы команда FFMPEG (я уже открыл билет), чтобы рассмотреть также случай отсутствия нижнего транспорта в ответе сервера rtsp. Затем сравните с запросом, отправленным клиентом, чтобы определить, был ли пропущен нижний транспорт. И попробуй соединиться с этим.
Совет
Возможно, если вы дойдете сюда, ваша дешевая камера может пострадать от злоупотребления RTSP. Я рекомендую вам попробовать использовать
openRTSP
сначала посмотреть, удастся ли ему подключиться. Если да, то попробуйте отладить его сообщения RTSP / setup. Возможно, существует какое-то нестандартное или взломанное решение, если вы измените (на свой страх и риск)
ffmpeg/libavformat/rtsp.c
код. Или вы можете / должны использовать библиотеку live555, VLC или mplayer.