如果我们的电脑有两个摄影机,就会有切换装置的需求,今天我们就来加入这个功能
在 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
}
前言 State跟Props这两个东西其实不会很难,却很重要,基本上你在写React的日子里都会一直...
ButterKnife可以让我们在宣告元件时之後不用再打findViewById这行,可以帮忙省下宣...
我围绕在「基本版」电脑已经二十多天了 ... 一开始先试着熟悉 Lua 语法,接着玩转电脑周边设备,...
今天使用的范例出自高焕堂老师的书《AI机器人、蓝芽与Android整合开发技术》,需要完整程序码请参...
想要在网路上取得台股最新的股价有许多种方式,其中一种免费的方式就是直接向证交所网站取得股价资料,这次...