如果我們的電腦有兩個攝影機,就會有切換裝置的需求,今天我們就來加入這個功能
在 index.html 增加兩個 select 用來選擇設備
<div>
<label>切換麥克風:</label>
<select id="audioSource"></select>
</div>
<div>
<label>切換攝影機:</label>
<select id="videoSource"></select>
</div>
在 main.js 增加切換設備會使用到的標籤
// 切換設備
const audioInputSelect = document.querySelector('select#audioSource')
const videoSelect = document.querySelector('select#videoSource')
const selectors = [audioInputSelect, videoSelect]
讀取設備並將設備加入 select 的選項中
// 將讀取到的設備加入到 select 標籤中
function gotDevices(deviceInfos) {
// Handles being called several times to update labels. Preserve values.
const values = selectors.map((select) => select.value)
selectors.forEach((select) => {
while (select.firstChild) {
select.removeChild(select.firstChild)
}
})
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i]
const option = document.createElement('option')
option.value = deviceInfo.deviceId
if (deviceInfo.kind === 'audioinput') {
option.text =
deviceInfo.label || `microphone ${audioInputSelect.length + 1}`
audioInputSelect.appendChild(option)
}else if (deviceInfo.kind === 'videoinput') {
option.text = deviceInfo.label || `camera ${videoSelect.length + 1}`
videoSelect.appendChild(option)
} else {
console.log('Some other kind of source/device: ', deviceInfo)
}
}
selectors.forEach((select, selectorIndex) => {
if (
Array.prototype.slice
.call(select.childNodes)
.some((n) => n.value === values[selectorIndex])
) {
select.value = values[selectorIndex]
}
})
}
// 讀取設備
navigator.mediaDevices
.enumerateDevices()
.then(gotDevices)
.catch((err) => {
console.error('Error happens:', err)
})
選取設備後切換標籤並將切換後的媒體傳送給對方,這邊使用 replaceTrack
去替換 track 不需要重新做協商
audioInputSelect.onchange = () => {
switchDevice(true)
}
videoSelect.onchange = () => {
switchDevice(false)
}
async function switchDevice(isAudio) {
if (!peerConn) return
const audioSource = audioInputSelect.value
const videoSource = videoSelect.value
const constraints = {
audio: { deviceId: audioSource ? { exact: audioSource } : undefined },
video: { deviceId: videoSource ? { exact: videoSource } : undefined },
}
const stream = await navigator.mediaDevices.getUserMedia(constraints)
let track = stream[isAudio ? 'getAudioTracks' : 'getVideoTracks']()[0]
let sender = peerConn.getSenders().find(function (s) {
return s.track.kind == track.kind
})
console.log('found sender:', sender)
sender.replaceTrack(track)
localStream = stream
localVideo.srcObject = stream
}