Appearance
浏览器调用输入输出接口
navigator.mediaDevices
可以通过浏览器调用媒体设备,例如输入设备:麦克风、摄像头,输出设备:显示器等。其中getUserMedia
调用输入设备的接口,getDisplayMedia
调用输出接口(开启屏幕共享)。
例子
实现一个录屏并上传的功能。
html
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
http-equiv="X-UA-Compatible"
content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button onclick="getUserDevices()">获取摄像头和麦克风</button>
<button onclick="getDisplayDevices()">获取显示器和扬声器权限</button>
<video></video>
<script>
....查看js部分
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
http-equiv="X-UA-Compatible"
content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button onclick="getUserDevices()">获取摄像头和麦克风</button>
<button onclick="getDisplayDevices()">获取显示器和扬声器权限</button>
<video></video>
<script>
....查看js部分
</script>
</body>
</html>
js
js
const video = document.querySelector("video");
// getUserMedia获取输入设备
async function getUserDevices() {
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
console.log(await navigator.mediaDevices.getSupportedConstraints());
try {
const data = await navigator.mediaDevices.getUserMedia({
// 获取输入设备-麦克风 的调用权限
audio: true,
// 获取输入设备-摄像头 的调用权限
video: true,
});
video.srcObject = data;
video.onloadedmetadata = () => {
video.play();
};
} catch (error) {
console.log("拒绝了调用请求.");
}
} else {
Promise.race("浏览器不支持调用设备接口!");
}
}
// getDisplayMedia获取输出设备
async function getDisplayDevices() {
if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {
try {
const data = await navigator.mediaDevices.getDisplayMedia({
// 获取输出设备-扬声器 的调用权限
audio: true,
// 获取输出设备-显示器 的调用权限
video: true,
});
video.srcObject = data;
video.onloadedmetadata = () => {
video.play();
};
} catch (error) {
console.log("拒绝了调用请求.");
}
} else {
Promise.race("浏览器不支持调用设备接口!");
}
}
const video = document.querySelector("video");
// getUserMedia获取输入设备
async function getUserDevices() {
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
console.log(await navigator.mediaDevices.getSupportedConstraints());
try {
const data = await navigator.mediaDevices.getUserMedia({
// 获取输入设备-麦克风 的调用权限
audio: true,
// 获取输入设备-摄像头 的调用权限
video: true,
});
video.srcObject = data;
video.onloadedmetadata = () => {
video.play();
};
} catch (error) {
console.log("拒绝了调用请求.");
}
} else {
Promise.race("浏览器不支持调用设备接口!");
}
}
// getDisplayMedia获取输出设备
async function getDisplayDevices() {
if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) {
try {
const data = await navigator.mediaDevices.getDisplayMedia({
// 获取输出设备-扬声器 的调用权限
audio: true,
// 获取输出设备-显示器 的调用权限
video: true,
});
video.srcObject = data;
video.onloadedmetadata = () => {
video.play();
};
} catch (error) {
console.log("拒绝了调用请求.");
}
} else {
Promise.race("浏览器不支持调用设备接口!");
}
}
将文件流合并成二进制文件
要将 srcObject
的媒体流数据上传到服务端并保存为视频文件,你需要先将媒体流数据转换为视频文件的格式,然后将该文件上传到服务器。以下是一般的步骤:
在客户端,使用
MediaRecorder
API 将srcObject
的媒体流数据录制为视频文件。MediaRecorder
提供了对媒体流进行录制的功能。你可以设置录制的输出格式和编解码器等参数。示例代码如下:
js
// srcObject为源数据,也就是音频
const mediaRecorder = new MediaRecorder(srcObject);
// 保存的数据片段
const chunks = [];
// 有点像可写流一样,每次有数据流过我们只需要保存好数据即可。
mediaRecorder.ondataavailable = (event) => {
// 每次有数据流过就保存数据片段
chunks.push(event.data);
};
// 停止录屏时,将
mediaRecorder.onstop = () => {
const blob = new Blob(chunks, { type: "video/webm" });
// 将 blob 上传到服务器或进行其他操作
};
mediaRecorder.start();
// srcObject为源数据,也就是音频
const mediaRecorder = new MediaRecorder(srcObject);
// 保存的数据片段
const chunks = [];
// 有点像可写流一样,每次有数据流过我们只需要保存好数据即可。
mediaRecorder.ondataavailable = (event) => {
// 每次有数据流过就保存数据片段
chunks.push(event.data);
};
// 停止录屏时,将
mediaRecorder.onstop = () => {
const blob = new Blob(chunks, { type: "video/webm" });
// 将 blob 上传到服务器或进行其他操作
};
mediaRecorder.start();
WARNING
一定要调用 mediaRecorder.start(),否则 ondataavailable 事件不会触发!!
录制一段时间后调用 mediaRecorder.stop() 停止录制并触发 onstop 事件
将录制的媒体数据存储为一个 Blob 对象。通过在
ondataavailable
事件中收集录制的数据块,最后将它们合并为一个 Blob 对象。通过 Ajax 请求发送给后端。
停止浏览器调用输入输出设备
通过调用mediaStream.getTracks().forEach(track => track.stop())
方法停止浏览器调用输入输出设备。
mediaStream.getTracks()
方法将返回一个MediaStreamTrack
对象的数组,表示当前MediaStream
中的所有轨道(音频轨道和视频轨道)。通过遍历这个数组,并调用每个轨道的stop()
方法,你可以停止浏览器调用输入输出设备。
在你的代码中,你可以在停止录制后的recordData.stop()
之后添加以下代码:
javascript
mediaStream.getTracks().forEach((track) => track.stop());
mediaStream.getTracks().forEach((track) => track.stop());
这将停止浏览器调用输入输出设备,释放资源。