nklayman / vue-cli-plugin-electron-builder

Easily Build Your Vue.js App For Desktop With Electron
https://nklayman.github.io/vue-cli-plugin-electron-builder/
MIT License
4.12k stars 278 forks source link

Audio files not playing on production #1798

Open hosnar opened 2 years ago

hosnar commented 2 years ago

I need to implement audio selector with a few different sounds that user can then select. On development it works fine, but when I package app, I am getting this error: MediaError {code: 4, message: "MEDIA_ELEMENT_ERROR: Format error"}

I load sounds with Webpack and I store them to assets/sound folder. When I package app I can see these files in dist_electron/bundled/media. I also tried putting these files to public folder and using /static/sounds path and it didn't work either.

Usage:

// Template
<audio ref="audio" :src="selectedSoundFile" preload id="audio"></audio>

// Computed
selectedSoundFile() {
  if (!this.selectedAlert) return
  return require(`@/assets/sounds/${this.selectedAlert.id}`)
}

// selectedAlert.id example = 'alert-1.mp3' 

I've also tried to import each sound manually, to let Webpack know which files to bundle, but then I get this error: DEMUXER_ERROR_COULD_NOT_OPEN: FFmpegDemuxer: open context failed

My env: "vue-cli-plugin-electron-builder": "^2.0.0" "electron": "^13.6.9"

I would appreciate any help. Thanks

Edit: I've also tried this solution: https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/47#issuecomment-413417255

It again works on development, but on production it tries to load file from this path: file:///app:/sounds/alert-3.mp3

And then it returns this error: MediaError {code: 4, message: "MEDIA_ELEMENT_ERROR: Media load rejected by URL safety check"}

hosnar commented 2 years ago

Adjusting this code https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/872#issuecomment-656292808 for audio files seems to fix the issue. The only weird thing now is that app requires accessibility rights when I hit play sound.

Can anyone confirm this is the correct way to do this?

// Background
function registerLocalAudioProtocol () {
  protocol.registerFileProtocol('local-audio', (request, callback) => {
    const url = request.url.replace(/^local-audio:\/\//, '')
    // Decode URL to prevent errors when loading filenames with UTF-8 chars or chars like "#"
    const decodedUrl = decodeURI(url) // Needed in case URL contains spaces
    try {
      // eslint-disable-next-line no-undef
      return callback(path.join(__static, decodedUrl))
    } catch (error) {
      console.error(
        'ERROR: registerLocalAudioProtocol: Could not get file path:',
        error
      )
    }
  })
}

// Template
return `local-audio://sounds/${this.selectedAlert.id}`
PlatinumHorizon commented 1 year ago

I'm currently facing the same issue. Hit a comment here if you got any solution 😄