TGViewer
Виталий и Платформа Виталий и Платформа @web_platform · 1.81K subscribers
Post #237 1.55K
Как пошарить системное видео/аудио в расширение браузера

Недавно увидел в одном расширении в Chrome интересное решение, расковырял исходники, решил поделиться.

Функциональность расширения — запись звука, сохранение в файл и дальнейшая отправка его в сервис транскрибации.

Так вот интересный момент как именно расширение получает аудио. Допустим вы открываете во браузере Google Meet, десктопный Zoom или любой другой апп для созвонов. Начинаете созвон, приложение/браузер стримит туда-сюда звук и видео. И этот поток направляется в браузерное расширение. В Chrome при этом надо дать явное разрешение и затем появляется уведомление, что происходит шаринг вкладки или всей системы в расширение (аналогичным образом вы обычно шарите свой экран в веб-приложение, а тут веб-приложением выступает браузерное расширение).

Как это работает под капотом. Там Manifest V3 приложение. Микрофон получается через getUserMedia из (Media Capture and Streams API). А вот звук стрима берётся через getDisplayMedia — это уже Screen Capture API, в рамках которой браузер показывает системный диалог "чем поделиться". Таким образом и получается что угодно шарить в браузерное расширение.

Потом два независимых потока, микрофон и собеседник, нужно свести в один. И делается это Web Audio API:


const ctx = new AudioContext();
const mix = ctx.createMediaStreamDestination();

ctx.createMediaStreamSource(micStream).connect(micGain).connect(mix);
ctx.createMediaStreamSource(tabStream).connect(tabGain).connect(mix);

const combined = mix.stream; // снова обычный MediaStream, его и пишем


То есть по сути Web Audio используется как микшер. В процессе там заодно можно что-то дополнительно обработать, например, усилить микрофон, а на выходе получить единый поток.

Ок, поток получили, теперь задача его записать. Для этого используется MediaStream Recording API и интерфейс MediaRecorder. Пишется не одним куском в конце, а порциями: start(timeslice) отдаёт данные кусками по ходу записи, и если что-то пойдёт не так на втором часу разговора, то всё не будет потеряно. У WebM при этом есть давняя болячка — MediaRecorder не проставляет длительность в заголовок, и готовый файл выглядит «бесконечным» для плееров и сервера. Лечится это пост-обработкой блоба, дописыванием правильных метаданных уже после остановки.

То есть кратенько: Media Capture and Streams и Screen Capture добывают MediaStream (с устройств или с экрана), Web Audio умеет этот поток обрабатывать и микшировать, а MediaStream Recording берёт готовый MediaStream на вход и сериализует его в сжатые байты — Blob в webm/mp4/ogg, которые уже можно сохранить на устройство или отправить в какой-то внешний сервис дальше.

И ещё один интересный момент уже про само браузерное расширение. Вообще оно работает в service worker, у которого нет доступа к DOM и всем веб-API. И чтоб это обойти используется Chrome-специфичное chrome.offscreen, которое создаёт полноценную "невидимую" страницу, где и выполняется код.

#Лаборатория_веб_платформы

@web_platform | Поддержать блог 💙
  • 🔥 13
  • 👍 2
  • ❤ 1
More from @web_platform
  1. Aug 14, 2026Мой воркфлоу с ИИшками сейчас У меня счас несколько подписок: • антропик 20$ (для разработ…
  2. Jul 13, 2026Hermes vs OpenClaw В комметах к прошлому посту @fogrew спросил, чем Hermes отличается от O…
  3. Jul 8, 2026Недавний инцидент с ДЦ сподвиг меня причесать всё на VPS с ботом-дайджестёром. Раньше было…
  4. Jul 2, 2026вчера мой ботик @web_platform_pulse_bot не прислал новости, а всё потому что кукольный теа…
  5. Jun 22, 2026btw там интересная система в репе, используются git submodules: в .gitmodules указывается…
  6. Jun 22, 20264 мая -> 20 июня, столько провисел мой pr в zed до мерджа зато теперь тема superset доступ…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →