当前位置:网站首页>After the deployment of web resources, the navigator cannot obtain the solution of mediadevices instance (navigator.mediadevices is undefined)
After the deployment of web resources, the navigator cannot obtain the solution of mediadevices instance (navigator.mediadevices is undefined)
2022-07-05 04:08:00 【lyricist 】
problem
Recently in development , There is a function that needs to realize the function of recording screen , I used recordrtc library , There is no problem with local development in the process , When deploying to online environment navigator.mediaDevices by undefined, I searched many articles and official articles to solve
Causes and solutions
This problem is caused by the security policy of the browser , Currently tried , In the following cases navigator.mediaDevices It can be used normally.
1. The address is localhost:// During the interview
2. The address is https:// when
3. For file access file:///
// notes : If there are other plans, please correct
Attached recordrtc Use the source code for reference ( The reference source code uses element UI)
index.vue
<template>
<div>
<button @click="handleScreenRecord"> Start recording </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 {
// Get the recorded file file, Here's the deal file Business logic of
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 Kurt's documents :https://github.com/muaz-khan/RecordRTC
边栏推荐
- DFS and BFS concepts of trees and graphs
- EasyCVR更改录像存储路径,不生成录像文件如何解决?
- 10种寻址方式之间的区别
- 【UNIAPP】系统热更新实现思路
- 3. Package the bottom navigation tabbar
- 已解决(sqlalchemy+pandas.read_sql)AttributeError: ‘Engine‘ object has no attribute ‘execution_options‘
- Convert Boolean to integer value PHP - Convert Boolean to integer value PHP
- Summary of scene design
- Interview byte, pass the exam and directly work on three sides. As a result, I found an architect to hang me?
- 长度为n的入栈顺序的可能出栈顺序
猜你喜欢
测试开发是什么?为什么现在那么多公司都要招聘测试开发?
Plasticscm enterprise crack
Wechat applet development process (with mind map)
[understand series after reading] 6000 words teach you to realize interface automation from 0 to 1
我国算力规模排名全球第二:计算正向智算跨越
已解决(sqlalchemy+pandas.read_sql)AttributeError: ‘Engine‘ object has no attribute ‘execution_options‘
阿里云ECS使用cloudfs4oss挂载OSS
Learning notes 8
Looking back on 2021, looking forward to 2022 | a year between CSDN and me
Threejs Internet of things, 3D visualization of factory
随机推荐
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?
kubernetes集群之调度系统
基于TCP的移动端IM即时通讯开发仍然需要心跳保活
Threejs Internet of things, 3D visualization of farms (I)
Fuel consumption calculator
[Chongqing Guangdong education] 2408t Chinese contemporary literature reference test in autumn 2018 of the National Open University
How to realize real-time audio and video chat function
Longyuan war "epidemic" 2021 network security competition web easyjaba
【虛幻引擎UE】實現UE5像素流部署僅需六步操作少走彎路!(4.26和4.27原理類似)
【FineBI】使用FineBI制作自定义地图过程
Get to know MySQL connection query for the first time
我国算力规模排名全球第二:计算正向智算跨越
Use threejs to create geometry, dynamically add geometry, delete geometry, and add coordinate axes
Pyqt pyside custom telescopic menu bar sharing (including tutorial)
如何实现实时音视频聊天功能
Bit operation skills
Plasticscm enterprise crack
【看完就懂系列】一文6000字教你从0到1实现接口自动化
Kwai, Tiktok, video number, battle content payment
Test d'automatisation de l'interface utilisateur télécharger manuellement le pilote du navigateur à partir de maintenant