当前位置:网站首页>web资源部署后navigator获取不到mediaDevices实例的解决方案(navigator.mediaDevices为undefined)
web资源部署后navigator获取不到mediaDevices实例的解决方案(navigator.mediaDevices为undefined)
2022-07-05 04:05:00 【乐辞】
问题
最近在开发中,有一个功能需要实现录制屏幕的功能,我这边使用了recordrtc库,在过程中本地开发都没有问题,部署到线上环境时出现 navigator.mediaDevices为undefined,查找了不少文章和官方文章才得以解决
原因和解决方案
由于浏览器的安全策略导致了这个问题,目前经尝试,在以下几种情况中 navigator.mediaDevices 可以正常使用
1. 地址为localhost:// 访问时
2. 地址为https:// 时
3. 为文件访问file:///
// 注:如果有其他方案欢迎指正
另附上 recordrtc 使用源码以供参考 (参考源码使用了element UI)
index.vue
<template>
<div>
<button @click="handleScreenRecord">开始录屏</button>
<el-dialog
style="max-width: 60%"
v-model="screenRecorder.dialogVisible"
:before-close="handleClose"
top="0"
>
<Screenrecording
:isSubmitting="screenRecorder.isSubmitting"
@submit="recordedVideoSubmit"
/>
</el-dialog>
</div>
</template>
<script>
import { defineComponent, reactive } from "vue";
import Screenrecording from "./ScreenRecorder.vue";
export default defineComponent({
components: {
Screenrecording,
},
setup() {
const screenRecorder = reactive({
fileurl: "",
dialogVisible: false,
title: "",
isSubmitting: false,
});
const handleScreenRecord = async () => {
screenRecorder.dialogVisible = true;
};
const recordedVideoSubmit = async (file) => {
screenRecorder.isSubmitting = true;
try {
// 拿到录制后的文件 file,这里是处理 file 的业务逻辑
console.log("file", file);
} catch (error) {
// notify.error(error.message)
}
screenRecorder.isSubmitting = false;
};
const handleClose = () => {
screenRecorder.dialogVisible = false;
};
return {
screenRecorder,
handleScreenRecord,
recordedVideoSubmit,
handleClose,
};
},
});
</script>
ScreenRecorder.vue
<template>
<div class="h-recorder-wrapper">
<el-card class="row">
<div class="col-12">
<video
ref="video"
style="width: 100%"
loop
controls
autoplay
playsinline
/>
</div>
<div>
<el-button
ref="startRecord"
@click="startRecord"
:disabled="isSubmitting"
v-show="!recording && !startedBefore"
type="primary"
>
record
</el-button>
<el-button
ref="recordAgain"
@click="startRecord"
v-show="!recording && startedBefore"
:disabled="isSubmitting"
type="primary"
>
recordAgain
</el-button>
<el-button
ref="stopRecord"
v-show="recording"
@click="stopRecord"
type="primary"
>
finish
</el-button>
<el-button
v-show="!recording && startedBefore"
@click="handleRecordedVideo(video.blob)"
type="green"
:loading="isSubmitting"
>
submit
</el-button>
</div>
</el-card>
</div>
</template>
<script>
import RecordRTC from "recordrtc";
export default {
name: "screen-recorder",
langPrefix: "components.recorder",
data() {
return {
recorder: null,
stream: null,
video: null,
recording: false,
startedBefore: false,
};
},
props: {
isSubmitting: {
type: Boolean,
required: true,
},
},
methods: {
handleRecordedVideo() {
this.$emit("submit", {
file: this.video.blob,
});
},
startRecord() {
this.captureScreen((screen) => {
this.video.srcObject = screen;
this.recorder = RecordRTC(screen, {
type: "video",
});
this.recorder.startRecording();
this.recorder.screen = screen;
this.startedBefore = this.recording = true;
});
},
stopRecord() {
this.recorder.stopRecording(this.stopRecordingCallback);
this.recording = false;
},
async stopRecordingCallback() {
this.video.src = this.video.srcObject = null;
const blob = this.recorder.getBlob();
this.video.src = URL.createObjectURL(blob);
this.video.blob = blob;
this.recorder.screen.stop();
this.recorder.destroy();
},
getStream() {
if (navigator.mediaDevices.getDisplayMedia) {
return navigator.mediaDevices.getDisplayMedia({
video: {
displaySurface: "monitor",
logicalSurface: true,
cursor: "always",
},
});
}
},
invokeGetDisplayMedia(success, error) {
let displaymediastreamconstraints = {
video: {
displaySurface: "monitor",
logicalSurface: true,
cursor: "always",
},
};
displaymediastreamconstraints = {
video: true,
};
if (navigator.mediaDevices.getDisplayMedia) {
navigator.mediaDevices
.getDisplayMedia(displaymediastreamconstraints)
.then(success)
.catch(error);
} else {
navigator
.getDisplayMedia(displaymediastreamconstraints)
.then(success)
.catch(error);
}
},
addStreamStopListener(stream, callback) {
stream.addEventListener(
"ended",
() => {
callback();
callback = () => {};
},
false
);
stream.addEventListener(
"inactive",
() => {
callback();
callback = () => {};
},
false
);
stream.getTracks().forEach((track) => {
track.addEventListener(
"ended",
() => {
callback();
callback = () => {};
},
false
);
track.addEventListener(
"inactive",
() => {
callback();
callback = () => {};
},
false
);
});
},
captureScreen(callback) {
this.invokeGetDisplayMedia(
(screen) => {
this.addStreamStopListener(screen, () => {
this.$refs.stopRecord.click();
});
callback(screen);
},
(error) => {
console.error(error);
}
);
},
},
mounted() {
this.video = this.$refs.video;
},
};
</script>
recordrtc库参考文档:https://github.com/muaz-khan/RecordRTC
边栏推荐
- Official announcement! The third cloud native programming challenge is officially launched!
- 10种寻址方式之间的区别
- 长度为n的入栈顺序的可能出栈顺序
- 技术教程:如何利用EasyDSS将直播流推到七牛云?
- Interview summary: This is a comprehensive & detailed Android interview guide
- Threejs Internet of things, 3D visualization of farms (II)
- MindFusion.Virtual Keyboard for WPF
- [array]566 Reshape the matrix - simple
- Longyuan war "epidemic" 2021 network security competition web easyjaba
- Pyqt5 displays file names and pictures
猜你喜欢
Wechat applet development process (with mind map)
北京程序员的真实一天!!!!!
Soul 3: what is interface testing, how to play interface testing, and how to play interface automation testing?
线上故障突突突?如何紧急诊断、排查与恢复
Timing manager based on C #
kubernetes集群之调度系统
What is test development? Why do so many companies hire test developers now?
Threejs implements labels and displays labels with custom styles
Threejs rendering obj+mtl model source code, 3D factory model
我国算力规模排名全球第二:计算正向智算跨越
随机推荐
open graph协议
[understand series after reading] 6000 words teach you to realize interface automation from 0 to 1
[punch in questions] integrated daily 5-question sharing (phase III)
Ctfshow 2022 Spring Festival welcome (detailed commentary)
基于TCP的移动端IM即时通讯开发仍然需要心跳保活
官宣!第三届云原生编程挑战赛正式启动!
Open graph protocol
Clickpaas low code platform
English essential vocabulary 3400
Basic function learning 02
Installation of postman and postman interceptor
Threejs factory model 3DMAX model obj+mtl format, source file download
Wechat applet development process (with mind map)
BDF application - topology sequence
WGS84 coordinate system, web Mercator, gcj02 coordinate system, bd09 coordinate system - brief introduction to common coordinate systems
“金九银十”是找工作的最佳时期吗?那倒未必
Laravel8 export excel file
Use threejs to create geometry, dynamically add geometry, delete geometry, and add coordinate axes
IronXL for . NET 2022.6
Threejs Internet of things, 3D visualization of farms (I)