音频检测和视频检测


最近做音视频开发有涉及到这些功能,在此记录一下。

1. 视频检测

包括获取摄像头、切换摄像头、打开/关闭摄像头以及截图功能,界面效果如下,代码使用的是Vue框架。
在这里插入图片描述

1.1 获取设备

首先利用webRTC mediaDevices这个接口的enumerateDevices()方法获取所有的设备列表,然后将其按摄像头、麦克风、扬声器三种类型存储到列表中,存储时将设备的label作为设备标识并且要将每个设备的deviceId存储到列表,方便后边的摄像头切换。

  // 获取设备
  getMedia (context) {
    return navigator.mediaDevices.enumerateDevices().then((devices) => {
      // this.cameraList = [];
      console.log(devices);
      devices.forEach((device) => {
        if (device.kind == "videoinput") {
          context.commit("setCameraList", {
            label: device.label,
            id: device.deviceId,
          });
          context.commit("updateDefaultCamera", state.cameraList[0].id);
        } else if (device.kind == "audiooutput") {
          context.commit("setMicroPhoneList", {
            label: device.label,
            id: device.deviceId,
          });
          context.commit("updateDefaultMicroPhone", state.microPhoneList[0].id);
        } else if (device.kind == "audioinput") {
          context.commit("setAudioList", {
            label: device.label,
            id: device.deviceId,
          });
          context.commit("updateDefaultAudio", state.audioList[0].id);
        }
      });
    });
  },

1.2 打开摄像头

获取到摄像头设备后,就可以利用mediaDevices接口的getUserMedia()方法打开摄像头。因为我这里已经将设备绑定的deviceId作为参数传给了video,再借助vue的v-model双向绑定,就可以实现切换功能了,所以我前面强调一定要将deviceId存到设备列表上,这是重点。

	// 打开摄像头
    callCamera () {
      if (window.stream) {
        window.stream.getTracks().forEach(track => {
          track.stop();
        });
      }
      navigator.mediaDevices.getUserMedia({
        // video: true
        video: {
          deviceId: this.$store.state.defaultCamera ?
            { exact: this.$store.state.defaultCamera } : undefined
        }
      }).then(stream => {
        // 把媒体流赋值给 video 元素的 srcObj 属性,我们就能从屏幕上看到视频了
        this.$refs['video'].srcObject = stream
        // 实时拍照效果
        this.$refs['video'].play()
      }).catch(error => {
        console.log(error);
        this.$message.error('摄像头开启失败,请检查摄像头是否可用!');
      })
    },

1.3 关闭摄像头

关闭摄像头只要停止当前流的轨道即可。

	// 关闭摄像头
    closeCamera () {
      if (!this.$refs['video']) {
        return
      } else {
        if (this.$refs['video'].srcObject) {
          let stream = this.$refs['video'].srcObject
          let tracks = stream.getTracks()
          tracks.forEach(track => {
            track.stop()
          })
          this.$refs['video'].srcObject = null
        }

      }

    },

1.4 截图

虽然这里没有做这个功能,但是开启摄像头之后还可以实现拍照并保存图片功能

    // 拍照
    photograph () {
      // 图片容器
      let ctx = this.$refs['canvas'].getContext('2d')
      // 把当前视频帧内容渲染到canvas上
      ctx.drawImage(this.$refs['video'], 0, 0, 640, 480)
      // 转base64格式、图片格式转换、图片质量压缩---支持两种格式image/jpeg+image/png
      let imgBase64 = this.$refs['canvas'].toDataURL('image/jpeg', 0.7)

      /**------------到这里为止,就拿到了base64位置的地址,后面是下载功能----------*/

      // 由字节转换为KB 判断大小
      let str = imgBase64.replace('data:image/jpeg;base64,', '')
      let strLength = str.length
      // 图片尺寸  用于判断
      let fileLength = parseInt(strLength - (strLength / 8) * 2)
      let size = (fileLength / 1024).toFixed(2)
      // 上传拍照信息  调用接口上传图片 .........
      console.log(size)

      // 保存到本地
      let ADOM = document.createElement('a')
      ADOM.href = this.headImgSrc
      ADOM.download = new Date().getTime() + '.jpeg'
      ADOM.click()
    },

2. 音频检测

选择扬声器和麦克风设备,对它们进行输出等级(实时音量)检测及音量调节,界面如下:
在这里插入图片描述

2.1 切换扬声器

首先利用setSinkId()方法切换要检测的扬声器,重点也是我前面提到的要把当前选中设备的deviceId作为参数。

	// 切换扬声器
    changeMicro () {
      console.log("change");
      this.$refs['audio'].setSinkId(this.$store.state.defaultMicroPhone)
        .then(() => {
          console.log(this.$store.state.defaultMicroPhone);
        }).catch(error => {
          console.log(error);
        })
    },

2.2 检测扬声器

首先同摄像头一样先获取到设备,然后选定设备开始检测。我这里是检测一段音频文件

	// 检测扬声器
    testMicro () {
      if ('检测' === this.beginTestMicro) {
        this.$refs['audio'].play();
        // 定时获取音量
        var _that = this;
        this.audioVolume = _that.$refs['audio'].volume
        // 将本地文件转化为媒体流
        let stream = _that.$refs['audio'].captureStream();
        window.AudioContext = window.AudioContext || window.webkitAudioContext;
        window.audioContext = new AudioContext();
        // 根据第二个参数判断是要获取扬声器还是麦克风的输出等级
        this.handleSuccess(stream, 'micro')
        this.beginTestMicro = '停止检测'
      } else if ('停止检测' == this.beginTestMicro) {
        this.$refs['audio'].pause()
        this.audioVolume = 0;
        this.beginTestMicro = '检测';
      }
    },

handleSuccess是WebRTC上定义的检测麦克风的函数,这里同样可以用来检测扬声器。

    handleSuccess (stream, type) {
      var _that = this
      console.log(stream);
      // 成功调用麦克风后,媒体输入会产生一个MediaStream,其中包含了请求的媒体类型的轨道,将此轨道保存
      window.stream = stream;
      const soundMeter = window.soundMeter = new SoundMeter(window.audioContext);
      soundMeter.connectToSource(stream, function (e) {
        if (e) {
          alert(e);
          return;
        }
        // 组件卸载需要清除定时器,使用useRef()
        _that.meterRefresh = setInterval(() => {
          // 设置展示数据,就是取得音量
          if (type == 'audio') {
            _that.volume =
              soundMeter.instant.toFixed(2);
          } else if (type == 'micro') {
            _that.microLevel =
              soundMeter.instant.toFixed(2);
          }
        }, 200);
      });
    },

2.3 设置扬声器音量

因为这里是提前准备好的音频,只要直接设置audio元素的volume即可。

	// 修改扬声器音量
    changeMicroVolume (index) {
      this.$refs['audio'].volume = index / 100;
      this.microVolume = index;
    },

2.4 切换麦克风

麦克风的切换同摄像头。

2.5 检测麦克风

麦克风的输出等级检测类似扬声器,只是麦克风是检测我们开启麦克风后产生的实时流。

testAudio () {
      if ('检测' == this.beginTestVolume) {
        this.beginTestVolume = '停止检测'
        try {
          // 跨浏览器
          window.AudioContext = window.AudioContext || window.webkitAudioContext;
          // AudioContext:音频上下文,负责音频的处理和解码
          window.audioContext = new AudioContext();
        } catch (e) {
          alert('Web Audio API not supported.');
        }
        // 调用开启麦克风
        navigator.mediaDevices
          .getUserMedia({
            audio: {
              deviceId: this.$store.state.defaultAudio ?
                { exact: this.$store.state.defaultAudio } : undefined
            },
            video: false
          })
          .then(stream => this.handleSuccess(stream, 'audio'))
          .catch(this.handleError);
      } else if ('停止检测' == this.beginTestVolume) {
        this.beginTestVolume = '检测'
        // 获取到上面的媒体轨道信息数组 遍历关闭
        window.stream.getTracks().forEach(track => track.stop());
        window.soundMeter.stop();
        // 组件卸载需要清除定时器
        clearInterval(this.meterRefresh);
        this.volume = '';
      }
    },
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值