Кодеки и согласование медиа
Коротко о главном
-
Кодеки звонка согласуются обменом SDP по модели offer/answer (RFC 3264): одна сторона предлагает список форматов (offer), другая отвечает выбранными из него (answer).
-
Платформа старается не транскодировать: при передаче предложения на другое плечо известные платформе форматы из входящего SDP остаются впереди в своем порядке, дополнительные кодеки добавляются после них (кроме
--*и предложения esg внутрь платформы — см. opts.payloads_audio). -
Состав и порядок дополнительных кодеков задает параметр роли payloads_audio_offer. Базовые кодеки
PCMU/8000,PCMA/8000иtelephone-event/8000предлагаются всегда, если их не исключить явно (кроме предложения esg внутрь платформы, плеча провайдера сopts.payloads_audioиaudio_formatsсерверов записи). -
У провайдера список кодеков opts.payloads_audio необязателен, а если задан — точный: на плече провайдера предлагаются только указанные кодеки в указанном порядке. Применяется только при обслуживании медиа через медиашлюз bgmg.
-
Ответ, отправляемый платформой, содержит множество кодеков или один кодек в зависимости от параметра allow_ac_set.
-
Видео в SIP-звонках платформа пробрасывает, как правило, без декодирования.
Термины
- Плечо (leg)
-
Участок вызова между двумя узлами. Каждый микросервис сигнализации на пути вызова обслуживает два плеча — входящее и исходящее. Вызов внутреннего абонента на провайдера (абонент → sg → b2b → esg → провайдер) имеет 4 плеча сигнализации. Медийных плеч может быть столько, сколько медиашлюзов в цепочке обработки — от 0 до 3, в зависимости от задач и настроек.
- Формат (fmt, payload type, PT)
-
Номер, под которым кодек указан в строке
m=SDP. Номера 0–95 статические и закреплены за кодеками (0 — PCMU, 8 — PCMA, 18 — G729 и т.д.), 96–127 динамические и связываются с кодеком атрибутомa=rtpmap. - Терминейшен
-
Точка подключения потока плеча к медиашлюзу. У каждого медийного плеча свой терминейшен со своими local и remote SDP.
- Транскодинг
-
Перекодирование аудио из одного кодека в другой медиашлюзом. В зависимости от сочетания кодеков может требовать дополнительных ресурсов: например, перепаковка между PCMU и PCMA табличная и почти ничего не стоит, а кодирование в G729 или opus заметно дороже.
Поддерживаемые кодеки
Имена кодеков в параметрах указываются в формате Name/Freq, регистр не важен.
| Кодек | PT по умолчанию | Примечание |
|---|---|---|
|
0 |
G.711 μ-law. Базовый |
|
8 |
G.711 A-law. Базовый |
|
3 |
|
|
9 |
Широкополосный |
|
13 |
Комфортный шум. Не используется как основной кодек |
|
18 |
|
|
97, 98, 99 |
Динамический |
|
101 |
Сигналы DTMF по RFC 2833/4733. Базовый. Не используется как основной кодек |
|
102–105 |
Динамический |
|
106 |
Динамический |
|
107 |
Динамический |
Видео: H263/90000 (34), H263-1998/90000, H264/90000, VP8/90000, VP9/90000 (динамические).
Неизвестные платформе аудиоформаты отбрасываются, когда SDP обрабатывается для медиашлюза с транскодингом, неизвестные имена в параметрах игнорируются. Неизвестные видеоформаты не отбрасываются: видео пробрасывается, см. Видео.
Базовые кодеки
PCMU/8000, PCMA/8000 и telephone-event/8000 предлагаются всегда, даже если не указаны в payloads_audio_offer (кроме предложения esg внутрь платформы, плеча провайдера с opts.payloads_audio и audio_formats серверов записи). Так разные роли одного экземпляра платформы с разными настройками (например, ivr3 и b2b2) всегда имеют общий кодек и не отвечают друг другу финальным неуспешным ответом 415 Unsupported Media Type.
Исключить базовый кодек можно явно: -PCMU/8000 — не добавлять PCMU, -* — не добавлять ни один неуказанный базовый кодек.
Параметры
payloads_audio_offer, payloads_video_offer (роли)
Параметры ролей b2b, conf, esg, ivr, prompt, sg. Применяются, когда экземпляр роли формирует предложение (offer): создает новый исходящий вызов или передает предложение входящего вызова на другое плечо. sg применяет параметр только к SDP ответа на OPTIONS.
| Элемент | Значение |
|---|---|
|
Кодек предлагается; положение в SDP — по месту в списке |
|
Кодек не добавляется (обычно базовый) |
|
Не добавляется ни один неуказанный базовый кодек |
|
Кодек не добавляется и исключается из SDP входящего вызова, передаваемого на другое плечо |
|
Как |
Итоговый список: сначала указанные кодеки в порядке списка, затем неуказанные и не исключенные базовые. CN/8000 и telephone-event/8000 размещаются в конце. Если параметр не задан или пуст, предлагаются только базовые кодеки.
Для видео базовых кодеков нет: список задает состав и порядок.
opts.payloads_audio (провайдер)
Поле opts.payloads_audio провайдера.
-
Медиа не обслуживается (поле провайдера
mediaвыключено, bgmg не используется): кодеки к вызовам провайдера не применяются, SDP проходит через esg без изменений. Поле должно быть пустым. -
Медиа обслуживается через bgmg, поле задано: на плече провайдера предлагаются только указанные кодеки в указанном порядке, медиашлюз при необходимости транскодирует;
telephone-event/8000добавляется в конец, если не исключен элементом-telephone-event/8000или-*. Список действует только на плече провайдера. Вызов, re-INVITE или INVITE с Replaces от провайдера принимается, если в его SDP есть кодек из списка, иначе esg отвечает 488 Not Acceptable Here (re-INVITE отклоняется без разрыва вызова). Ответ провайдеру содержит кодеки списка из его предложения в порядке списка; приopts.allow_ac_set = false— один: тот, что уже использует другое плечо, иначе первый по списку. Если INVITE пришел без SDP, предложение внутрь строится по списку. Предложение внутрь платформы содержит кодеки провайдера из списка в порядке провайдера (telephone-event/8000— если не исключен), поэтому транскодинг к устройствам выполняет медиашлюз b2b, а не bgmg. Кодеки списка должны поддерживаться медиашлюзами mg (параметрcodecs), через которые обслуживаются вызовы b2b. Внутренние плечи списком не ограничиваются: если в предложении изнутри нет кодеков списка, транскодирует bgmg. -
Медиа обслуживается через bgmg, поле не задано: esg передает SDP без изменений, медиашлюз пропускает медиа без транскодинга — это снижает нагрузку на bgmg. Если в INVITE, re-INVITE или INVITE с Replaces нет ни одного известного платформе основного кодека, esg отвечает 488 Not Acceptable Here (re-INVITE отклоняется без разрыва вызова).
payloads_audio_offerэкземпляра esg применяется только в двух случаях:-
поле провайдера reinvite имеет значение
0: re-INVITE не пересылаются, на них отвечает сам esg, медиашлюз может транскодировать. С учетомpayloads_audio_offerстроятся INVITE к провайдеру и INVITE к новой цели при переводе на стороне провайдера (REFER), который обслуживает esg; предложение провайдера внутрь платформы передается с его кодеками в его порядке (неизвестные платформе форматы отбрасываются). Ответ esg на re-INVITE и INVITE с Replaces содержит только кодеки предложения; если общих нет — 488 Not Acceptable Here, re-INVITE отклоняется без разрыва вызова; -
INVITE пришел без SDP: esg сам формирует предложение на другое плечо по
payloads_audio_offer.
-
Порядок списка провайдера намеренно не подстраивается под порядок входящего SDP: список из нескольких кодеков может выражать предпочтение (например, G729/8000 для экономии полосы, PCMA/8000 — запасной). Поэтому возможен транскодинг: внутреннее устройство предложило PCMA, а провайдер выбрал первый в списке G729. Если транскодинг на медиашлюзе нежелателен, поставьте первым кодек, который используют внутренние устройства (например, ["PCMA/8000", "G729/8000"]), или укажите только его.
allow_ac_set
Параметр роли b2b (по умолчанию true) и поле провайдера opts.allow_ac_set (по умолчанию false, применяется при bgmg). Определяет, сколько кодеков платформа указывает в своем ответе (answer) на предложение:
-
true— подмножество известных платформе кодеков предложения; впереди — кодеки, выбранные противоположной (вызываемой) стороной в ее ответе, если они есть в предложении (ответ esg провайдеру со списком — в порядке списка); -
false— один кодек: первый по порядку предложения, который есть и в ответе противоположной стороны; если таких нет — первый основной кодек предложения.telephone-event/8000иCN/8000из предложения добавляются к нему (ответ esg провайдеру со списком — см. opts.payloads_audio).
Подробнее — RFC 3264 и allow_ac_set.
Как строится SDP
Новый исходящий вызов
Роль формирует предложение сама, без входящего SDP: исходящий вызов из сценария IVR, вызов участника конференции, служебные вызовы. Список строится по payloads_audio_offer экземпляра роли.
| payloads_audio_offer | Форматы в SDP |
|---|---|
не задан |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Для вызовов на серверы записи SIPREC и потоковой записи состав кодеков можно задать отдельно — полем audio_formats сервера в настройках домена siprec_options, mixed_call_rec_options, streamed_call_rec_options. Если поле задано, предлагаются ровно указанные кодеки в порядке списка (telephone-event/8000 и CN/8000 — в конце, если указаны), payloads_audio_offer не применяется; если не задано — предложение строится по payloads_audio_offer экземпляра b2b.
Передача предложения на другое плечо
Роль получает INVITE с SDP и передает предложение на другое плечо (b2b; esg — см. opts.payloads_audio). Порядок:
-
известные платформе форматы входящего SDP — в их порядке (кроме исключенных
--); -
затем недостающие кодеки по
payloads_audio_offer— в порядке итогового списка; -
CN/8000иtelephone-event/8000— в конце.
Входящие форматы остаются впереди, потому что вызываемая сторона обычно выбирает первый подходящий формат. Если она выберет любой из форматов, предложенных вызывающей стороной, медиашлюзу не нужно транскодировать: потоки в этом формате передаются между плечами без изменений.
| payloads_audio_offer экземпляра b2b | Форматы в предложении на другое плечо |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ответ
Ответ (answer) содержит только форматы из предложения, на которое он отвечает: статические — по номеру, динамические — по имени кодека. Количество — по allow_ac_set.
| Ответ плеча B | Ответ b2b плечу A при allow_ac_set = true | при allow_ac_set = false |
|---|---|---|
|
|
|
|
|
|
|
|
|
Если кодек, выбранный плечом B, есть в предложении A, транскодинга нет. Иначе медиашлюз транскодирует.
Номера динамических форматов
В ответе динамические форматы указываются под номерами из предложения, на которое он отвечает (RFC 3264, раздел 6.1). В предложении, передаваемом на другое плечо, номера динамических форматов входящего SDP сохраняются; добавляемые динамические кодеки получают свободные номера, не занятые во входящем SDP. Если стороны объявили для одного кодека разные номера, медиашлюз сопоставляет форматы по имени кодека: каждая сторона получает поток с номерами из своего SDP.
Входящее предложение: m=audio 30000 RTP/AVP 8 96 101 a=rtpmap:96 opus/48000/2 a=rtpmap:101 telephone-event/8000 Предложение на другое плечо (payloads_audio_offer = ["G722/8000", "speex/16000"]): m=audio 40000 RTP/AVP 8 96 9 98 0 101 a=rtpmap:8 PCMA/8000 a=rtpmap:96 opus/48000/2 a=rtpmap:9 G722/8000 a=rtpmap:98 speex/16000 a=rtpmap:0 PCMU/8000 a=rtpmap:101 telephone-event/8000
Сценарии вызовов
Исходящий из IVR через провайдера
IVR → b2b → esg → провайдер.
-
IVR формирует новое предложение по своему
payloads_audio_offer. -
b2b передает его на плечо esg, добавляя кодеки по своему
payloads_audio_offer. -
esg на плече провайдера: если у провайдера задан
opts.payloads_audio(и используется bgmg) — только его кодеки в его порядке; иначе SDP передается без изменений, а приreinvite = 0— дополняется поpayloads_audio_offeresg (см. opts.payloads_audio). -
Провайдер отвечает; ответ на каждом плече содержит кодеки из предложения этого плеча, медиашлюз соединяет потоки, при необходимости транскодируя.
Вызов между абонентами
Устройство → sg → b2b → sg → устройство (sg может быть одним и тем же экземпляром или разными).
sg при использовании bgmg не меняет кодеки, пропуская INVITE через себя, и работает без транскодинга. b2b передает предложение вызывающего устройства вызываемому, добавляя кодеки по payloads_audio_offer; входящие форматы остаются впереди. Если вызываемое устройство выбирает любой из форматов вызывающего, транскодинга нет.
С устройства на провайдера
Устройство → sg → b2b → esg → провайдер. Пример: устройство не поддерживает telephone-event/8000 (передает DTMF через SIP INFO), у провайдера opts.payloads_audio не задан.
b2b дополняет предложение базовым telephone-event/8000, esg передает SDP провайдеру без изменений (при reinvite = 0 — дополняет по payloads_audio_offer esg). Ответ b2b устройству содержит только кодеки его предложения, без telephone-event/8000. Сигналы DTMF провайдера по RFC 2833 b2b передает устройству через SIP INFO и обратно (см. DTMF без telephone-event).
Входящий от провайдера
Провайдер → esg → b2b → …
-
У провайдера задан
opts.payloads_audio(bgmg): esg принимает вызов, только если в SDP провайдера есть кодек из списка (иначе — 488 Not Acceptable Here), и отвечает кодеками из пересечения: множеством или одним по opts.allow_ac_set. Предложение дальше в платформу содержит кодеки провайдера из списка в порядке провайдера, b2b дополняет его по своемуpayloads_audio_offer. -
Не задан: esg передает предложение провайдера в платформу без изменений (при
reinvite = 0— без неизвестных платформе форматов); b2b дополняет его по своемуpayloads_audio_offer. Ответ провайдеру содержит кодеки из его предложения.
Разные роли одного экземпляра платформы
Роли одного экземпляра платформы могут быть настроены по-разному, например ivr3 с ["G722/8000"] и b2b2 с ["G729/8000"]. Благодаря базовым кодекам у них всегда есть общий кодек, и вызов не завершается финальным неуспешным ответом 415. Исключая базовые кодеки (-PCMU/8000, -*), не лишним будет убедиться, что у всех ролей экземпляра остается общий кодек.
sg и esg при использовании bgmg
-
sg не меняет кодеки: INVITE проходит через sg со своим SDP, транскодинга на sg нет.
-
esg действует по opts.payloads_audio провайдера: если список задан, он применяется к SDP плеча провайдера, внутрь передаются кодеки провайдера из списка, при необходимости выполняется транскодинг; если не задан — предложение провайдера передается внутрь с его кодеками, а
payloads_audio_offerэкземпляра esg применяется к предложениям провайдеру приreinvite = 0и к INVITE без SDP.
DTMF без telephone-event
Сигналы DTMF передаются в RTP по RFC 2833 (формат telephone-event/8000) или сообщениями SIP INFO (application/dtmf-relay). b2b перепаковывает их между плечами:
-
SIP INFO с одного плеча передается на другое как RFC 2833, если в SDP другого плеча есть
telephone-event/8000, иначе — как SIP INFO; -
событие RFC 2833 с одного плеча передается на другое как SIP INFO, если в SDP другого плеча нет
telephone-event/8000.
Поэтому исключение telephone-event/8000 (-telephone-event/8000, -*) не лишает вызов DTMF, если устройство или провайдер принимает SIP INFO.
RFC 3264 и allow_ac_set
RFC 3264 допускает обмен множествами кодеков и в предложении, и в ответе:
-
предложение перечисляет форматы в порядке предпочтения (раздел 5.1); предложившая сторона должна быть готова принимать любой из них;
-
ответ должен содержать хотя бы один формат из предложения; рекомендуется отвечать подмножеством форматов предложения, в том же относительном порядке, с теми же номерами динамических форматов (раздел 6.1);
-
в ответ можно включить и форматы, которых не было в предложении, но в текущем сеансе они не используются, пока не появятся в новом предложении;
-
в течение сеанса стороны могут переключаться между согласованными форматами без нового обмена SDP.
На практике большинство устройств и провайдеров отвечают одним кодеком из предложения. Встречаются реализации, которые некорректно обрабатывают ответ множеством кодеков: например, устройство воспроизводит тишину, когда поток приходит в согласованном, но не первом кодеке ответа. Для сохранения работоспособности связки платформы с такими устройствами и провайдерами платформа поддерживает ответ одним кодеком: allow_ac_set = false (у провайдера это значение по умолчанию). Параметр задается для экземпляра роли b2b и для провайдера; для отдельной учетной записи абонента он не задается.
Медиашлюз: tubes
Медиашлюз получает для терминейшена каждого медийного плеча local и remote SDP. local приходит как шаблон: адреса, порты и специфические атрибуты подставляет сам медиашлюз.
Между терминейшенами противоположных плеч строятся tubes — пути из каждого формата одного плеча в форматы другого, в обе стороны. Пакет RTP находит вход по номеру формата (PT) и проходит через tube в противоположный поток: без перекодирования, если формат совпадает (номер формата — из SDP принимающей стороны), или с перекодированием. Tubes строятся так, чтобы транскодирования было как можно меньше: совпадающие форматы соединяются напрямую.
Поэтому смена кодека стороной в пределах согласованного множества, допустимая по RFC 3264, обслуживается без нового обмена SDP: пакеты другого формата просто идут через другой tube.
Видео
Видео в SIP-звонках платформа не записывает, поэтому, как правило, пробрасывает его между плечами без декодирования: форматы видео, в том числе неизвестные платформе, передаются как есть. Транскодинг видео выключен по умолчанию (параметр use_video_transcoding). payloads_video_offer задает состав и порядок видеоформатов в формируемых предложениях; базовых видеокодеков нет.
В настоящее время для видеосвязи в основном используются сервисы видео- и веб-конференций, в том числе сервис meet на борту платформы (ВКС), поэтому акцент развития смещен туда.
Частые вопросы
- Почему в INVITE кодеки идут в другом порядке, чем в payloads_audio_offer?
-
В предложении, передаваемом на другое плечо, впереди остаются форматы входящего SDP в их порядке; список настройки задает порядок добавляемых кодеков. Для нового вызова (IVR, конференция) порядок совпадает с настройкой,
CN/8000иtelephone-event/8000— в конце. - Как предлагать только PCMA?
-
["PCMA/8000", "-*"]. При передаче предложения на другое плечо входящие форматы сохраняются; чтобы оставить только PCMA и там, используйте["PCMA/8000", "--*"]. - Как убрать telephone-event?
-
-telephone-event/8000вpayloads_audio_offerили вopts.payloads_audioпровайдера. DTMF при этом передается SIP INFO, см. DTMF без telephone-event. - Почему вызов отклонен финальным неуспешным ответом 415 или 488?
-
У сторон нет общего кодека: например, исключены базовые кодеки, а в предложении нет ни одного кодека из списка. esg отвечает 488 Not Acceptable Here, если в SDP провайдера нет кодека из opts.payloads_audio или в предложении нет ни одного известного платформе кодека.
- Где посмотреть SDP вызова?
-
В trn-логах и на диаграмме последовательности звонка (/api/monitor/v1/trace).