JS 調用 麥克風 檢測實時音量

代碼較多 看第二份調用代碼 裏面有註釋

關鍵步驟
1、將成功調用麥克風後的 媒體軌道保存 (第二份代碼)
2、 關閉的時候便利軌道數組 逐個關閉 (第三份代碼)

封裝部分 直接調用

封裝代碼 、

/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */
export default class SoundMeter {
  instant: number;
  script: any;
  clip: number;
  slow: number;
  context: any;
  mic: any;
  constructor(context: any) {
    this.context = context;
    this.instant = 0.0;
    this.slow = 0.0;
    this.clip = 0.0;
    this.script = context.createScriptProcessor(2048, 1, 1);
    var that = this;
    this.script.onaudioprocess = function (event: { inputBuffer: { getChannelData: (arg0: number) => any; }; }) {
      var input = event.inputBuffer.getChannelData(0);
      var i;
      var sum = 0.0;
      var clipcount = 0;
      for (i = 0; i < input.length; ++i) {
        sum += input[i] * input[i];
        if (Math.abs(input[i]) > 0.99) {
          clipcount += 1;
        }
      }
      that.instant = Math.sqrt(sum / input.length);
      that.slow = 0.95 * that.slow + 0.05 * that.instant;
      that.clip = clipcount / input.length;
    };
  }
  connectToSource = (stream: any, callback: (arg0: null) => void) => {
    console.log('SoundMeter connecting');
    try {
      this.mic = this.context.createMediaStreamSource(stream);
      this.mic.connect(this.script);
      // necessary to make sample run, but should not be.
      this.script.connect(this.context.destination);
      if (typeof callback !== 'undefined') {
        callback(null);
      }
    } catch (e) {
      console.error(e);
      if (typeof callback !== 'undefined') {
        callback(e);
      }
    }
  }
  stop = () => {
    this.mic.disconnect();
    this.script.disconnect();
  }
}

調用

  useEffect(() => {
    const mic = () => {
      let constraints = {
        audio: true,
        video: false,
      };
      //調用開啓麥克風
      navigator.mediaDevices
        .getUserMedia(constraints)
        .then(handleSuccess)
        .catch(handleError);
    };


    const handleSuccess = (stream: any) => {
      window.MSStream = stream;
      //成功調用麥克風後 媒體輸入會產生一個MediaStream,裏面包含了請求的媒體類型的軌道
      // 將此軌道保存  後面關閉的時候回用到
      setSource(window.MSStream);
      soundMeter.connectToSource(stream, function (e: any) {
        if (e) {
          console.log(e);
          return;
        }
        //組件卸載需要清除定時器 使用useRef()
        intervalRef.current = setInterval(function () {
        	//	設置展示數據 就是取得 音量
          setVoice(Number(soundMeter.instant.toFixed(2)) * 100);
        }, 200);
      });
    };

    const handleError = (error: any) => {
      console.log('navigator.getUserMedia error: ', error);
    };

    if (micResult.support === 'success') {
      mic();
    } else {
   		//判斷音頻流是存在
      soundMeter.mic && soundMeter.stop();
      clearInterval(intervalRef.current);
    }
    return () => {
      clearInterval(intervalRef.current);
    };
    //根據是成果否調用到麥克風硬件 觸發是否監聽 麥克風音量
  }, [micResult, soundMeter]);

關閉監聽

調用完後直接切換組件,監聽音量會一直存在 瀏覽器上方會展示話筒
所以需要關閉瀏覽器

 const init = useCallback(() => {
    if(! window.MSStream) return 
    // 首次進入卸載 會導致下面報錯 所以需要return
    
   // 獲取到上面的 媒體軌道信息數組 遍歷關閉
    source && source.getTracks().forEach(function (track: { stop: () => void }) {
        track.stop();
      });
  }, [source]);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章