当前位置:网站首页>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
边栏推荐
- IronXL for . NET 2022.6
- PlasticSCM 企业版Crack
- The scale of computing power in China ranks second in the world: computing is leaping forward in Intelligent Computing
- English essential vocabulary 3400
- error Couldn‘t find a package. JSON file in "your path“
- [an Xun cup 2019] not file upload
- Threejs implements labels and displays labels with custom styles
- provide/inject
- Mixed compilation of C and CC
- Use of vscode software
猜你喜欢
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?
[brush questions] BFS topic selection
PlasticSCM 企业版Crack
JWT vulnerability recurrence
Redis source code analysis: redis cluster
Differences among 10 addressing modes
Rust区块琏开发——签名加密与私钥公钥
Special Edition: spreadjs v15.1 vs spreadjs v15.0
Behavior perception system
An elegant program for Euclid‘s algorithm
随机推荐
[wp]bmzclub writeup of several questions
Uni app common functions /api
@The problem of cross database query invalidation caused by transactional annotation
Test d'automatisation de l'interface utilisateur télécharger manuellement le pilote du navigateur à partir de maintenant
“金九银十”是找工作的最佳时期吗?那倒未必
DMX parameter exploration of grandma2 onpc 3.1.2.5
[wp][introduction] brush weak type questions
ClickPaaS低代码平台
Redis source code analysis: redis cluster
Laravel8 export excel file
Threejs factory model 3DMAX model obj+mtl format, source file download
小程序中实现文章的关注功能
C语言课设:影院售票管理系统
[charging station]_ Secular wisdom_ Philosophical wisdom _
Operation flow of UE4 DMX and grandma2 onpc 3.1.2.5
provide/inject
[C language] address book - dynamic and static implementation
Official announcement! The third cloud native programming challenge is officially launched!
优先使用对象组合,而不是类继承
IronXL for . NET 2022.6