TIP
前几节我们都是使用的默认的音视频设备来进行媒体数据的输出,我们这一节就将系统中可以使用的音频输入、输出设备及视频输入设备列举出来并进行切换。
前言
大家好,我是小鑫同学。一位从事过Android开发、混合开发,现在长期从事前端开发的编程爱好者,我觉得在编程之路上最重要的是知识的分享,所谓三人行必有我师。所以我开始在社区持续输出我所了解到、学习到、工作中遇到的各种编程知识,欢迎有想法、有同感的伙伴加我fe-xiaoxin微信交流~
写作背景:
前几节我们都是使用的默认的音视频设备来进行媒体数据的输出,我们这一节就将系统中可以使用的音频输入、输出设备及视频输入设备列举出来并进行切换。
涉及 API:
枚举设备的 API 是 navigator.mediaDevices.enumerateDevices()
,它将会异步回调给我们一个 MediaDeviceInfo 数组,每个 MediaDeviceInfo 将包含一个设备的 deviceId ,设备名称 label ,设备的类型 kind 。设备类型包括:audioinput(音频输入),audiooutput(音频输出),videoinput(视频输入)。
// 获取当前计算机可列举的音频输入|输出|视频输入设备
navigator.mediaDevices
.enumerateDevices()
.then((devices) => {
for (const device of devices) {
if (device.kind === "audioinput") {
audioInputDevices.push(device);
} else if (device.kind === "audiooutput") {
audioOutputDevices.push(device);
} else if (device.kind === "videoinput") {
videoDevices.push(device);
}
}
})
.then(() => {
resolve({ audioInputDevices, audioOutputDevices, videoDevices });
});
// 获取当前计算机可列举的音频输入|输出|视频输入设备
navigator.mediaDevices
.enumerateDevices()
.then((devices) => {
for (const device of devices) {
if (device.kind === "audioinput") {
audioInputDevices.push(device);
} else if (device.kind === "audiooutput") {
audioOutputDevices.push(device);
} else if (device.kind === "videoinput") {
videoDevices.push(device);
}
}
})
.then(() => {
resolve({ audioInputDevices, audioOutputDevices, videoDevices });
});
注:当用户选择完设备后最好支持保存配置,省去下次调整,因为用户的偏好和设备时候故障都会影响到用户的实际使用。
HTMLMediaElement.setSinkId()
API 是一个实验功能,可以通过传入一个音频输出设备的 deviceId 来切换不同的音频输出设备:
const handleChangeAudioOutputDevice = (value: string) => {
selectedAudioOutputDevice.value = value;
video
// @ts-ignore
.value!.setSinkId(value)
.then(() => {
console.log(`音频输出设备设置成功${value}`);
})
.catch((error: Error) => {
console.log(error);
});
};
const handleChangeAudioOutputDevice = (value: string) => {
selectedAudioOutputDevice.value = value;
video
// @ts-ignore
.value!.setSinkId(value)
.then(() => {
console.log(`音频输出设备设置成功${value}`);
})
.catch((error: Error) => {
console.log(error);
});
};
注:实际开发时在 HTMLMediaElement 接口中没能找到 setSinkId 函数,但功能正常,这里先使用 @ts-ignore
将下一行的错误忽略。
启动设备:
在这里我们要扩展约束条件,以支持使用默认选择的各设备:
const openDevice = () => {
const constraints: MediaStreamConstraints = {
audio: {
deviceId: selectedAudioInputDevice.value
? { exact: selectedAudioInputDevice.value }
: undefined,
},
video: {
deviceId: selectedVideoDevice.value
? { exact: selectedVideoDevice.value }
: undefined,
},
};
...
};
const openDevice = () => {
const constraints: MediaStreamConstraints = {
audio: {
deviceId: selectedAudioInputDevice.value
? { exact: selectedAudioInputDevice.value }
: undefined,
},
video: {
deviceId: selectedVideoDevice.value
? { exact: selectedVideoDevice.value }
: undefined,
},
};
...
};
注:
- 强烈推荐使用 TypeScript 来开发,并指定真实的类型来得到优秀的代码提示;
- 其他步骤同前几节的方式,也可以看文末的完整代码。
完整代码:Resolution.vue
结语:
我们通过 enumerateDevices 的到了系统中已存在的音频输入、输出设备及视频的输入设备,在视频会议等软件中也需要支持多种设备的切换来满足不同的场景。
如果看完觉得有收获,欢迎点赞、评论、分享支持一下。你的支持和肯定,是我坚持写作的动力~
最后可以关注我@小鑫同学。欢迎点此扫码加我微信fe-xiaoxin交流,共同进步(还可以帮你fix🐛)~