获取设备的支持情况
代码语言:javascript复制var types = [
"video/webm",
"audio/webm",
"video/webm;codecs=vp8",
"video/webm;codecs=daala",
"video/webm;codecs=h264",
"audio/webm;codecs=opus",
"video/mpeg"
];
for (var i in types) {
console.log(types[i] ":" (MediaRecorder.isTypeSupported(types[i]) ? "支持" : "不支持"));
}
获取可用的视频源
代码语言:javascript复制desktopCapturer.getSources({
types: ['screen']
}, (error, sources) => {
if (error) throw error
for (let source of sources) {
console.info(source);
}
});
定义全局变量
代码语言:javascript复制let audioStream;
let vedioStream;
let mediaRecorder;
let recordedChunks = [];
获取音频流
代码语言:javascript复制function getAudioStream() {
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(function (stream) {
audioStream = stream;
getVedioStream()
stream.onended = () => {
console.log('Micro audio ended.')
}
})
.catch(function (error) {
console.log('getUserMedia() failed.')
});
}
或者
代码语言:javascript复制function getAudioStream() {
navigator.webkitGetUserMedia(
{audio: true, video: false},
function (stream) {
console.log('Received audio stream.')
audioStream = stream;
getVedioStream()
stream.onended = () => {
console.log('Micro audio ended.')
}
},
function () {
console.log('getUserMedia() failed.')
}
);
}
获取视频流
sourceid可以通过获取可用的录制源返回source.id获取
代码语言:javascript复制function getVedioStream() {
navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
// chromeMediaSourceId: sourceid,
maxWidth: window.screen.width,
maxHeight: window.screen.height
}
}
}).then(function (stream) {
vedioStream = stream;
let liveVideo = document.querySelector("video");
liveVideo.srcObject = stream;
liveVideo.muted = true;
liveVideo.play();
startRecord();
}).catch(function (err) {
console.log('The following error occured: ' err);
})
}
或者
代码语言:javascript复制function getVedioStream() {
navigator.webkitGetUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
// chromeMediaSourceId: sourceid,
maxWidth: window.screen.width,
maxHeight: window.screen.height
}
}
}, function (stream) {
vedioStream = stream;
let liveVideo = document.querySelector("video");
liveVideo.srcObject = stream;
liveVideo.muted = true;
liveVideo.play();
startRecord();
}, function () {
})
}
录制带声音
代码语言:javascript复制function startRecord() {
if (audioStream) {
let audioTracks = audioStream.getAudioTracks();
vedioStream.addTrack(audioTracks[0]);
}
mediaRecorder = new MediaRecorder(vedioStream);
mediaRecorder.ondataavailable = (event) => {
if (event.data && event.data.size > 0) {
recordedChunks.push(event.data)
}
};
mediaRecorder.onstart = () => {
console.log("开始录制")
};
mediaRecorder.onstop = () => {
console.log("停止录制")
};
mediaRecorder.start();
}
停止录制
代码语言:javascript复制// 结束录制
function stopRecord() {
if (mediaRecorder) {
mediaRecorder.stop();
} else {
alert("还没有开始。");
}
}
保存
代码语言:javascript复制function formatLength(str, length) {
str = '';
if (str.length < length)
return formatLength('0' str, length)
else
return str
}
function getnowstr() {
var now = new Date();
var year = now.getFullYear(); //得到年份
var month = formatLength(now.getMonth(), 2);//得到月份
var date = formatLength(now.getDate(), 2);//得到日期
var hour = formatLength(now.getHours(), 2);//得到小时
var minu = formatLength(now.getMinutes(), 2);//得到分钟
var all_time = year "-" month "-" date "_" hour "-" minu;
return all_time;
}
// 保存视频
function saveRecord() {
let blob = new Blob(recordedChunks, {type: "video/x-matroska;codecs=avc1,opus"});
let url = URL.createObjectURL(blob);
let a = document.createElement('a');
var all_time = getnowstr();
document.body.appendChild(a);
a.style = 'display: none';
a.href = url;
a.download = all_time 'video.webm';
a.click()
setTimeout(function () {
document.body.removeChild(a);
window.URL.revokeObjectURL(url)
}, 100)
}
播放
代码语言:javascript复制function playRecord() {
let video = document.querySelector('video')
video.controls = true;
video.muted = false;
let blob = new Blob(recordedChunks, {type: "video/x-matroska;codecs=avc1,opus"})
video.src = window.URL.createObjectURL(blob)
video.play();
}
整体代码
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>Document</title>
</head>
<body>
<video id="live"></video>
<div class="toolbar">
<span class="timer"></span>
<button id="startOrStop">开始</button>
<button id="save">保存</button>
<button id="play">播放</button>
</div>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
#live {
width: 100%;
height: 0;
flex-grow: 1;
}
.toolbar {
width: 100%;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.toolbar button {
margin-left: 6px;
margin-right: 6px;
padding: 10px 16px;
border-radius: 4px;
background-color: blue;
color: white;
}
.timer {
width: 60px;
text-align: center;
}
</style>
<script>
let n = 0;
let timer;
let audioStream;
let vedioStream;
let mediaRecorder;
let recordedChunks = [];
const startOrStopButton = document.getElementById("startOrStop");
const saveButton = document.getElementById("save");
const playButton = document.getElementById("play");
startOrStopButton.addEventListener("click", startOrStopRecord);
saveButton.addEventListener("click", saveRecord);
playButton.addEventListener("click", playRecord);
function getAudioStream() {
navigator.mediaDevices.getUserMedia({audio: true, video: false})
.then(function (stream) {
audioStream = stream;
getVedioStream()
stream.onended = () => {
console.log('Micro audio ended.')
}
})
.catch(function (error) {
console.log('getUserMedia() failed.')
});
}
function getVedioStream() {
navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
maxWidth: window.screen.width,
maxHeight: window.screen.height
}
}
}).then(function (stream) {
vedioStream = stream;
let liveVideo = document.querySelector("video");
liveVideo.src = null;
liveVideo.srcObject = vedioStream;
liveVideo.controls = false;
liveVideo.muted = true;
liveVideo.play();
}).catch(function (err) {
console.log('The following error occured: ' err);
})
}
// 显示录制的秒数
function startTimer() {
const timerEl = document.querySelector(".timer");
n = 0;
timerEl.textContent = `${n}s`;
timer = setInterval(() => {
n = 1;
timerEl.textContent = `${n}s`;
}, 1000);
}
// 开始录制
function startRecord() {
if (audioStream) {
let audioTracks = audioStream.getAudioTracks();
vedioStream.addTrack(audioTracks[0]);
}
mediaRecorder = new MediaRecorder(vedioStream);
mediaRecorder.ondataavailable = (event) => {
if (event.data && event.data.size > 0) {
recordedChunks.push(event.data)
}
};
mediaRecorder.onstart = () => {
console.log("开始录制")
};
mediaRecorder.onstop = () => {
console.log("停止录制")
};
mediaRecorder.start();
}
// 结束录制
function startOrStopRecord() {
if (startOrStopButton.innerHTML === "开始") {
recordedChunks = [];
startTimer();
startRecord();
startOrStopButton.innerHTML = "停止"
} else {
clearInterval(timer);
if (mediaRecorder) {
mediaRecorder.stop();
//停止视频音频流
// vedioStream.getVideoTracks()[0].stop();
// audioStream.getAudioTracks()[0].stop();
}
startOrStopButton.innerHTML = "开始"
}
}
function formatLength(str, length) {
str = '';
if (str.length < length)
return formatLength('0' str, length);
else
return str
}
function getnowstr() {
let now = new Date();
let year = now.getFullYear(); //得到年份
let month = formatLength(now.getMonth(), 2);//得到月份
let date = formatLength(now.getDate(), 2);//得到日期
let hour = formatLength(now.getHours(), 2);//得到小时
let minu = formatLength(now.getMinutes(), 2);//得到分钟
let time_all = year "-" month "-" date "_" hour ":" minu;
return time_all;
}
// 保存视频
function saveRecord() {
let blob = new Blob(recordedChunks, {type: "video/x-matroska;codecs=avc1,opus"});
let url = URL.createObjectURL(blob);
let a = document.createElement('a');
var all_time = getnowstr();
document.body.appendChild(a);
a.style = 'display: none';
a.href = url;
a.download = all_time 'vedio.webm';
a.click()
setTimeout(function () {
document.body.removeChild(a);
window.URL.revokeObjectURL(url)
}, 100)
}
function playRecord() {
if (playButton.innerHTML === "播放") {
let liveVideo = document.querySelector('video');
liveVideo.controls = true;
liveVideo.muted = false;
let blob = new Blob(recordedChunks, {type: "video/x-matroska;codecs=avc1,opus"});
liveVideo.srcObject = null;
liveVideo.src = window.URL.createObjectURL(blob);
liveVideo.play();
playButton.innerHTML = "取消播放"
} else {
let liveVideo = document.querySelector("video");
liveVideo.src = null;
liveVideo.srcObject = vedioStream;
liveVideo.controls = false;
liveVideo.muted = true;
liveVideo.play();
playButton.innerHTML = "播放"
}
}
getAudioStream();
</script>
</body>
</html>
工具类
为了方便使用封装成了工具类方便使用
代码语言:javascript复制/**
*自动录屏模块*录制桌面
*
* @class Recorder
*/
class Recorder {
constructor(path) {
this.mediaOutputPath = path;
}
/**
*开始录制
*
* @memberof Recorder
*/
startRecord = () => {
/* 要获取桌面音频必须设置audio约束如下 */
this.getVedioStream().then(vedioStream => {
this.getAudioStream().then((audioStream) => {
vedioStream.addTrack(audioStream.getAudioTracks()[0])//注!此处添加麦克风音轨无效
this.startRecorder(vedioStream);
});
}).catch(err => {
this.getUserMediaError(err);
});
};
/**
*获取麦克风音频流
*
* @memberof Recorder
*/
getAudioStream = () => {
return navigator.mediaDevices.getUserMedia({audio: true, video: false})
};
/**
*获取屏幕视频流
*
* @memberof Recorder
*/
getVedioStream = () => {
return navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
maxWidth: window.screen.width,
maxHeight: window.screen.height
}
}
})
};
/**
*获取媒体源失败
*
* @memberof Recorder
*/
getUserMediaError = (err) => {
console.log('mediaError', err);
};
getUserAudioError = (err) => {
console.log('audioError', err);
};
/**
*开始视频录制
*
* @memberof Recorder
*/
startRecorder = (stream) => {
this.recorder = new MediaRecorder(stream);
this.recorder.start();
this.recorder.ondataavailable = event => {
let blob = new Blob([event.data], {
type: 'video/webm'
});
this.saveMedia(blob);
};
};
formatLength = (str, length) => {
str = '';
if (str.length < length)
return this.formatLength('0' str, length)
else
return str
};
getnowstr = () => {
var now = new Date();
var year = now.getFullYear(); //得到年份
var month = this.formatLength(now.getMonth(), 2);//得到月份
var date = this.formatLength(now.getDate(), 2);//得到日期
var hour = this.formatLength(now.getHours(), 2);//得到小时
var minu = this.formatLength(now.getMinutes(), 2);//得到分钟
var all_time = year "-" month "-" date "_" hour "-" minu;
return all_time;
};
/**
*数据转换并保存成MP4
*
* @memberof Recorder
*/
saveMedia = (blob) => {
let reader = new FileReader();
let _t = this;
var filename = this.mediaOutputPath this.getnowstr() "_vedio.webm";
reader.onload = function () {
let buffer = Buffer.from(reader.result);
const fs = require('fs')
fs.writeFile(filename, buffer, {}, (err, res) => {
if (err) {
console.error(err);
return
}
})
};
reader.readAsArrayBuffer(blob);
};
/**
*停止录制视频
*
* @memberof Recorder
*/
stopRecord = () => {
this.recorder.stop();
}
}
exports.Recorder = Recorder;
调用方式
代码语言:javascript复制const {Recorder} = require('./utils/Recorder');
let my_recorder = new Recorder("/Users/zhangjian/Downloads/");
// 开始录制
my_recorder.startRecord();
// 结束录制自动保存文件
if (my_recorder) {
my_recorder.stopRecord();
}