通过RapidApi实现MediaRecorder和Shazam API的问题

问题描述 投票:0回答:1

我目前正在开展一个学校项目,其中我正在创建 Shazam 的一种克隆版本。 我现在可以成功录制音频,并将其解码为 Base64 字符串,就像 api 所要求的那样,但它无法识别任何歌曲,因为这可能是错误的解码过程或错误的录制过程。 目前,我正在手动将数据插入 api,因此不存在连接问题。

这就是 api 的要求: 从小于 500KB 的原始数据生成的 byte[] 的 Base64 编码字符串(3-5 秒的样本足以用于检测)。原始声音数据必须是 44100Hz、1 通道(单声道)、带符号的 16 位 PCM 小端。不支持其他类型的媒体,例如:mp3、wav、e...

我有一个 AudioRecorder 类来处理音频的录制:

override fun start(outputFile: File) {
        createRecorder().apply {
            setAudioSource(MediaRecorder.AudioSource.MIC)
            setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
            setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
            setAudioChannels(1)
            setAudioSamplingRate(44100)
            setAudioEncodingBitRate(16 * 44100)
            setOutputFile(outputFile.absolutePath)

            prepare()
            start()

            recorder = this
        }
    }

    override fun stop() {
        recorder?.stop()
        recorder?.reset()
        recorder = null
    }

    fun readAudioFile(file: File): ByteArray {
        return file.readBytes()
    }

然后我有一个处理我的录音的函数,它也会在正确的时间执行

private suspend fun launchAudioRecording(audioRecorder: AudioRecorder, context: Context): String {
    Log.d("be.howest.rythmradar.ui.SearchingSongScreen", "be.howest.rythmradar.ui.launchAudioRecording - Start")
    // Start recording
    File(context.cacheDir, "audio.3gp").also {
        audioRecorder.start(it)
        audioFile = it
    }

    // Delay for 5 seconds to record audio
    delay(5000)

    // Stop recording
    audioRecorder.stop()

    // Do something with the recorded audio, such as converting it to Base64 string
    val audioData = audioRecorder.readAudioFile(audioFile!!)
    val base64String = convertToBase64String(audioData)
    
    return base64String
}

最后是我的 base64string 转换器:

private fun convertToBase64String(audioData: ByteArray): String {
    return Base64.encodeToString(audioData, Base64.DEFAULT)
}
android-jetpack-compose android-mediarecorder rapidapi
1个回答
0
投票

我最近参与了一个类似的项目。 RapidApi 也不适合我,但AudDApi!做。我设法通过将其值设置为 base64String 并将其传递给 AudDApi,将其保存到隐藏的表单输入元素中,效果非常好。但是,录音时间不得超过 5 秒,否则会导致负载错误。

您可以尝试下面的代码来调整您的录音和base65String。

    <div>
  <form action="/" method="post">
    <input id="audioString" hidden />
    <button type="submit">Fetch</button>
  </form>
</div>

    <script type="text/javascript">
  class VoiceRecorder {
    constructor() {
      if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        console.log("getUserMedia supported");
      } else {
        console.log("getUserMedia is not supported on your browser!");
      }

      this.mediaRecorder;
      this.stream;
      this.chunks = [];
      this.isRecording = false;

      this.recorderRef = document.querySelector("#recorder");
      this.playerRef = document.querySelector("#player");
      this.startRef = document.querySelector("#start");
      this.stopRef = document.querySelector("#stop");

      this.startRef.onclick = this.startRecording.bind(this);
      this.stopRef.onclick = this.stopRecording.bind(this);

      this.constraints = {
        audio: true,
        video: false,
      };
    }

    handleSuccess(stream) {
      this.stream = stream;
      this.stream.oninactive = () => {
        console.log("Stream ended!");
      };
      this.recorderRef.srcObject = this.stream;
      this.mediaRecorder = new MediaRecorder(this.stream);
      console.log(this.mediaRecorder);
      this.mediaRecorder.ondataavailable =
        this.onMediaRecorderDataAvailable.bind(this);
      this.mediaRecorder.onstop = this.onMediaRecorderStop.bind(this);
      this.recorderRef.play();
      this.mediaRecorder.start();
    }

    handleError(error) {
      console.log("navigator.getUserMedia error: ", error);
    }

    onMediaRecorderDataAvailable(e) {
      this.chunks.push(e.data);
    }

    onMediaRecorderStop(e) {
      const blob = new Blob(this.chunks, { type: "audio/ogg; codecs=opus" });
      const audioURL = window.URL.createObjectURL(blob);
      this.playerRef.src = audioURL;
      this.chunks = [];
      this.stream.getAudioTracks().forEach((track) => track.stop());
      this.stream = null;
      var reader = new FileReader();
      reader.readAsDataURL(blob);
      reader.onloadend = function () {
        var base64String = reader.result;
        base64String = base64String.substring(base64String.indexOf(',') + 1);
        document.querySelector("#audioString").value = base64String;
      };
    }

    startRecording() {
      if (this.isRecording) return;
      this.isRecording = true;
      this.startRef.innerHTML =
        '<em>Recording <span class="material-symbols-outlined listen">noise_aware</span></em>';
      this.playerRef.src = "";
      navigator.mediaDevices
        .getUserMedia(this.constraints)
        .then(this.handleSuccess.bind(this))
        .catch(this.handleError.bind(this));
    }

    stopRecording() {
      if (!this.isRecording) return;
      this.isRecording = false;
      this.startRef.innerHTML =
        "<span class='material-symbols-outlined'>mic</span>";
      this.recorderRef.pause();
      this.mediaRecorder.stop();
    }
  }
  window.voiceRecorder = new VoiceRecorder();
</script>
© www.soinside.com 2019 - 2024. All rights reserved.