media.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import "./media-polyfill";
  2. class Media {
  3. constructor(videoElement) {
  4. this.videoElement = videoElement;
  5. this.timer = null; //audio frame
  6. this.init();
  7. }
  8. init() {
  9. this.initAudio();
  10. this.initCamera();
  11. }
  12. initAudio() {
  13. // set up forked web audio context, for multiple browsers
  14. // window. is needed otherwise Safari explodes
  15. this.audioCtx = new (window.AudioContext ||
  16. window.webkitAudioContext)();
  17. this.source = null;
  18. this.stream = null;
  19. //set up the different audio nodes we will use for the app
  20. this.analyser = this.audioCtx.createAnalyser();
  21. this.analyser.minDecibels = -90;
  22. this.analyser.maxDecibels = -10;
  23. this.analyser.smoothingTimeConstant = 0.85;
  24. this.distortion = this.audioCtx.createWaveShaper();
  25. this.gainNode = this.audioCtx.createGain();
  26. this.biquadFilter = this.audioCtx.createBiquadFilter();
  27. this.convolver = this.audioCtx.createConvolver();
  28. }
  29. setAudio() {
  30. this.source = this.audioCtx.createMediaStreamSource(this.stream);
  31. this.source.connect(this.distortion);
  32. this.distortion.connect(this.biquadFilter);
  33. this.biquadFilter.connect(this.gainNode);
  34. this.convolver.connect(this.gainNode);
  35. this.gainNode.connect(this.analyser);
  36. this.analyser.connect(this.audioCtx.destination);
  37. this.analyser.fftSize = 256;
  38. this.bufferLengthAlt = this.analyser.frequencyBinCount;
  39. this.dataArrayAlt = new Uint8Array(this.bufferLengthAlt);
  40. this.distortion.oversample = "4x";
  41. this.biquadFilter.disconnect(0);
  42. this.biquadFilter.connect(this.gainNode);
  43. }
  44. initCamera() {
  45. // Get access to the camera!
  46. if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  47. // Not adding `{ audio: true }` since we only want video now
  48. navigator.mediaDevices
  49. .getUserMedia({
  50. audio: true,
  51. video: {
  52. facingMode: "user",
  53. width: { min: 375, ideal: 750, max: 1280 },
  54. height: { min: 800, ideal: 900, max: 1080 }
  55. }
  56. })
  57. .then(stream => {
  58. // Older browsers may not have srcObject
  59. if ("srcObject" in this.videoElement) {
  60. this.videoElement.srcObject = stream;
  61. } else {
  62. // Avoid using this in new browsers, as it is going away.
  63. this.videoElement.src = window.URL.createObjectURL(
  64. stream
  65. );
  66. }
  67. this.videoElement.onloadedmetadata = e => {
  68. this.videoElement.play();
  69. this.stream = stream;
  70. this.setAudio();
  71. this.getDecibel();
  72. };
  73. })
  74. .catch(error => {
  75. alert("get access to the camera error:" + error.message);
  76. });
  77. } else {
  78. alert("we can not get access to the camera!");
  79. }
  80. }
  81. getDecibel() {
  82. this.gainNode.gain.setTargetAtTime(0.1, this.audioCtx.currentTime, 0); //播放声音
  83. this.analyser.getByteFrequencyData(this.dataArrayAlt);
  84. let max = 0;
  85. this.dataArrayAlt.forEach(decibel => {
  86. max = Math.max(decibel, max);
  87. });
  88. this.decibel = max;
  89. this.decibelCallbacks && this.decibelCallbacks(this.decibel);
  90. this.timer = requestAnimationFrame(this.getDecibel.bind(this));
  91. }
  92. add(fn) {
  93. this.decibelCallbacks = fn;
  94. }
  95. }
  96. export default Media;