当前位置:网站首页>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
边栏推荐
- Rust blockchain development - signature encryption and private key public key
- 北京程序员的真实一天!!!!!
- 技术教程:如何利用EasyDSS将直播流推到七牛云?
- How to realize real-time audio and video chat function
- Possible stack order of stack order with length n
- Online sql to excel (xls/xlsx) tool
- About the project error reporting solution of mpaas Pb access mode adapting to 64 bit CPU architecture
- @The problem of cross database query invalidation caused by transactional annotation
- [wp]bmzclub writeup of several questions
- Plasticscm enterprise crack
猜你喜欢

如何实现实时音视频聊天功能
![[wp][introduction] brush weak type questions](/img/d0/9eb3ade701057837d98e4a20082a10.png)
[wp][introduction] brush weak type questions

CTF stegano practice stegano 9

As soon as I write the code, President Wang talks with me about the pattern all day

【虚幻引擎UE】实现背景模糊下近景旋转操作物体的方法及踩坑记录

“金九银十”是找工作的最佳时期吗?那倒未必

NetSetMan pro (IP fast switching tool) official Chinese version v5.1.0 | computer IP switching software download

在线文本行固定长度填充工具
![[brush questions] BFS topic selection](/img/24/7ec68ef60f94f7b366054824223709.png)
[brush questions] BFS topic selection

Uni app common functions /api
随机推荐
行为感知系统
[understand series after reading] 6000 words teach you to realize interface automation from 0 to 1
laravel8 导出Excle文件
[untitled]
官宣!第三届云原生编程挑战赛正式启动!
Threejs clicks the scene object to obtain object information, and threejs uses raycaster to pick up object information
C language course setting: cinema ticket selling management system
Summary of scene design
基于TCP的移动端IM即时通讯开发仍然需要心跳保活
Test d'automatisation de l'interface utilisateur télécharger manuellement le pilote du navigateur à partir de maintenant
“金九银十”是找工作的最佳时期吗?那倒未必
Resolved (sqlalchemy+pandas.read_sql) attributeerror: 'engine' object has no attribute 'execution_ options‘
UI自動化測試從此告別手動下載瀏覽器驅動
学习MVVM笔记(一)
Threejs Internet of things, 3D visualization of farms (II)
Phpmailer reported an error: SMTP error: failed to connect to server: (0)
在线文本行固定长度填充工具
Realize the attention function of the article in the applet
快手、抖音、视频号交战内容付费
The new project Galaxy token just announced by coinlist is gal