В Web SDK отсутствует возможность получить список устройств "audio output"

Axel

Member
Здравствуйте.

Как получить список устройств пользователя, доступных для воспроизведения аудио? WebSDK API позволяет получить только список audio input и video input устройств, но не audio output.

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

Code:
const printMediaDeviceInfo = (id, type, label) => {
    console.log(`Type: "${type}", Label: "${label}", ID: "${id}"`);
};

Flashphoner.init();

Flashphoner.getMediaDevices(null, true).then(list => {
    console.log('\nDevices detected by FP WebSDK\n\n');

    list.audio.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
    list.video.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
});

navigator.mediaDevices.enumerateDevices().then(devices => {
    console.log('\nDevices detected by native WebRTC API \n\n');

    devices.forEach(device => {
        printMediaDeviceInfo(device.deviceId, device.kind, device.label);
    });
});
Результаты:

Code:
Devices detected by native WebRTC API

Type: "audioinput", Label: "Default", ID: "default"
Type: "audioinput", Label: "Built-in Audio Analog Stereo", ID: "9c374fa20770c3b193340ddfe5122aca6695a7430d2c8f9ac172d127236c4788"
Type: "audioinput", Label: "Webcam C170 Analog Mono", ID: "0bd4706e657f2905bda8a35f2d985c6393a1a5e97b32e32728189bc696e65f0d"
Type: "videoinput", Label: "Webcam C170 (046d:082b)", ID: "8e294b7ea4d22b45c175aa842562dd4b3053dab1963cae5f36e751b844dad721"
Type: "audiooutput", Label: "Default", ID: "default"
Type: "audiooutput", Label: "Built-in Audio Analog Stereo", ID: "676b337a40d4b5023b16d7ddaf58448df5e85a10e30438166c62fe89fccf793f"

Devices detected by FP WebSDK

Type: "mic", Label: "Default", ID: "default"
Type: "mic", Label: "Built-in Audio Analog Stereo", ID: "9c374fa20770c3b193340ddfe5122aca6695a7430d2c8f9ac172d127236c4788"
Type: "mic", Label: "Webcam C170 Analog Mono", ID: "0bd4706e657f2905bda8a35f2d985c6393a1a5e97b32e32728189bc696e65f0d"
Type: "camera", Label: "Webcam C170 (046d:082b)", ID: "8e294b7ea4d22b45c175aa842562dd4b3053dab1963cae5f36e751b844dad721"
Как видно, в списке устройств, полученных через нативное API, присутствуют устройства для воспроизведения аудио:

Code:
Type: "audiooutput", Label: "Default", ID: "default"
Type: "audiooutput", Label: "Built-in Audio Analog Stereo", ID: "676b337a40d4b5023b16d7ddaf58448df5e85a10e30438166c62fe89fccf793f"
Однако, получить информацию о таких устройствах посредством Flashphoner WebSDK не представляется возможным. Что делать в таком случае?

В этом контексте, видится некоторая нестыковка в WebSDK API: в методе "Session.createStream()" можно указать "options.constraints.audio.outputId", который будет использоваться для воспроизведения аудио. Однако, без возможности получить этот ID, как сказано выше, сделать это проблематично.
 

Max

Administrator
Staff member
Добрый день.
Пример в документации Web SDK для работы с трансляцией с возможностью выбора медиа устройств устарел и не содержит актуальную информацию в полной мере. В ближайшее время он будет обновлен. Однако, в документации по WCS есть описание выбора устройств вывода звука на этой странице
На Github вы можете ознакомиться с новой версией Media Devices (с элементом audioOutput). Для загрузки последние версии WebSDK доступны на странице WebSDK release notes.
 
Last edited:

Axel

Member
В таком случае, возникает новая проблема: как получить все устройства пользователя?

Как было сказано выше, вызов "Flashphoner.getMediaDevices(null, true)" не возвращает output-устройства. Вы порекомендовали использовать для этого явную передачу константы "MEDIA_DEVICE_KIND.OUTPUT" (кстати, группы констант "MEDIA_DEVICE_KIND" нет в документации к Web SDK) - это сработало. Я пошёл дальше, и попробовал использовать "MEDIA_DEVICE_KIND.ALL", надеясь получить список всех устройств, однако, в результирующем списке отсутствует устройство камеры.

Получается, что вызовы вида "Flashphoner.getMediaDevices(null, true)" и "Flashphoner.getMediaDevices(null, true, Flashphoner.constants.MEDIA_DEVICE_KIND.ALL)" - не эквивалентны по части возвращаемых данных, хотя вроде как должны таковыми являться. Делаю такой вывод, так как отсутвие третьего аргумента и установка его в "MEDIA_DEVICE_KIND.ALL" выглядят логически непротиворечивыми.

Код для STR:

Code:
const printMediaDeviceInfo = (id, type, label) => {
    console.log(`Type: "${type}", Label: "${label}", ID: "${id}"`);
};

Flashphoner.init();

Flashphoner.getMediaDevices(null, true).then(list => {
    console.log('\nAll devices detected by FP Web SDK (without "MEDIA_DEVICE_KIND.ALL" option)\n\n');

    list.audio.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
    list.video.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
});

Flashphoner.getMediaDevices(null, true, Flashphoner.constants.MEDIA_DEVICE_KIND.ALL).then(list => {
    console.log('\nAll devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.ALL" option)\n\n');

    list.audio.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
});

Flashphoner.getMediaDevices(null, true, Flashphoner.constants.MEDIA_DEVICE_KIND.OUTPUT).then(list => {
    console.log('\nOutput devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.OUTPUT" option)\n\n');

    list.audio.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
});

Flashphoner.getMediaDevices(null, true, Flashphoner.constants.MEDIA_DEVICE_KIND.INPUT).then(list => {
    console.log('\nInput devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.INPUT" option)\n\n');

    list.audio.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
});

navigator.mediaDevices.enumerateDevices().then(devices => {
    console.log('\nDevices detected by native WebRTC API \n\n');

    devices.forEach(device => printMediaDeviceInfo(device.deviceId, device.kind, device.label));
});
Результаты:

Code:
Devices detected by native WebRTC API

Type: "audioinput", Label: "Default", ID: "default"
Type: "audioinput", Label: "Built-in Audio Analog Stereo", ID: "9c374fa20770c3b193340ddfe5122aca6695a7430d2c8f9ac172d127236c4788"
Type: "audioinput", Label: "Webcam C170 Analog Mono", ID: "0bd4706e657f2905bda8a35f2d985c6393a1a5e97b32e32728189bc696e65f0d"
Type: "videoinput", Label: "Webcam C170 (046d:082b)", ID: "8e294b7ea4d22b45c175aa842562dd4b3053dab1963cae5f36e751b844dad721"
Type: "audiooutput", Label: "Default", ID: "default"
Type: "audiooutput", Label: "Built-in Audio Analog Stereo", ID: "676b337a40d4b5023b16d7ddaf58448df5e85a10e30438166c62fe89fccf793f"

All devices detected by FP Web SDK (without "MEDIA_DEVICE_KIND.ALL" option)

Type: "mic", Label: "Default", ID: "default"
Type: "mic", Label: "Built-in Audio Analog Stereo", ID: "9c374fa20770c3b193340ddfe5122aca6695a7430d2c8f9ac172d127236c4788"
Type: "mic", Label: "Webcam C170 Analog Mono", ID: "0bd4706e657f2905bda8a35f2d985c6393a1a5e97b32e32728189bc696e65f0d"
Type: "camera", Label: "Webcam C170 (046d:082b)", ID: "8e294b7ea4d22b45c175aa842562dd4b3053dab1963cae5f36e751b844dad721"

All devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.ALL" option)

Type: "mic", Label: "Default", ID: "default"
Type: "mic", Label: "Built-in Audio Analog Stereo", ID: "9c374fa20770c3b193340ddfe5122aca6695a7430d2c8f9ac172d127236c4788"
Type: "mic", Label: "Webcam C170 Analog Mono", ID: "0bd4706e657f2905bda8a35f2d985c6393a1a5e97b32e32728189bc696e65f0d"
Type: "speaker", Label: "Default", ID: "default"
Type: "speaker", Label: "Built-in Audio Analog Stereo", ID: "676b337a40d4b5023b16d7ddaf58448df5e85a10e30438166c62fe89fccf793f"

Output devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.OUTPUT" option)

Type: "speaker", Label: "Default", ID: "default"
Type: "speaker", Label: "Built-in Audio Analog Stereo", ID: "676b337a40d4b5023b16d7ddaf58448df5e85a10e30438166c62fe89fccf793f"

Input devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.INPUT" option)

Type: "mic", Label: "Default", ID: "default"
Type: "mic", Label: "Built-in Audio Analog Stereo", ID: "9c374fa20770c3b193340ddfe5122aca6695a7430d2c8f9ac172d127236c4788"
Type: "mic", Label: "Webcam C170 Analog Mono", ID: "0bd4706e657f2905bda8a35f2d985c6393a1a5e97b32e32728189bc696e65f0d"
Очевидно, что как воркэраунд, можно сделать несколько вызовов "Flashphoner.getMediaDevices()" с разными аргументами, и смержить результаты, фильтруя их по ID устройства и типу. Но такое решение выглядит как костыль, и, я подозреваю, является следствием бага в коде, так как "ALL" должно возвращать всё, а не часть, которую ещё надо корректно определить и запросить отдельно: сейчас это камера, судя по результатам теста, но кто знает, как будет потом? Но даже если это не баг, а фича, то в таком случае, должна быть константа для получения устройства типа "камера", но её нет.

В нативном WebRTC API, к слову, такой проблемы нет: при вызове "navigator.mediaDevices.enumerateDevices()" возвращается список всех устройств.

Что посоветуете по этой проблеме?
 

Max

Administrator
Staff member
Добрый день.
По вашим вопросам создали внутренние карточки (WCS-2379 и WCS-2380). О результатах сообщим вам позже в этой теме.
 

Max

Administrator
Staff member
Добрый день.
Если необходимо получить список всех устройств, требуется один вызов Flashphoner.getMediaDevices() и два вызова list.audio.forEach и list.video.ForEach:
Code:
const printMediaDeviceInfo = (id, type, label) => {
console.log(`Type: "${type}", Label: "${label}", ID: "${id}"`);
};

Flashphoner.init();

Flashphoner.getMediaDevices(null, true, Flashphoner.constants.MEDIA_DEVICE_KIND.ALL).then(list => {
    console.log('\nAll devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.ALL" option)\n\n');
    list.audio.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
    list.video.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
});
Список устройств будет выглядеть так (пример из браузера Chrome под Windows 10):
Code:
All devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.ALL" option)

Type: "mic", Label: "Default - Микрофон (Conexant ISST Audio)", ID: "default"
Type: "mic", Label: "Микрофон (HD Webcam C615) (046d:082c)", ID: "3f07e968645f944e2b492455e16839b837459b670895034b824470997c62edd9"
Type: "mic", Label: "Микрофон (Conexant ISST Audio)", ID: "6024aa9722465b359804570df6796e4380a0f4e3687dc77dd3307d71d18351e1"
Type: "mic", Label: "Микрофон (ManyCam Virtual Microphone)", ID: "7f547a40084f6b79f8d8cefe1d345bed6541c7dc4d989096a2f982f2ee264400"
Type: "speaker", Label: "Default - Наушники (Conexant ISST Audio)", ID: "default"
Type: "speaker", Label: "Наушники (Conexant ISST Audio)", ID: "6e3a02b2757fa1a862fe0c38cc9901fdae1a96ffc171489d13714e0530cbf12f"
Type: "speaker", Label: "Динамик (Conexant ISST Audio)", ID: "888ce197e3dbe33d68c51c46e37dfee6534cd98523ef7c0c8aa6a80cb71288d3"
Type: "camera", Label: "Logitech HD Webcam C615 (046d:082c)", ID: "90c7fe9d4682fabe894a82ff1b116b87e3b1150dabf42c7476e15a3e4cb1542d"
Type: "camera", Label: "ManyCam Virtual Webcam", ID: "6905b4f6fae4827ae8b6e35662ace043ecc620232b469927400b32137cfe6f18"
Type: "camera", Label: "HP HD Camera (05c8:03b1)", ID: "740b089e8490fbf954f961fd07ef26f801bf07d9410558037a680c7b9d50649b"
Пожалуйста, уточните, чем именно неудобен в использовании такой вариант.
 

Axel

Member
Моя ошибка: при копипастинге примера забыл про обработку видео-устройств - потерялась стройка "list.video.forEach(...". Спасибо, всё работает, вопрос по поводу получения всех устройств с указанием "MEDIA_DEVICE_KIND.ALL" снят.

Однако ещё один вопрос остался актуальным. Вызовы вида "Flashphoner.getMediaDevices(null, true)" и "Flashphoner.getMediaDevices(null, true, Flashphoner.constants.MEDIA_DEVICE_KIND.ALL)" возвращают разные данные: с "MEDIA_DEVICE_KIND.ALL" в списке будут устройства speaker, а без этой константы - их не будет. На мой взгляд, оба вызова должны быть эквивалентными (вызов без фильтра, и с фильтром "ALL"), но по факту, это не так. Так и задумано, и это фича?

Код для STR:

Code:
const printMediaDeviceInfo = (id, type, label) => {
    console.log(`Type: "${type}", Label: "${label}", ID: "${id}"`);
};

Flashphoner.init();

Flashphoner.getMediaDevices(null, true, Flashphoner.constants.MEDIA_DEVICE_KIND.ALL).then(list => {
    console.log('\nAll devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.ALL" option)\n\n');

    list.audio.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
    list.video.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
});

Flashphoner.getMediaDevices(null, true).then(list => {
    console.log('\nAll devices detected by FP Web SDK (without "MEDIA_DEVICE_KIND.ALL" option)\n\n');

    list.audio.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
    list.video.forEach(device => printMediaDeviceInfo(device.id, device.type, device.label));
});
Результаты:

Code:
All devices detected by FP Web SDK (with "MEDIA_DEVICE_KIND.ALL" option)

Type: "mic", Label: "Default", ID: "default"
Type: "mic", Label: "Built-in Audio Analog Stereo", ID: "9c374fa20770c3b193340ddfe5122aca6695a7430d2c8f9ac172d127236c4788"
Type: "mic", Label: "Webcam C170 Analog Mono", ID: "0bd4706e657f2905bda8a35f2d985c6393a1a5e97b32e32728189bc696e65f0d"
Type: "speaker", Label: "Default", ID: "default"
Type: "speaker", Label: "Built-in Audio Analog Stereo", ID: "676b337a40d4b5023b16d7ddaf58448df5e85a10e30438166c62fe89fccf793f"
Type: "camera", Label: "Webcam C170 (046d:082b)", ID: "8e294b7ea4d22b45c175aa842562dd4b3053dab1963cae5f36e751b844dad721"

All devices detected by FP Web SDK (without "MEDIA_DEVICE_KIND.ALL" option)

Type: "mic", Label: "Default", ID: "default"
Type: "mic", Label: "Built-in Audio Analog Stereo", ID: "9c374fa20770c3b193340ddfe5122aca6695a7430d2c8f9ac172d127236c4788"
Type: "mic", Label: "Webcam C170 Analog Mono", ID: "0bd4706e657f2905bda8a35f2d985c6393a1a5e97b32e32728189bc696e65f0d"
Type: "camera", Label: "Webcam C170 (046d:082b)", ID: "8e294b7ea4d22b45c175aa842562dd4b3053dab1963cae5f36e751b844dad721"
 

Max

Administrator
Staff member
Так и задумано, и это фича?
Да, при вызове без указания типа перечисляются устройства ввода.
 

Axel

Member
Было бы неплохо указать это явно в документации: сейчас там написано "Get available local media devices", что подразумевает все устройства, а не только input.
 
Top