问题
I am building a simple WebRTC app with OpenTok. I need to be able to select camera, audio input and audio output. Currently that doesn't seem easily possible.
See opentok-hardware-setup
https://github.com/opentok/opentok-hardware-setup.js/issues/18
I am loading OpenTok in my index.html
file
and opentok-hardware-setup.js
.
All looks great and I can select microphone and camera BUT not the speaker out aka audiooutput
.
<script src="https://static.opentok.com/v2/js/opentok.min.js"></script>
From the console, I tried
OT.getDevices((err, devices) => { console.debug(devices)});
and observed that you can't get the audioOutput
(4) [{…}, {…}, {…}, {…}]
0: {deviceId: "default", label: "Default - Built-in Microphone", kind: "audioInput"}
1: {deviceId: "b183634b059298f3692aa7e5871e6a463127701e21e320742c48bda99acdf925", label: "Built-in Microphone", kind: "audioInput"}
2: {deviceId: "4b441035a4db3c858c65c30eabe043ae1967407b3cc934ccfb332f0f6e33a029", label: "Built-in Output", kind: "audioInput"}
3: {deviceId: "05415e116b36584f848faeef039cd06e5290dde2e55db6895c19c8be3b880d91", label: "FaceTime HD Camera", kind: "videoInput"}
length
:4 __proto__:Array(0)
whereas you can get them using navigator.mediaDevices.enumerateDevices()
Any pointers?
回答1:
Disclosure, I'm an employee at TokBox :). OpenTok does not currently provide a way to specify the audio output device. This is still an experimental API and only works in Chrome. When the API is standardised and has wider browser support we will make it easier.
In the meantime, it's pretty easy to do this using native WebRTC. There is a good sample for this at https://webrtc.github.io/samples/src/content/devices/multi/ the source code can be found at https://github.com/webrtc/samples/blob/gh-pages/src/content/devices/multi/js/main.js
In summary you use the enumerateDevices
method as you found. Then you use the setSinkId()
method on the video element https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/setSinkId
You can get access to the videoElement
by listening to the videoElementCreated
event on the subscriber like so:
subscriber.on('videoElementCreated', (event) => {
if (typeof event.element.sinkId !== 'undefined') {
event.element.setSinkId(deviceId)
.then(() => {
console.log('successfully set the audio output device');
})
.catch((err) => {
console.error('Failed to set the audio output device ', err);
});
} else {
console.warn('device does not support setting the audio output');
}
});
回答2:
So,
The answer gave by @Adam Ullman is not valid anymore since there is a separate audio element created alongside the video element preventing us to use the setSinkId
method of the video element.
I found a solution consisting in finding the audio element from the video one and using its own setSinkId
.
Code:
const subscriber_videoElementCreated = async event => {
const videoElem = event.element;
const audioElem = Array.from(videoElem.parentNode.childNodes).find(child => child.tagName === 'AUDIO');
if (typeof audioElem.sinkId !== 'undefined') {
try {
await audioElem.setSinkId(deviceId);
} catch (err) {
console.log('Could not update speaker ', err);
}
}
};
来源:https://stackoverflow.com/questions/50645017/how-to-select-audiooutput-with-opentok