下载插件
npm install --save webm-duration-fix
代码及作用
调用摄像头
callCamera () {
let _this = this;
MediaUtils.getUserMedia(true, true, function (err, stream) {
if (err) {
throw err;
} else {
// 通过 MediaRecorder 记录获取到的媒体流
const mimeType = 'video/webm;codecs=vp8,opus';
mediaRecorder = new MediaRecorder(stream, {
// mimeType: "video/webm;codecs=vp9",
mimeType: mimeType,
});
mediaStream = stream;
var chunks = []
var video = _this.$refs.videos;
video["srcObject"] = stream;
video.play();// 播放实时画面
mediaRecorder.ondataavailable = function (e) {
mediaRecorder.blobs.push(e.data);
chunks.push(e.data);
};
mediaRecorder.blobs = [];
mediaRecorder.onstop = async () => {
recorderFile = await fixWebmDuration(new Blob(chunks, { type: mimeType }));
console.log(recorderFile);
var url = URL.createObjectURL(recorderFile)
var videosreplay = _this.$refs.videosreplay;
videosreplay.setAttribute("src", url);
console.log('url', url)
chunks = [];
if (null != stopRecordCallback) {
stopRecordCallback();
}
};
_this.record()
}
});
},
开始结束录制
record () {
if (this.recordtype == "ING") {
this.stopRecord(() => {
console.log("结束录制");
this.toggleReplayVideo()
});
}
else if (this.recordtype == "BEGIN") {
console.log("开始录制");
this.startAudio();
mediaRecorder.start();
startTime = Date.now();
this.recordtype = "ING";
}
},
对录像时长进行记录
startAudio () {
this.timer = setInterval(() => {
this.recordtime += 1000;
if (this.recordtime == 1000000) {
this.stopRecord();
}
this.second++;
if (this.second >= 60) {
this.second = 0;
this.minute = this.minute + 1;
}
if (this.minute >= 60) {
this.minute = 0;
this.hour = this.hour + 1;
}
console.log(this.recordtime)
}, 1000);
},
停止录像时终止录制器,关闭媒体流并清除时长记录定时器
stopRecord (callback) {
this.recordtype = "END";
this.showReplay = true;
stopRecordCallback = callback;
clearInterval(this.timer);
// 终止录制器
mediaRecorder.stop();
// 关闭媒体流
MediaUtils.closeStream(mediaStream);
var videosreplay = this.$refs.videosreplay;
videosreplay.onended = () => {
this.playtime = 0;
this.replayVideo = false;
clearInterval(this.playtimer);
};
videosreplay.onclick = () => {
this.showReplay = !this.showReplay;
};
},
回放
toggleReplayVideo () {
console.log('播放中...')
this.replayVideo = !this.replayVideo;
this.showReplay = false;
var videosreplay = this.$refs.videosreplay;
if (this.replayVideo) {
videosreplay.play().catch(err => {
this.$message.error(err.message);
console.log(err);
});
this.playtimer = setInterval(() => {
this.playtime += 1000;
}, 1000);
} else {
videosreplay.pause();
clearInterval(this.playtimer);
}
},
下载视频
指定且只能指定,下载后的默认文件名字和文件后缀。注意,可以不指定后缀名,浏览器会根据数据类型自动为其匹配后缀名,但是最好指定后缀。
<a href="base64..." download="after">SAVE</a>
下载后的文件名为after.jpg
download属性不能指定下载路径;
当 download 属性值为空时,下载的文件的名字和扩展名与源文件一致;当href为base64编码的图像数据时,则下载后文件名也是那么离谱得长。
<a href="base64..." download>SAVE</a>
下载后的文件名为data_image_jpeg;base64,… .jpg
download () {
var url = URL.createObjectURL(recorderFile)
console.log("URLLLLLL", url)
const a = document.createElement("a");
document.body.appendChild(a);
a.style.display = "none";
a.href = url;
if (this.fileName) {
a.download = this.fileName + ".mp4";
} else {
a.download = new Date() + ".mp4";
}
a.click();
window.URL.revokeObjectURL(url);
},
下载或上传给后端
submit () {
let that = this;
console.log(recorderFile)
// 下载
this.download()
let file = new File(
[recorderFile],
"msr-" + new Date().toISOString().replace(/:|\./g, "-") + ".mp4",
{
type: "video/mp4",
}
);
let config = {
headers: { "Content-Type": "multipart/form-data" }
}
console.log('file', file)
const formdata = new FormData()
formdata.append("file", file);
// 传给后端
// axios.post('/video', formdata, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } },) //请求头要为表单
// .then(response => {
// console.log('video', response.data);
// this.yy_score = parseInt(response.data.data + 0.5)
// that.progress = response.data.data * 1.0 / 23 * 100
// })
// .catch(function (error) {
// that.$message({
// message: error,
// type: 'error'
// });
// console.log(error);
// })
},
var MediaUtils = {
/**
* 获取用户媒体设备(处理兼容的问题)
* @param videoEnable {boolean} - 是否启用摄像头
* @param audioEnable {boolean} - 是否启用麦克风
* @param callback {Function} - 处理回调
*/
getUserMedia: function (videoEnable, audioEnable, callback) {
navigator.getUserMedia =
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia ||
window.getUserMedia;
var constraints = { video: videoEnable, audio: audioEnable };
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
callback(false, stream);
})
["catch"](function (err) {
callback(err);
});
} else if (navigator.getUserMedia) {
navigator.getUserMedia(
constraints,
function (stream) {
callback(false, stream);
},
function (err) {
callback(err);
}
);
} else {
callback(new Error("Not support userMedia"));
}
},
/**
* 关闭媒体流
* @param stream {MediaStream} - 需要关闭的流
*/
closeStream: function (stream) {
if (typeof stream.stop === "function") {
stream.stop();
} else {
let trackList = [stream.getAudioTracks(), stream.getVideoTracks()];
for (let i = 0; i < trackList.length; i++) {
let tracks = trackList[i];
if (tracks && tracks.length > 0) {
for (let j = 0; j < tracks.length; j++) {
let track = tracks[j];
if (typeof track.stop === "function") {
track.stop();
}
}
}
}
}
},
};
var startTime, mediaRecorder, mediaStream, stopRecordCallback, recorderFile;
页面完整代码
<template>
<div>
<video id="video" autoplay ref="videos" style="width: 400px;height: 400px;" muted></video>
<video style="width: 400px;height: 400px;" id="videosreplay" src="" ref="videosreplay"></video>
<button @click="callCamera()">开始录制</button>
<button @click="record()">结束录制</button>
<button @click="submit()">下载或上传</button>
</div>
</template>
<script>
import axios from 'axios'
import fixWebmDuration from 'webm-duration-fix'
export default {
name: "Test",
data () {
return {
progress: 0,
replayVideo: false,
recordtype: "BEGIN",
showReplay: true,
timer: 0,
recordtime: 0,
second: 0,
minute: 0,
hour: 0,
playtime: 0,
playtimer: 0,
yy_score: 0,
cnt_sum: 0,
ansMaxTime: 0,
ansBeginTime: 0,
ansMaxBeginTime: 0,
}
},
methods: {
// 调用摄像头
callCamera () {
let _this = this;
MediaUtils.getUserMedia(true, true, function (err, stream) {
if (err) {
throw err;
} else {
// 通过 MediaRecorder 记录获取到的媒体流
const mimeType = 'video/webm;codecs=vp8,opus';
mediaRecorder = new MediaRecorder(stream, {
// mimeType: "video/webm;codecs=vp9",
mimeType: mimeType,
});
mediaStream = stream;
var chunks = []
var video = _this.$refs.videos;
video["srcObject"] = stream;
video.play();// 播放实时画面
mediaRecorder.ondataavailable = function (e) {
mediaRecorder.blobs.push(e.data);
chunks.push(e.data);
};
mediaRecorder.blobs = [];
mediaRecorder.onstop = async () => {
recorderFile = await fixWebmDuration(new Blob(chunks, { type: mimeType }));
console.log(recorderFile);
var url = URL.createObjectURL(recorderFile)
var videosreplay = _this.$refs.videosreplay;
videosreplay.setAttribute("src", url);
console.log('url', url)
chunks = [];
if (null != stopRecordCallback) {
stopRecordCallback();
}
};
_this.record()
}
});
},
record () {
if (this.recordtype == "ING") {
this.stopRecord(() => {
console.log("结束录制");
this.toggleReplayVideo()
});
}
else if (this.recordtype == "BEGIN") {
console.log("开始录制");
this.startAudio();
mediaRecorder.start();
startTime = Date.now();
this.recordtype = "ING";
}
},
// 对录像时长进行记录
startAudio () {
this.timer = setInterval(() => {
this.recordtime += 1000;
if (this.recordtime == 1000000) {
this.stopRecord();
}
this.second++;
if (this.second >= 60) {
this.second = 0;
this.minute = this.minute + 1;
}
if (this.minute >= 60) {
this.minute = 0;
this.hour = this.hour + 1;
}
console.log(this.recordtime)
}, 1000);
},
// 停止录像时终止录制器,关闭媒体流并清除时长记录定时器
stopRecord (callback) {
this.recordtype = "END";
this.showReplay = true;
stopRecordCallback = callback;
clearInterval(this.timer);
// 终止录制器
mediaRecorder.stop();
// 关闭媒体流
MediaUtils.closeStream(mediaStream);
var videosreplay = this.$refs.videosreplay;
videosreplay.onended = () => {
this.playtime = 0;
this.replayVideo = false;
clearInterval(this.playtimer);
};
videosreplay.onclick = () => {
this.showReplay = !this.showReplay;
};
},
// 回放
toggleReplayVideo () {
console.log('播放中...')
this.replayVideo = !this.replayVideo;
this.showReplay = false;
var videosreplay = this.$refs.videosreplay;
if (this.replayVideo) {
videosreplay.play().catch(err => {
this.$message.error(err.message);
console.log(err);
});
this.playtimer = setInterval(() => {
this.playtime += 1000;
}, 1000);
} else {
videosreplay.pause();
clearInterval(this.playtimer);
}
},
// 下载视频
download () {
var url = URL.createObjectURL(recorderFile)
console.log("URLLLLLL", url)
const a = document.createElement("a");
document.body.appendChild(a);
a.style.display = "none";
a.href = url;
if (this.fileName) {
a.download = this.fileName + ".mp4";
} else {
a.download = new Date() + ".mp4";
}
a.click();
window.URL.revokeObjectURL(url);
},
// 下载或上传
submit () {
let that = this;
console.log(recorderFile)
// 下载
this.download()
let file = new File(
[recorderFile],
"msr-" + new Date().toISOString().replace(/:|\./g, "-") + ".mp4",
{
type: "video/mp4",
}
);
let config = {
headers: { "Content-Type": "multipart/form-data" }
}
console.log('file', file)
const formdata = new FormData()
formdata.append("file", file);
// 传给后端
// axios.post('/video', formdata, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } },) //请求头要为表单
// .then(response => {
// console.log('video', response.data);
// this.yy_score = parseInt(response.data.data + 0.5)
// that.progress = response.data.data * 1.0 / 23 * 100
// })
// .catch(function (error) {
// that.$message({
// message: error,
// type: 'error'
// });
// console.log(error);
// })
},
}
}
var MediaUtils = {
/**
* 获取用户媒体设备(处理兼容的问题)
* @param videoEnable {boolean} - 是否启用摄像头
* @param audioEnable {boolean} - 是否启用麦克风
* @param callback {Function} - 处理回调
*/
getUserMedia: function (videoEnable, audioEnable, callback) {
navigator.getUserMedia =
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia ||
window.getUserMedia;
var constraints = { video: videoEnable, audio: audioEnable };
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices
.getUserMedia(constraints)
.then(function (stream) {
callback(false, stream);
})
["catch"](function (err) {
callback(err);
});
} else if (navigator.getUserMedia) {
navigator.getUserMedia(
constraints,
function (stream) {
callback(false, stream);
},
function (err) {
callback(err);
}
);
} else {
callback(new Error("Not support userMedia"));
}
},
/**
* 关闭媒体流
* @param stream {MediaStream} - 需要关闭的流
*/
closeStream: function (stream) {
if (typeof stream.stop === "function") {
stream.stop();
} else {
let trackList = [stream.getAudioTracks(), stream.getVideoTracks()];
for (let i = 0; i < trackList.length; i++) {
let tracks = trackList[i];
if (tracks && tracks.length > 0) {
for (let j = 0; j < tracks.length; j++) {
let track = tracks[j];
if (typeof track.stop === "function") {
track.stop();
}
}
}
}
}
},
};
var startTime, mediaRecorder, mediaStream, stopRecordCallback, recorderFile;
</script>
结果
录制
播放
下载
文章来源:https://www.toymoban.com/news/detail-615417.html
项目代码
https://gitee.com/yuan-hongting/video文章来源地址https://www.toymoban.com/news/detail-615417.html
到了这里,关于Vue调用摄像头录制视频和音频并上传给后端或下载到本地的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!