<template>
  <div>
    <div class="h90 tc">
      <div class="wih100 tc">
        <div v-if="flag">
          <div class="mt24 cf f25 fw700">实时广播</div>
          <div class="cf mt5">{{ time }}</div>
        </div>
        <div v-else>
          <div class="mt24 cf f25 fw700">实时广播</div>
          <div class="cf mt5">{{ time }}</div>
        </div>
      </div>
      <div class="wih100">
        <div class="AudioBG tc mt24 dib">
          <img
            class="dib wih100 h80 mt10"
            src="./assets/AudioBG.png"
            alt=""
          />
        </div>
      </div>
      <div class="bottomBtnBox jcsb mt30 pl24 pr24" v-if="flag">
        <!-- <div class="cf f14" @click="change">
          <div class="w35 h35 btnStyle lh35 tc">
            <div class="w15 h15 ml8 iconfont icon-moshiqiehuan"></div>
          </div>
          <div>模式切换</div>
        </div> -->
        <div class="cf f14" style="transform: scale(0.7)">
          <div class="w45 h45 lh45 btnStyle tc cp" @click="play">
            <div
              class="w5 h5 ml14 iconfont"
              :class="isPlay ? 'icon-wanchengluyin' : 'icon-kaishiluyin'"
            ></div>
          </div>
          <div>{{ !isPlay ? "开始喊话" : "结束喊话" }}</div>
        </div>
        <!-- <div class="cf f14" :class="{ vish: !isPlay }">
          <div class="w35 h35 btnStyle" @click="reset">
            <div class="w5 h5 mt10 ml9 iconfont icon-guanbi"></div>
          </div>
          <div>取消</div>
        </div> -->
      </div>
      <!-- <div class="mt40" v-if="!flag">
        <div class="bottomBtnBox mr jcenter">
          <div class="cf f14" @click="change">
            <div class="w45 h45 lh45 btnStyle tc cp">
              <div class="w15 h15 ml13 iconfont icon-moshiqiehuan"></div>
            </div>
            <div>模式切换</div>
          </div>
        </div>
      </div> -->
    </div>
  </div>
</template>

<script>
import CmdStreamUpData from "mmc/utils/PagerP1/cmd_stream_up_data";
//必须引入的核心，换成require也是一样的。注意：recorder-core会自动往window下挂载名称为Recorder对象，全局可调用window.Recorder，也许可自行调整相关源码清除全局污染
import Recorder from "recorder-core";
//需要使用到的音频格式编码引擎的js文件统统加载进来
import "recorder-core/src/engine/mp3";
import "recorder-core/src/engine/mp3-engine";
import "recorder-core/src/engine/pcm";
export default {
  data() {
    return {
      flag: true,
      isPlay: false,
      hours: "00",
      time: "00:00:00",
      setIntervalTime: "",
      s: 0,
      h: 0,
      f: 0,
      action: null,
      result: null,
      type: null,
    };
  },
  inject: ["PagerP1", "PoliceKey"],
  mounted() {},
  beforeDestroy() {
    this.handleStartShoutDown();
  },
  watch:{
    action:{
      handler(val){
        if(val == 12 && this.type == 0 && this.result == 0){
          this.say()
        }
      }
    }
  },
  methods: {
    reset() {
      clearInterval(this.setIntervalTime);
      this.time = "00:00:00";
      this.s = 0;
      this.h = 0;
      this.f = 0;
      this.isPlay = false;
    },
    change() {
      this.flag = !this.flag;
      this.reset();
      if (!this.flag) {
        this.handleStartShout();
        this.init();
      } else {
        this.handleStartShoutDown();
      }  
    },

    play() {
      this.isPlay = !this.isPlay;
      if (!this.isPlay) {
        //完成录音
        this.handleStartShoutDown();
        this.reset();
      } else {
        // this.init();
        this.init();
        this.handleStartShout();
      }
    },
    init() {
      this.setIntervalTime = setInterval(() => {
        this.s += 1;
        if (this.s === 60) {
          this.s = 0;
          this.f += 1;
          if (this.f === 60) {
            this.h += 1;
          }
        }
        if (this.s < 10 && this.f < 10) {
          this.time = "0" + this.h + ":" + 0 + this.f + ":" + 0 + this.s;
        } else if (this.s < 10 && this.f >= 10) {
          this.time = "0" + this.h + ":" + this.f + ":" + 0 + this.s;
        } else if (this.s >= 10 && this.f < 10) {
          this.time = "0" + this.h + ":" + 0 + this.f + ":" + this.s;
        } else if (this.s >= 10 && this.f >= 10) {
          this.time = "0" + this.h + ":" + this.f + ":" + this.s;
        }
      }, 1000);
    },
    handleStartShout() {
      let message = {
        data: 12,
        type: 2317,
      };
      this.mqtt_publish(message);
      let _this = this;
    },
    say(){
      let _this = this
        function sendAllBytes(arrayBuffer) {
          // console.log(arrayBuffer);
          var uint8array = new Uint8Array(arrayBuffer);
          let list = [...uint8array];
          let mav_list = [];
          while (list.length > 0) {
            let byte250 = list.splice(0, 250);
            let uint8array = Uint8Array.from(byte250);
            let array = [...uint8array];
            let cmd = new CmdStreamUpData(array.length, array);
            let message = cmd.pack();
            mav_list.push(...message);
          }
          let message = Uint8Array.from(mav_list);
          let datas = {
            data: Array.from(uint8array),
            type: 2318,
          };
          _this.mqtt_publish(datas);
        }
  
        var testSampleRate = 16000;
        var testBitRate = 16;
        var SendInterval = 1;
  
        /******
          转码发送间隔（实际间隔比这个变量值偏大点，取决于BufferSize）。这个值可以设置很大，但不能设置很低，毕竟转码和传输还是要花费一定时间的，设备性能低下可能还处理不过来。
  
          mp3格式下一般大于500ms就能保证能够正常转码处理，wav大于100ms，剩下的问题就是传输速度了。由于转码操作都是串行的，录制过程中转码生成出来mp3顺序都是能够得到保证，但结束时最后几段数据可能产生顺序问题，需要留意。由于传输通道不一定稳定，后端接收到的顺序可能错乱，因此可以携带编号进行传输，完成后进行一次排序以纠正顺序错乱的问题。
  
          mp3格式在间隔太低的情况下中间的停顿会非常明显，可适当调大间隔以规避此影响，因为mp3编码时首尾出现了填充的静默数据（mp3.js编码器内已尽力消除了这些静默，但还是会有些许的静默停顿）；wav格式没有此问题，测试时可以打开 testOutputWavLog + mp3、wav合并demo 来对比音质。
  
          当出现性能问题时，可能音频编码不过来，将采取丢弃部分帧的策略。
        ******/
  
        //重置环境
        var RealTimeSendTryReset = function (type) {
          realTimeSendTryType = type;
          realTimeSendTryTime = 0;
        };
  
        var realTimeSendTryType;
        var realTimeSendTryEncBusy;
        var realTimeSendTryTime = 0;
        var realTimeSendTryNumber;
        var transferUploadNumberMax;
        var realTimeSendTryChunk;
  
        //=====实时处理核心函数==========
        var RealTimeSendTry = function (rec, isClose) {
          var t1 = Date.now(),
            endT = 0,
            recImpl = Recorder.prototype;
          if (realTimeSendTryTime == 0) {
            realTimeSendTryTime = t1;
            realTimeSendTryEncBusy = 0;
            realTimeSendTryNumber = 0;
            transferUploadNumberMax = 0;
            realTimeSendTryChunk = null;
          }
          if (!isClose && t1 - realTimeSendTryTime < SendInterval) {
            return; //控制缓冲达到指定间隔才进行传输
          }
          realTimeSendTryTime = t1;
          var number = ++realTimeSendTryNumber;
  
          //借用SampleData函数进行数据的连续处理，采样率转换是顺带的
          var chunk = Recorder.SampleData(
            rec.buffers,
            rec.srcSampleRate,
            testSampleRate,
            realTimeSendTryChunk,
            { frameType: isClose ? "" : realTimeSendTryType }
          );
  
          //清理已处理完的缓冲数据，释放内存以支持长时间录音，最后完成录音时不能调用stop，因为数据已经被清掉了
          for (
            var i = realTimeSendTryChunk ? realTimeSendTryChunk.index : 0;
            i < chunk.index;
            i++
          ) {
            rec.buffers[i] = null;
          }
          realTimeSendTryChunk = chunk; //此时的chunk.data就是原始的音频pcm数据，直接保存即为pcm文件、加个wav头即为wav文件、丢给mp3编码器转一下码即为mp3文件
  
          //实时编码队列阻塞处理
          if (!isClose) {
            if (realTimeSendTryEncBusy >= 2) {
              // console.log("编码队列阻塞，已丢弃一帧");
              return;
            }
          }
          realTimeSendTryEncBusy++;
  
          //通过mock方法实时转码成mp3、wav；pcm格式可以不经过此操作，直接发送chunk.data
          var encStartTime = Date.now();
          var recMock = Recorder({
            type: realTimeSendTryType,
            sampleRate: testSampleRate, //采样率
            bitRate: testBitRate, //比特率
          });
          recMock.mock(chunk.data, chunk.sampleRate);
  
          recMock.stop(
            function (blob, duration) {
              realTimeSendTryEncBusy && realTimeSendTryEncBusy--;
              blob.encTime = Date.now() - encStartTime;
              sendAllBytes(chunk.data.buffer);
            },
            function (msg) {
              realTimeSendTryEncBusy && realTimeSendTryEncBusy--;
            }
          );
        };
  
        //调用录音
        var rec;
        function recStartPcm() {
          recStart("pcm");
        }
        function recStart(type) {
          if (rec) {
            rec.close();
          }
          rec = Recorder({
            type: "unknown",
            onProcess: function (
              buffers,
              powerLevel,
              bufferDuration,
              bufferSampleRate
            ) {
              //推入实时处理，因为是unknown格式，这里简化函数调用，没有用到buffers和bufferSampleRate，因为这些数据和rec.buffers是完全相同的。
              RealTimeSendTry(rec, false);
            },
          });
  
          var t = setTimeout(function () {}, 8000);
  
          rec.open(
            function () {
              //打开麦克风授权获得相关资源
              clearTimeout(t);
              rec.start(); //开始录音
  
              RealTimeSendTryReset(type); //重置
            },
            function (msg, isUserNotAllow) {
              clearTimeout(t);
            }
          );
        }
        function recStop() {
          rec.close(); //直接close掉即可，这个例子不需要获得最终的音频文件
  
          RealTimeSendTry(rec, true); //最后一次发送
        }
  
        this.recStop = recStop;
  
        recStartPcm();
    },
    handleStartShoutDown() {
      this.recStop && this.recStop();
      // if(this.action == 13 && this.type == 0 && this.result == 0){
        let message = {
          data: 13,
          type: 2317,
        };
        this.mqtt_publish(message);
      // }
    },
    async mqtt_publish(message) {
      if (this.PoliceKey()) {
        let key = await this.PoliceKey();
        this.PagerP1.mqtt.client.publish(
          `SPEAK/OBTAIN/${key}-01`,
          new TextEncoder().encode(JSON.stringify(message)),
          {
            qos: 0,
          },
          (e) => {
            console.log("发送指令成功:", message);
          }
        );
        this.PagerP1.mqtt.client.on("message", (topic, payload, packet) => {
        const data = JSON.parse(packet.payload.toString());
        this.action = data.action;
        this.result = data.result;
        this.type = data.type;
        // console.log(this.action,this.result,this.type);
      });
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.AudioBG {
  width: 100%;
  height: 120px;
  border: 1px solid #3263a5;
}
.bottomBtnBox {
  .btnStyle {
    cursor: pointer;
    border-radius: 50%;
    background: #9bacbe;
    color: #3e495b;
    border: 10px solid #000;
    .bf {
      transform: rotate(90deg);
    }
  }
  .btnStyle:hover {
    color: #43deff;
  }
}
.vish {
  visibility: hidden;
}
.jcenter {
  display: flex;
  justify-content: center;
}
</style>
