下載插件
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);
}
},
下載視頻
指定且只能指定,下載后的默認文件名字和文件后綴。注意,可以不指定后綴名,瀏覽器會根據(jù)數(shù)據(jù)類型自動為其匹配后綴名,但是最好指定后綴。
<a href="base64..." download="after">SAVE</a>
下載后的文件名為after.jpg
download屬性不能指定下載路徑;
當 download 屬性值為空時,下載的文件的名字和擴展名與源文件一致;當href為base64編碼的圖像數(shù)據(jù)時,則下載后文件名也是那么離譜得長。
<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>
結果
錄制
播放
下載
文章來源:http://www.zghlxwxcb.cn/news/detail-615417.html
項目代碼
https://gitee.com/yuan-hongting/video文章來源地址http://www.zghlxwxcb.cn/news/detail-615417.html
到了這里,關于Vue調用攝像頭錄制視頻和音頻并上傳給后端或下載到本地的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!