<template>
  <div>
    <h1>音频实时传输</h1>
    <button @click="toggleRecording">
      {{ isRecording ? '停止传输音频' : '开始传输音频' }}
    </button>
    <p>{{ status }}</p>
    <div class="audio-settings">
      <div class="setting-item">
        <label>采样率 (Hz):</label>
        <select v-model="audioConfig.sampleRate"> 
          <option value="8000">8000</option>
          <option value="16000">16000</option>
          <option value="44100">44100</option>
          <option value="48000">48000</option>
        </select>
      </div>
      <div class="setting-item">
        <label>位深度:</label>
        <select v-model="audioConfig.bitsPerSample"> 
          <option value="8">8位</option>
          <option value="16">16位</option>
        </select>
      </div>
      <div class="setting-item">
        <label>通道数:</label>
        <select v-model="audioConfig.channels"> 
          <option value="1">单声道</option>
          <option value="2">双声道</option>
        </select>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      ws: null,  // WebSocket 连接
      mediaRecorder: null,  // MediaRecorder 实例
      audioChunks: [],  // 音频数据
      status: '点击按钮开始传输音频',
      isRecording: false,  // 用于判断是否在录音
      audioConfig: {
        sampleRate: 16000,
        bitsPerSample: 16,
        channels: 1
      },
      stream: null,
      audioContext: null,
      worklet: null,
      // lastSendTime: 0,
      // sendInterval: 200, // 修改为 500ms
    };
  },
  mounted() {
    // 初始化 WebSocket 连接
    this.ws  = new WebSocket('ws://192.168.4.103/ws'); // 替换为 ESP32 IP 地址
    // this.ws = new WebSocket('ws://192.168.1.60:81'); // 替换为您的 ESP32 IP

    this.ws.onopen  = () => {
      console.log('WebSocket 连接已打开');
    };
    this.ws.onmessage  = (event) => {
      console.log(' 接收到来自ESP32的消息:', event.data); 
    };
    this.ws.onclose  = () => {
      console.log('WebSocket 连接已关闭');
    };
  },
  methods: {
    toggleRecording() {
      if (this.isRecording)  {
        // 停止录音
        this.stopRecording(); 
      } else {
        // 开始录音
        this.startRecording(); 
      }
    },
    
    async startRecording() {
      this.status = '开始录音并传输音频...';
      this.isRecording = true;

      const constraints = {
        audio: {
          sampleRate: parseInt(this.audioConfig.sampleRate),
          channelCount: parseInt(this.audioConfig.channels),
          sampleSize: parseInt(this.audioConfig.bitsPerSample)
        }
      };

      try {
        const stream = await navigator.mediaDevices.getUserMedia(constraints);
        
        // 创建 AudioContext
        const audioContext = new AudioContext({
          sampleRate: parseInt(this.audioConfig.sampleRate)
        });
        
        // 加载 AudioWorklet
        await audioContext.audioWorklet.addModule('audio-processor.js');
        
        const source = audioContext.createMediaStreamSource(stream);
        const worklet = new AudioWorkletNode(audioContext, 'audio-processor');
        
        // 监听来自 worklet 的消息
        worklet.port.onmessage = (event) => {
          if (this.ws.readyState === WebSocket.OPEN) {
            // const currentTime = Date.now();
            // if (!this.lastSendTime || currentTime - this.lastSendTime > this.sendInterval) {
              const pcmData = new Int16Array(event.data);
              // 只打印原始数据
              console.log('发送的音频数据:', Array.from(pcmData.slice(0, 20))); // 显示前20个采样点
              this.ws.send(event.data);
              // this.lastSendTime = currentTime;
            // }
          }
        };
        source.connect(worklet);
        worklet.connect(audioContext.destination);

        // 保存引用以便后续停止
        this.stream = stream;
        this.audioContext = audioContext;
        this.worklet = worklet;
      } catch (err) {
        console.error('无法访问麦克风:', err);
        this.status = '访问麦克风失败: ' + err.message;
      }
    },

    stopRecording() {
      this.status = '停止录音';
      this.isRecording = false;

      if (this.stream) {
        this.stream.getTracks().forEach(track => track.stop());
      }
      if (this.worklet) {
        this.worklet.disconnect();
      }
      if (this.audioContext) {
        this.audioContext.close();
      }
    }
  }
};
</script>

<style scoped>
button {
  padding: 10px 20px;
  font-size: 16px;
  cursor: pointer;
}

.audio-settings {
  margin: 20px 0;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

.setting-item {
  margin: 10px 0;
}

.setting-item label {
  margin-right: 10px;
}

select {
  padding: 5px;
  border-radius: 3px;
}
</style>