当前位置:网站首页>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
边栏推荐
- 长度为n的入栈顺序的可能出栈顺序种数
- DFS and BFS concepts of trees and graphs
- Redis之Jedis如何使用
- 在线SQL转Excel(xls/xlsx)工具
- Pyqt pyside custom telescopic menu bar sharing (including tutorial)
- NEW:Devart dotConnect ADO.NET
- 已解决(sqlalchemy+pandas.read_sql)AttributeError: ‘Engine‘ object has no attribute ‘execution_options‘
- kubernetes集群之调度系统
- Behavior perception system
- Ctfshow 2022 Spring Festival welcome (detailed commentary)
猜你喜欢

ActiveReportsJS 3.1 VS ActiveReportsJS 3.0

Operation flow of UE4 DMX and grandma2 onpc 3.1.2.5

Soul 3: what is interface testing, how to play interface testing, and how to play interface automation testing?

Enterprise level: spire Office for . NET:Platinum|7.7. x

Why can't all browsers on my computer open web pages

What is the reason why the webrtc protocol video cannot be played on the easycvr platform?

行为感知系统

在线文本行固定长度填充工具

Redis之Jedis如何使用

面试字节,过关斩将直接干到 3 面,结果找了个架构师来吊打我?
随机推荐
Rome chain analysis
BDF application - topology sequence
Is there a sudden failure on the line? How to make emergency diagnosis, troubleshooting and recovery
快手、抖音、视频号交战内容付费
DFS and BFS concepts of trees and graphs
C # use awaiter
[wp]bmzclub writeup of several questions
MindFusion.Virtual Keyboard for WPF
Operation flow of UE4 DMX and grandma2 onpc 3.1.2.5
Why do big companies such as Baidu and Alibaba prefer to spend 25K to recruit fresh students rather than raise wages by 5K to retain old employees?
Summary of scene design
About the project error reporting solution of mpaas Pb access mode adapting to 64 bit CPU architecture
ClickPaaS低代码平台
Basic function learning 02
[数组]566. 重塑矩阵-简单
阿里云ECS使用cloudfs4oss挂载OSS
反絮凝剂-氨碘肽滴眼液
How does the applet solve the rendering layer network layer error?
Redis source code analysis: redis cluster
Threejs realizes sky box, panoramic scene, ground grass