Микрофоны, скриншаринг и локальное видео: как Voximplant Web SDK управляет медиа в браузере


    Сегодня я раскажу про модуль Hardware в Voximplant Web SDK. Этот модуль пришел на смену старой системе управления аудио- и видеоустройствами. Но сначала – немного об управлении устройствами в WebRTC-стеке и зачем все это нужно.

    Редко, но у конечных пользователей бывает несколько микрофонов. Или бывает несколько динамиков: например обычные динамики и bluetooth-наушники; или динамик телефона и громкая связь для смартфона.

    А вот две камеры в современном мире бывают очень часто. На планшетах и телефонах: обычная и фронтальная. На ноутбуках: встроенная и получше внешняя. И так далее и тому подобное. Пользователь может сильно растроиться, если по дефолту будет выбран не тот набор устройств и он никак не сможет их изменить. Это первое применение управлению медиа в WebRTC.

    Второе применение — это тонкие настройки аудио и видео. Всякие эхоподавления, шумоподавления, установка разрешения видео, фреймрейта, баланс белого и прочего, что конкретно ваш браузер поддерживает.



    Раньше для управлениями устройствами мы предоставляли интерфейс constraints и разработчику нужно было прописывать все ограничения и параметры запроса медиа самостоятельно. Вот небольшой пример полностью настроенного запроса аудио и видео:

    const myConstraints = {
        audio:{
            sampleSize: 16,
            channelCount: 2,
            noiseSuppression: true,
            echoCancellation: false
        },
        video:{
        width: { min: 640, ideal: 1920, max: 1920 },
        height: { min: 400, ideal: 1080 },
        aspectRatio: 1.777777778,
        frameRate: { max: 30 },
        facingMode: { exact: "user" }
      }
    };
    

    Это дает неимоверную гибкость при настройке аудио и видео, однако всегда есть «НО». Как показала статистика опроса поддержки, клиенты в основном не пользовались этой опцией, так как мы дружелюбная платформа и сами приучаем пользователей к простоте. Те же, кто рискнул использовать это, нередко отстреливали себе все чуть выше колена, так как браузеры имеют в этой точке пространства легкую несовместимость.

    Теперь ясно, как мы дошли до жизни такой. Пора перейти к делу: бегло осмотрим модуль; для детального прочтения я оставлю ссылку на документацию на нашем сайте.

    Входной точкой в этот модуль является StreamManager. Исторически сложилось [картинка со слоном.jpg], что многие части нашего Web SDK — синглтоны, и этот класс не исключение: получить инстанс можно при помощи функции get(). Для этого есть море причин, но об этом в другой раз, пожалуй.

    const streamManager = VoxImplant.Hardware.StreamManager.get();
    

    С помощью StreamManager можно включить или выключить локальное видео и
    получить медиастримы для него – по сути, это всё. Входная точка не очень большая, если смотреть на внешние интерфейсы.

    (async () => {
      try{
        console.log('[WebSDK] Включаем локальное видео');
        await streamManager.showLocalVideo();
        console.log('[WebSDK] Выключаем локальное видео');
        await streamManager.hideLocalVideo();
        console.log('[WebSDK] Операция по подмигиванию диодом успешно завершена!');
      } catch(e){
        console.log('[WebSDK] Что-то пошло не так. Возможно, никакой камеры не существует?!'); 
        console.error(e);
      }
    })();
    

    Интересный факт о локальном видео: локальное видео никак не передается собеседнику. Например, пользователю можно показать картинку в HD, а передавать 320*240 или наоборот, если локальное видео прячется в углу. Чуть ниже будет о том, как провернуть такой фокус.

    В StreamManager есть 3 события:

    • DevicesUpdated — вызывается когда пользователь подключил/отключил микрофон или камеру;
    • MediaRendererAdded — добавлено новое локальное видео или скриншаринг с превью;
    • MediaRendererRemoved — удалено локальное видео или скриншаринг с превью.

    Функцией getLocalMediaRenderers() полезно получать ссылки на DOM-элементы с локальным видео, если вы не сохранили объект себе.

    streamManager.getLocalMediaRenderers().forEach(renderer => {
      cont elementOfDOM = renderer.element;
      elementOfDOM.addEventListener('on42',doSomething,true);
    });
    

    Перейдем к настройкам видео (самое вкусное, следите за руками). Внезапно CameraManager. Опять же, синглтон со скучной функцией get():

    const cameraManager= VoxImplant.Hardware.CameraManager.get();
    

    Какие настройки мы вообще можем установить? Давайте посмотрим на интерфейс CameraParams:

    • strict — значение true скажет браузеру буквально: «Я знаю, что я делаю, не пытайся что-то починить, если все пошло не так!». Если false, браузер смиренно поправит кривые настройки;
    • cameraId — выбор устройства камеры. Можно выбрать из списка, который отдает getInputDevices()

      const allMyDevices = await cameraManager.CameraManager.getInputDevices();
    • frameRate – отвечает непосредственно за частоту кадров. Эта опция помогает либо экономить трафик, либо поднимать качество. Я бы не рекомендовал устанавливать это значение выше 30 и ниже 10 без предварительного теста у каждого пользователя и фоллбека. Вне этого диапазона работают не все камеры.
    • facingModetrue флипнет картинку по горизонтали. Опция достаточно нишевая, т.к. для вывода локального видео мы уже делаем флип картинки.

    Еще 3 опции отвечают за размер видео:

    • можно пользоваться либо videoQuality (мы подготовили еще и enum VideoQuality с набором модных разрешений)
    • или можно выставить размеры вручную в пикселях через frameHeight и frameWidth

    Вернемся к CameraManager и применим настройки! Внутри есть 2 геттера и 2 сеттера настроек:


    Все что с «Default» — настройки «по умолчанию», как не трудно догадаться. Они будут использоваться для получения локального видео, для новых входящих и исходящих звонков.
    А теперь обещаный фокус:

    console.log('[WebSDK] Позволим пользователю почувствовать легкую ностальгию без вреда для окружающих.');
    await cameraManager.setDefaultVideoSettings({
        frameWidth:320,
        frameHeight:240,
        frameRate:12
    });
    await streamManager.showLocalVideo();
    cameraManager.setDefaultVideoSettings({
        frameWidth:640,
        frameHeight:480,
        frameRate:25
    });
    const newCall = client.call('mySchoolFriendBoris');
    

    Пара с Call в названии немного сложнее. Эти функции созданы, чтобы получать и устанавливать настройки в процессе звонка, который уже идет. При изменении настроек, возникнет событие CallEvents.Updated.

    console.log('[WebSDK] Теперь очередь для ностальгии у Бориса.');
    cameraManager.setCallVideoSettings(newCall,{
        frameWidth:320,
        frameHeight:240,
        frameRate:12
    });
    newCall.on(VoxImplant.CallEvents.Updated,e => {
      console.log('[WebSDK] Ностальгия Борису успешно доставлена.');
    });
    

    Осталось две функции CameraManager. Очень мощные, но сложные. В enum VideoQuality есть три интересных значения:

    • VIDEO_QUALITY_HIGH;
    • VIDEO_QUALITY_MEDIUM;
    • VIDEO_QUALITY_LOW.

    Закономерный вопрос: «Игорь! Если Web SDK знает лучшее, худшее и среднее качество, то почему нет метода для получения списка поддерживаемых веб-камерой разрешений?!» Цимес в том, что не знает.

    И для того, чтобы узнать, нужно буквально перебрать все возможные разрешения. Что удалось получить — поддерживаются. Звучит довольно просто, но на деле это занимает до нескольких минут. Поэтому мы не можем сделать это в инициализации WebSDK, например. Чтобы вы могли сделать это в момент, максимально комфортный для пользователя – если вообще захотите это делать – и существует testResolutions. Результат работы функции неплохо было бы сохранить в localStorage и позже грузить через loadResolutionTestResult при перезагрузке страницы:

    console.log('[WebSDK] Откинтесь на спинку кресла и отдохните, пока WebSDK опрашивает вашу камеру.');
    const testResults = await cameraManager.testResolutions();
    localStorage.setItem('defaultCameraResolutionTestResults',JSON.stringify(testResolutions));
    

    И последнее по списку, но самое популярное: AudioDeviceManager. Класс очень сильно похож на CameraManager. Только для звука свои настройки отражены в интерфейсе AudioParams:

    • stricttrue отвечает за неукоснительное следование вашей воле;
    • inputId — выбор микрофона. Список всех микрофонов можно получить через AudioDeviceManager.getInputDevices;
    • outputId — выбор динамиков. Работает эта опция только в Chrome, остальные браузеры ее проигнорируют. Получить список устройств можно через getOutputDevices;
    • noiseSuppression — подавление шумов. По умолчанию, подавление шумов включено и отлично работает. Но может возникнуть частичное пропадание голоса, если пользователь работает в помещении, где очень много говорят, например в колл-центре. Фильтр просто может немного ошибаться и резать лишнее. Если у вас есть проблемы подобного характера, стоит выставить эту опцию в false;
    • echoCancellation — убирает эхо от микрофона. Ее стоит отключать вместе с предыдущей опцией;
    • autoGainControl — включает встроеный в операционную систему механизм автоматической регулировки усиления микрофона. Опция не имеет побочных эффектов, но ее работа сильно зависит от операционной системы и оборудования. Иногда она может просто не работать и усиление будет постоянным, что тоже неплохо.
    Voximplant
    159,18
    Облачная платформа голосовой и видеотелефонии
    Поделиться публикацией

    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое