Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.

No sound on iOS Safari. #67

Open
dkwasniewski opened this issue Aug 11, 2020 · 2 comments
Open

No sound on iOS Safari. #67

dkwasniewski opened this issue Aug 11, 2020 · 2 comments

Comments

@dkwasniewski
Copy link

dkwasniewski commented Aug 11, 2020

Hello
I am experiencing weird issue on iOS Safari. Audio seems to be recorded - time of audio is also compatible to its recording length but still with no sound. Manipulating native controls does not take any effect. I have made an attempt by switching package version into "audio-recorder-polyfill": "ai/audio-recorder-polyfill" as suggested in topic: #24 but no luck with this as well. Here is short summary of what I am trying to achieve. So basically simple click on button is triggering MediaRecorder. It is happening in parallel with Azure's Speech Recognizer SDK:

// first click
const startSpeechRecognition = ({ callback, key, token }) => {
  const speechConfig = SpeechSDK.SpeechConfig.fromAuthorizationToken(token, SPEECH_REGION)
  speechConfig.speechRecognitionLanguage = SPEECH_RECOGNITION_LANG
  const audioConfig = SpeechSDK.AudioConfig.fromDefaultMicrophoneInput()
  const recognizer = new SpeechSDK.SpeechRecognizer(speechConfig, audioConfig)
  const recorder = setupRecorder(callback)

  return new Promise((resolve, reject) => {
    recognizer.startContinuousRecognitionAsync(
      () => recorder.then((r) => {
        r.recorder.start()
        resolve({
          recognizer,
          recorder
        })
      }),
      err => reject(err)
    )
  })
}

Internal call of setupRecorder(callback) is defined as below:

const setupRecorder = callback => navigator.mediaDevices
  .getUserMedia({ audio: true })
  .then((stream) => {
    const data = []
    const recorder = new MediaRecorder(stream)
    recorder.addEventListener(MEDIA_EVENT.START, (e) => {
      data.length = 0
    })
    recorder.addEventListener(MEDIA_EVENT.DATA_AVAILABLE, (e) => {
      data.push(e.data)
    })
    recorder.addEventListener(MEDIA_EVENT.STOP, () => {
      callback(data)
      recorder.stream.getTracks().forEach(track => track.stop())
    })

    return { recorder }
  })

Second click on button triggers stop for Speech Recognizer and MediaRecorder stop event

// second click
const stopSpeechRecognition = ({ recognizer, recorder }) => new Promise((resolve, reject) => {
  recognizer.stopContinuousRecognitionAsync(
    () => resolve(recorder.then(r => r.recorder.stop())),
    err => reject(err)
  )
})

So callback from "stop" MediaRecorder event handler is invoked with stream data which later is parsed into Blob.

// callback is defined inside Vue's component instance, so that's why you see "this" here
const callback = (data) => {
  const audio = speechService.getAudioData({
    data,
    format: this.audioData.format,
    userId: this.selectUserId()
  })
  this.audioData = {
    ...this.audioData,
    ...audio
  }
}

// and in speechService:
const getAudioData = ({ data, format }) => {
  if (!data) { return }

  const blob = new Blob(data, { type: format })
  const blobUrl = window.URL.createObjectURL(blob)

  return {
    blob,
    blobUrl,
    type: format
  }
}

For an iOS Safari I am using default wav format as pointed in docs.
Any tips what could be wrong?

@ai
Copy link
Owner

ai commented Aug 11, 2020

Sorry. I am accepting only pull requests.

@dkwasniewski
Copy link
Author

As long I don't know cause of the issue how can I rise pull request :(

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants