VUE+Django实现前端开启摄像头录制存储视频并直接上传后端

这篇具有很好参考价值的文章主要介绍了VUE+Django实现前端开启摄像头录制存储视频并直接上传后端。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

效果预览


1.录制前

vue调用摄像头拍照上传,前端,django,html5,javascript,vue.js,Powered by 金山文档

2.录制中

vue调用摄像头拍照上传,前端,django,html5,javascript,vue.js,Powered by 金山文档

3.录制结束下载文件至本地

vue调用摄像头拍照上传,前端,django,html5,javascript,vue.js,Powered by 金山文档

4.视频文件同时上传至后端接口

vue调用摄像头拍照上传,前端,django,html5,javascript,vue.js,Powered by 金山文档
vue调用摄像头拍照上传,前端,django,html5,javascript,vue.js,Powered by 金山文档

后端准备


参考博客https://blog.csdn.net/wuchenlhy/article/details/79311234?spm=1001.2014.3001.5506

博主在后端这块写的十分简洁明了,可以直接参考实现开设后端简单文件上传接口的方法

前端组件实现


参考文章:

https://blog.csdn.net/XH_jing/article/details/117415496

http://t.csdn.cn/ap9Zy

http://t.csdn.cn/NpKtL

Vue 调用本地摄像头实现拍照功能,由于调用摄像头有使用权限,只能在本地运行,线上需用 https 域名才可以使用。

需求分析

点击“视频录制”按钮,打开摄像头开启录制,同时按钮中内容更换为“停止录制”

点击“停止录制”按钮,关闭摄像头并保存录制文件,同时将以录制的文件上传后端接口

使用API

MediaDevices.getUserMedia()

该 API 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。

它返回一个 Promise 对象,成功后会 resolve 回调一个 MediaStream 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,Promise 会 reject 回调一个 PermissionDeniedError 或者 NotFoundError。

HTML部分

<template>
  <div class="CallCamera">
    <!-- 下载按钮 -->
    <a id="downLoadLink" style="display: none"></a>
    <div class="video-box">
      <video ref="video"></video>
      <!-- 视频录制或暂停 -->
      <button @click="recordOrStop" id="record_btu">视频录制</button>
    </div>
  </div>
</template>

JS部分

1.调用开启摄像头
// 调用打开摄像头功能
    getCamera() {
      // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
      }
      // 正常支持版本
      navigator.mediaDevices
        .getUserMedia({
          video: true,
          audio: true,
        })
          .then((stream) => {
          // 摄像头开启成功
          this.mediaStreamTrack = typeof stream.stop === 'function' ? stream : stream.getTracks()[0];
          this.video_stream = stream;
          this.$refs.video.srcObject = stream;
          this.$refs.video.play();
        })
        .catch(err => {
          console.log(err);
        });
    },
2.视频录制并下载以及停止录制
  // 视频录制
    record() {
      console.log("record");
      this.isRecord = !this.isRecord;
      let mediaRecorder;
      let options;
      this.recordedBlobs = [];
      if (typeof MediaRecorder.isTypeSupported === "function") {
        // 根据浏览器来设置编码参数
        if (MediaRecorder.isTypeSupported("video/webm;codecs=vp9")) {
          options = {
            MimeType: "video/webm;codecs=h264",
          };
        } else if (MediaRecorder.isTypeSupported("video/webm;codecs=h264")) {
          options = {
            MimeType: "video/webm;codecs=h264",
          };
        } else if (MediaRecorder.isTypeSupported("video/webm;codecs=vp8")) {
          options = {
            MimeType: "video/webm;codecs=vp8",
          };
        }
        mediaRecorder = new MediaRecorder(this.video_stream, options);
      } else {
        // console.log('isTypeSupported is not supported, using default codecs for browser');
        console.log("当前不支持isTypeSupported,使用浏览器的默认编解码器");
        mediaRecorder = new MediaRecorder(this.video_stream);
      }
      mediaRecorder.start();
      // 视频录制监听事件
      mediaRecorder.ondataavailable = (e) => {
        console.log(e);
        // 录制的视频数据有效
        if (e.data && e.data.size > 0) {
          this.recordedBlobs.push(e.data);
        }
      };
      // 停止录像后增加下载视频功能,将视频流转为mp4格式
      mediaRecorder.onstop = () => {
        const blob = new Blob(this.recordedBlobs, { type: "video/mp4" });
        this.recordedBlobs = [];
        // 将视频链接转换完可以用于在浏览器上预览的本地视频
        const videoUrl = window.URL.createObjectURL(blob);
        // 设置下载链接
        document.getElementById("downLoadLink").href = videoUrl;
        // 设置下载mp4格式视频
        document.getElementById("downLoadLink").download = "media.mp4";
        document.getElementById("downLoadLink").innerHTML =
          "DownLoad video file";
        // 生成随机数字
        const rand = Math.floor(Math.random() * 1000000);
        // 生成视频名
        const name = `video${rand}.mp4`;

        // setAttribute() 方法添加指定的属性,并为其赋指定的值
        document.getElementById("downLoadLink").setAttribute("download", name);
        document.getElementById("downLoadLink").setAttribute("name", name);

        console.log(name);
        const filename = "C:\\Users\\k1114\\Downloads\\" + name;
        console.log(filename);

        // 0.5s后自动下载视频
        setTimeout(() => {
          document.getElementById("downLoadLink").click();
        }, 500);

        
      };
    },
    // 停止录制
    stop() {
      this.isRecord = !this.isRecord;
      if (!this.$refs.video.srcObject) return;
      const stream = this.$refs.video.srcObject;
      const tracks = stream.getTracks();
      // 关闭摄像头和音频
      tracks.forEach((track) => {
        track.stop();
      });
    },
3.获取文件流并上传后端

直接将视频流定义为file对象,通过post方法上传接口

//上传至后端
        let fileobj = new File(
          [blob],
            name,
          {
          type: "video/mp4",
        });

        let formData = new FormData(); //创建form对象
        formData.append("filename", fileobj); //通过append向form对象添加数据
        console.log(formData.get("filename")); //FormData私有类对象,访问不到,可以通过get判断值是否传进去
        //上传
        this.$axios
          .post("http://127.0.0.1:8000/runcase/start", formData, {
            headers: { "Content-Type": "none" },
          }) //请求头要为表单
          .then((response) => {
            console.log(response.data);
          })
          .catch(function (error) {
            console.log(error);
          });
4.按钮事件

通过 document.getElementById("record_btu") 获取按钮对象,并根据点击事件修改按钮内容和样式

根据 this.isRecord (boolen)判断视频录制状态,在进入页面时声明为false,按钮触发点击事件后修改为对立状态

因为在录制时要在页面的video窗口实时回显,如果不静音页面会产生回音,所以在开启摄像头时静音页面

触发按钮事件开启摄像头后直接开始录制会触发错误(我不知道具体原因,可能是摄像头还没有初始化完毕),所以设置了延时执行录制

recordOrStop() {
      if (this.isRecord) {
        document.getElementById("record_btu").innerText = "视频录制";
        document.getElementById("record_btu").style.backgroundColor =
          "rgb(22, 204, 195)";
        document.getElementById("record_btu").style.color = "black";
        this.stop();
      } else {
        this.getCamera();  //打开摄像头
        this.mutePage();   //将页面静音
        document.getElementById("record_btu").innerText = "结束录制";
        document.getElementById("record_btu").style.backgroundColor =
          "rgb(255 99 71)";
        document.getElementById("record_btu").style.color = "white";
        setTimeout(() => {
          // 方法区
          this.record();
        }, 2000);  //设置录制延迟 2s 
      }

完整JS代码文章来源地址https://www.toymoban.com/news/detail-628301.html

<script>
export default {
  data() {
    return {
      mediaStreamTrack: {}, // 退出时关闭摄像头
      video_stream: "", // 视频stream
      recordedBlobs: [], // 视频音频 blobs
      isRecord: false, // 视频是否正在录制
    };
  },
  mounted() {
    // 进入页面 调用摄像头
    // this.getCamera();
    // this.mutePage();
    window.onerror = () => {
      // mes 报错信息, source 那个文件, line 第几行, column 第几列, error 错误的对象
      this.$notify({
        title: "录制失败",
        message: "请点击结束录制并重新尝试",
        type: "warning",
      });
    };
  },
  methods: {
    // Mute a singular HTML5 element
    muteMe(elem) {
      elem.muted = true;
      elem.pause();
    },
    // Try to mute all video and audio elements on the page
    mutePage() {
      document
        .querySelectorAll("video, audio")
        .forEach((elem) => this.muteMe(elem));
    },

    // 调用打开摄像头功能
    getCamera() {
      // 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
      if (navigator.mediaDevices === undefined) {
        navigator.mediaDevices = {};
      }
      navigator.mediaDevices
        .getUserMedia({
          video: true,
          audio: true,
        })
        .then((stream) => {
          // 摄像头开启成功
          this.mediaStreamTrack =
            typeof stream.stop === "function" ? stream : stream.getTracks()[0];
          this.video_stream = stream;
          this.$refs.video.srcObject = stream;
          this.$refs.video.play();
        })
        .catch((err) => {
          console.log(err);
        });
    },
    // 录制或暂停
    recordOrStop() {
      if (this.isRecord) {
        document.getElementById("record_btu").innerText = "视频录制";
        document.getElementById("record_btu").style.backgroundColor =
          "rgb(22, 204, 195)";
        document.getElementById("record_btu").style.color = "black";
        this.stop();
      } else {
        this.getCamera();
        this.mutePage();
        document.getElementById("record_btu").innerText = "结束录制";
        document.getElementById("record_btu").style.backgroundColor =
          "rgb(255 99 71)";
        document.getElementById("record_btu").style.color = "white";
        setTimeout(() => {
          // 方法区
          this.record();
        }, 2000);
      }
    },
    // 视频录制
    record() {
      console.log("record");
      this.isRecord = !this.isRecord;
      let mediaRecorder;
      let options;
      this.recordedBlobs = [];
      if (typeof MediaRecorder.isTypeSupported === "function") {
        // 根据浏览器来设置编码参数
        if (MediaRecorder.isTypeSupported("video/webm;codecs=vp9")) {
          options = {
            MimeType: "video/webm;codecs=h264",
          };
        } else if (MediaRecorder.isTypeSupported("video/webm;codecs=h264")) {
          options = {
            MimeType: "video/webm;codecs=h264",
          };
        } else if (MediaRecorder.isTypeSupported("video/webm;codecs=vp8")) {
          options = {
            MimeType: "video/webm;codecs=vp8",
          };
        }
        mediaRecorder = new MediaRecorder(this.video_stream, options);
      } else {
        // console.log('isTypeSupported is not supported, using default codecs for browser');
        console.log("当前不支持isTypeSupported,使用浏览器的默认编解码器");
        mediaRecorder = new MediaRecorder(this.video_stream);
      }
      mediaRecorder.start();
      // 视频录制监听事件
      mediaRecorder.ondataavailable = (e) => {
        console.log(e);
        // 录制的视频数据有效
        if (e.data && e.data.size > 0) {
          this.recordedBlobs.push(e.data);
        }
      };
      // 停止录像后增加下载视频功能,将视频流转为mp4格式
      mediaRecorder.onstop = () => {
        const blob = new Blob(this.recordedBlobs, { type: "video/mp4" });
        this.recordedBlobs = [];
        // 将视频链接转换完可以用于在浏览器上预览的本地视频
        const videoUrl = window.URL.createObjectURL(blob);
        // 设置下载链接
        document.getElementById("downLoadLink").href = videoUrl;
        // 设置下载mp4格式视频
        document.getElementById("downLoadLink").download = "media.mp4";
        document.getElementById("downLoadLink").innerHTML =
          "DownLoad video file";
        // 生成随机数字
        const rand = Math.floor(Math.random() * 1000000);
        // 生成视频名
        const name = `video${rand}.mp4`;

        // setAttribute() 方法添加指定的属性,并为其赋指定的值
        document.getElementById("downLoadLink").setAttribute("download", name);
        document.getElementById("downLoadLink").setAttribute("name", name);

        console.log(name);
        const filename = "C:\\Users\\k1114\\Downloads\\" + name;
        console.log(filename);

        // 0.5s后自动下载视频
        setTimeout(() => {
          document.getElementById("downLoadLink").click();
        }, 500);

        //上传至后端

        let fileobj = new File(
          [blob],
            name,
          {
          type: "video/mp4",
        });

        let formData = new FormData(); //创建form对象
        formData.append("filename", fileobj); //通过append向form对象添加数据
        console.log(formData.get("filename")); //FormData私有类对象,访问不到,可以通过get判断值是否传进去
        //上传
        this.$axios
          .post("http://127.0.0.1:8000/runcase/start", formData, {
            headers: { "Content-Type": "none" },
          }) //请求头要为表单
          .then((response) => {
            console.log(response.data);
          })
          .catch(function (error) {
            console.log(error);
          });
      };
    },
    // 停止录制
    stop() {
      this.isRecord = !this.isRecord;
      if (!this.$refs.video.srcObject) return;
      const stream = this.$refs.video.srcObject;
      const tracks = stream.getTracks();
      // 关闭摄像头和音频
      tracks.forEach((track) => {
        track.stop();
      });
    },

  },
};
</script>

CSS部分

<style>
.CallCamera {
  flex-wrap: wrap;
  align-content: space-between;
}
.video-box {
  width: 800px;
  height: 600px;
  text-align: center;
}
video {
  width: 740px;
  height: 555px;
  background-color: black;
  object-fit: fill;
  margin: auto;
  /*position: relative;*/

  /*position: absolute;*/
}
canvas {
  width: 100%;
  height: 100%;
}
.CallCamera button {
  width: 100px;
  height: 40px;
  position: relative;
  margin: auto;
  border-radius: 15px;
  background-color: rgb(22, 204, 195);
  cursor: pointer;
  transition: 0.5s;
  top: 20px;
}
.CallCamera button:hover {
  font-size: 15px;
  background-color: rgb(255 99 71);
  color: white;
}

.img_bg_camera img {
  width: 300px;
  height: 200px;
}
</style>

到了这里,关于VUE+Django实现前端开启摄像头录制存储视频并直接上传后端的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCv:采集摄像头视频、读取视频帧与视频录制

    目录 一、涉及OpenCv函数 二、什么是帧、帧的大小代表什么 三、摄像头获取视频数据 四、录制视频并保存 从设备,可以是摄像头可以是本地视频, 获取视频的函数 cv.VideoCapture()。 本函数作用在于创建一个VideoCapture或者VideoWriter对象,真正的读取和写入是通过创建的对象进行

    2024年02月16日
    浏览(24)
  • 海康摄像头web3.3前端实现

     上篇我发布了一篇文章,有一个刷新页面摄像头就消失的bug,这个代码就是我改过以后得。 直接就放到组件里就行。要是不出来的话,可能是你们插件有问题。可以重新安装一次插件。 template     div class=\\\"chart-box\\\" ref=\\\"chartBox\\\"         div class=\\\"chart-body\\\" ref=\\\"divPlugin\\\" id=\\\"divPlu

    2024年02月20日
    浏览(18)
  • vue2使用rtsp视频流接入海康威视摄像头(纯前端)

    海康威视官方的RTSP最新取流格式如下: rtsp://用户名:密码@IP:554/Streaming/Channels/101 用户名和密码 IP就是登陆摄像头时候的IP(笔者这里IP是192.168.1.210) 所以笔者的rtsp流地址就是 rtsp://用户名:密码@192.168.1.210:554/Streaming/Channels/101 1.1关闭 萤石云的接入 1.2 调整视频编码为H.264 在此下载

    2024年04月26日
    浏览(33)
  • SpringBoot+海康威视摄像头实现在前端的预览

    本文是之前文章的一篇完善文,如果你是才接触海康威视摄像头的二次开发请先阅读入门篇 在实现摄像头的预览的时候需要搞懂什么是rtsp。 rtsp是一种实时流传输协议(Real Time Streaming Protocol,RTSP),主要使用TCP和UDP完成数据的传输。 1.1 了解海康威视rtsp的url规范 【老版本】

    2023年04月08日
    浏览(30)
  • 使用ffmpeg调用电脑自带的摄像头和扬声器录制音视频

    1、打开cmd,执行 chcp 65001 ,修改cmd的编码格式为utf8,避免乱码 2、执行指令 ffmpeg -list_devices true -f dshow -i dummy ,查看当前window的音频和视频名称 3、打开windows系统的\\\"打开声音设置\\\"–“麦克风隐私设置”–\\\"允许应用访问你的麦克风\\\"点击开启 录制视频: 录制音频: 录制音视频:

    2024年02月04日
    浏览(31)
  • SLAM系统--开启摄像头连接

    博客地址:https://www.cnblogs.com/zylyehuo/ 基于ORB-SLAM3库搭建SLAM系统 详见之前的博客 基于ORB-SLAM3库搭建SLAM系统 - zylyehuo - 博客园 (cnblogs.com) 参考链接 ORB-SLAM3 v1.0 编译问题解决 /usr/bin/env: \\\"pythonr\\\": 没有那个文件或目录 打开终端输入指令: vim ~/.bashrc 打开用户根目录下的.bashrc文件

    2024年02月06日
    浏览(23)
  • Vue集成海康websdk实现摄像头预览

    选择以及下载相应的websdk: 从海康开放平台下载相应的sdk,web3.0不支持高版本浏览器,web3.2需要摄像头支持摄像头取流,web3.3支持高版本浏览器 我这选择的是3.3的。 可以先测试下开发包是否可以成功访问,修改用ip、户名、密码。端口一般使用默认80,点击登录,然后选择相

    2024年02月03日
    浏览(31)
  • C#使用OpenCv(OpenCVSharp)使用摄像头视频显示和录制及图片保存、本地视频显示

    本篇实例讲解基于OpenCvSharp实现了摄像头视频显示、录制及截图、视频保存,本地视频的显示功能。 目录 创建winform项目添加控件 NuGet安装opencvsharp  代码  运行效果 实例实现过程

    2024年02月15日
    浏览(25)
  • VUE+faceApi.js实现摄像头拍摄人脸识别

    需求:前端获取到摄像头信息,通过模型来进行判断人像是否在镜头中,镜头是否有被遮挡。 实现步骤: 1、通过video标签来展示摄像头中的内容 2、通过canvas来绘制视频中信息进行展示 3、在拍照时候将canvas的当前帧转成图片 下载依赖 face-api.js是核心依赖必须要下 element-ui为

    2024年02月01日
    浏览(19)
  • JetsonNano学习(四)OPENCV开启CSI摄像头

    网上非常多的代码打不开CSI摄像头,但是使用 Python2 可以解决,根本原因在于OpenCV版本,Python2库中的CV2版本高于Python3导致,通过更新Python3库中的OpenCV即可解决该问题。 断电安装CSI摄像头,注意排线线缆的方向和正反,安装完成后上电开机。 如果是USB摄像头,安装有手就行

    2024年02月15日
    浏览(24)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包