Публикация Школы траблшутеров

Как отлаживать медиа-сервер с помощью ИИ-агента

Время чтения: 6 мин 40 сек
22 апреля 2026 г. Просмотров: 99

Искусственный интеллект | Олег БрагинскийМарина Строева

Основатель «Школы траблшутеров» Олег Брагинский и ученица Марина Строева разбирают, как с помощью ИИ-агента удалось стабилизировать процесс остановки сервера, устранить ошибку несовместимого кодека, восстановить отправку аудио и ликвидировать зависание.

Отладка медиа-серверов – одна из самых сложных задач в backend-разработке. Здесь нет простых ошибок «упал сервер – починил», а есть цепочки из RTP, кодеков, нативных библиотек, сетевых задержек и асинхронных событий.

Ключевая особенность процесса – вся работа велась через чат с агентом, который анализировал логи, предлагал гипотезы и вносил изменения в код. Это позволило пройти путь от «ничего не работает» до стабильной системы за несколько итераций.

Речь идёт о Go-сервере, который управляет звонками и взаимодействует с нативным медиа-стеком (через bridge и mediasoup). В системе есть несколько ключевых компонентов: обработка входящего аудио (STT), генерация синтетического аудио (TTS), и их доставка в звонок через SFU.

На практике это означает, что любая проблема может возникнуть на произвольном уровне – от кодека до сетевого соединения. Поэтому отладка строится не через догадки, а через последовательный разбор логов и проверку гипотез.

Основные задачи, которые нужно было решить:

  • восстановить исходящее аудио между агентом и пользователем
  • убедиться, что входящее аудио от пользователя к STT работает
  • стабилизировать поведение при перезапуске сервера
  • устранить зависания при обработке звонков.

Шаг №1

Первый симптом выглядел типично: пользователь говорит, STT отрабатывает, но ответа собеседника не слышно. Это сразу указывает на асимметричную проблему – входящий поток работает, исходящий нет. Промпт, с которого началась диагностика:

«Посмотри логи сервера»

Агент начал с анализа логов и быстро нашёл ключевую ошибку:

invalid params.opusMaxAverageBitrate

При попытке отправить аудио в медиа-сервер (mediasoup), параметры кодека не проходили валидацию. В результате трек просто не создавался, а система молчала. Решение оказалось точечным, агент предложил убрать неподдерживаемый параметр из конфигурации кодека:

  • удалить opusMaxAverageBitrate из audioCodecOptions
  • пересобрать нативную библиотеку

После этого в логах появилась ключевая строка:

speak_in_call pushed pcm_samples=120929

PCM-данные начали успешно передаваться в медиапайплайн.

Шаг №2

После фикса важно было не просто увидеть лог, а убедиться, что вся цепочка действительно работает. В медиа-системах часто бывает, что один этап проходит, но дальше данные теряются. Агент проверил несколько признаков корректной работы:

  • наличие STT-фраз (входящий поток жив)
  • успешный push PCM (исходящий поток отправляется)
  • отсутствие ошибок produce

Дополнительно были замечены повторяющиеся строки:

addTrack skip already_consumed

На первый взгляд это выглядело как ошибка, но агент корректно интерпретировал это как нормальное поведение при повторной синхронизации состояния. Важный момент: в отладке медиа-систем важно уметь отличать шум от реальной проблемы.

Шаг №3

Следующая проблема была сложнее. После некоторого времени работы система переставала реагировать:

  • звонки не обрабатываются
  • сообщения игнорируются
  • в логах почти пусто

Такое поведение особенно опасно, потому что выглядит как «всё работает, но ничего не происходит».

Следующий промпт был таким:

«В логах тишина, сервер не отвечает ни на что, как будто клиент умер. Найди, где зависание»

Агент начал анализ не с кода, а с архитектуры потоков. Выявил, что ключевая горутина (loopEvents), отвечающая за получение событий через long-poll, перестаёт обрабатывать события.

Причина оказалась нетривиальной:

  • внутри обработки событий держится mutex (domainPayloadMu)
  • под этим mutex вызывается нативная функция connect
  • connect может зависать из-за сети, TLS или DNS.

В итоге:

  • новые события не обрабатываются
  • mutex не освобождается
  • система «замирает»

Шаг №4

После обнаружения причины задача свелась к изменению архитектуры выполнения. Нужно было разорвать цепочку «долгая операция под lock».

Промпт:

«Вынеси connect из-под domainPayloadMu и сделай его асинхронным, чтобы long-poll не блокировался»

Агент предложил корректное решение:

  • запускать HeadlessEnsureRoomConnected в отдельной горутине
  • оставить под mutex только быстрые операции
  • обработку треков выполнять отдельно.

Это привело к тому, что long-poll перестал блокироваться, события снова начали поступать, система «ожила» без рестарта.

Шаг №5

После стабилизации рантайма всплыла ещё одна проблема – уже на этапе остановки сервера. Симптом:

State 'stop-sigterm' timed out. Killing.

То есть сервер получает SIGTERM, не успевает завершиться и systemd убивает его через приблизительно 90 секунд.

Промпт для решения:

«Почему сервер не останавливается и висит до SIGKILL?»

Агент нашёл цепочку:

planet.Shutdown()

→ stop()

→ wg.Wait()

→ loopEvents не завершился

И снова корень оказался в том же месте – зависшая горутина. Решение было таким: изменить порядок shutdown (сначала HTTP, потом внутренние сервисы), добавить таймаут на planet.Shutdown и ограничить общее время graceful shutdown.

В итоге вся отладка заняла несколько итераций, каждая из которых снимала отдельный слой проблемы. Это типично для real-time систем: одна ошибка редко бывает единственной.

В результате работы были достигнуты следующие улучшения:

  • исправлена архитектурная блокировка mutex
  • стабилизирован процесс остановки сервера
  • устранена ошибка несовместимого кодека
  • восстановлена отправка аудио в звонок
  • ликвидировано зависание long-poll.

Отладка медиа-сервера – не поиск одной ошибки, а последовательное снятие слоёв проблем. ИИ-агент в этом процессе оказался особенно полезен не как генератор кода, а как системный аналитик, который удерживает в голове сразу несколько уровней архитектуры.

Но ключевой фактор успеха – правильные промпты. Чем точнее формулируется проблема («где блокируется поток», «почему produce падает»), тем быстрее агент выходит на реальную причину, а не лечит симптомы.

Кейс показывает: даже сложные real-time системы можно отлаживать быстро, если разбивать проблему на этапы и последовательно проверять каждую гипотезу.