Fixes WebAudio sink not playing on Safari (#1765)
Fixes #1717.
Safari (and Chrome possibly as well) requires a user interaction after a
web audio stream has been requested, which means audio will not play
until at least one stream has been started and then the user clicks
somewhere in the web app.
This implements a workaround
(https://www.mattmontag.com/web/unlock-web-audio-in-safari-for-ios-and-macos)
which unlocks and stores the AudioContext globally, so that after the
first stream only a single interaction is required for the lifetime of
that browser session.
Signed-off-by: Dan Cunningham <dan@digitaldan.com>
(cherry picked from commit b90cbc47f2
)
3.4.x
parent
6ce395b9ed
commit
7121d09913
|
@ -286,6 +286,7 @@ export default {
|
|||
init: false,
|
||||
ready: false,
|
||||
eventSource: null,
|
||||
audioContext: null,
|
||||
|
||||
// Framework7 Parameters
|
||||
f7params: {
|
||||
|
@ -620,29 +621,35 @@ export default {
|
|||
this.eventSource = null
|
||||
},
|
||||
playAudioUrl (audioUrl) {
|
||||
let context
|
||||
try {
|
||||
window.AudioContext = window.AudioContext || window.webkitAudioContext
|
||||
if (typeof (window.AudioContext) !== 'undefined') {
|
||||
context = new AudioContext()
|
||||
if (!this.audioContext) {
|
||||
window.AudioContext = window.AudioContext || window.webkitAudioContext
|
||||
if (typeof (window.AudioContext) !== 'undefined') {
|
||||
this.audioContext = new AudioContext()
|
||||
unlockAudioContext(this.audioContext)
|
||||
}
|
||||
}
|
||||
console.log('Playing audio URL: ' + audioUrl)
|
||||
this.$oh.api.getPlain(audioUrl, '', '*/*', 'arraybuffer').then((data) => {
|
||||
context.decodeAudioData(data, function (buffer) {
|
||||
let source = context.createBufferSource()
|
||||
this.audioContext.decodeAudioData(data, (buffer) => {
|
||||
let source = this.audioContext.createBufferSource()
|
||||
source.buffer = buffer
|
||||
source.connect(context.destination)
|
||||
source.onended = function () {
|
||||
context.close()
|
||||
}
|
||||
source.connect(this.audioContext.destination)
|
||||
source.start(0)
|
||||
})
|
||||
})
|
||||
} catch (e) {
|
||||
console.warn('Error while playing audio URL: ' + e.toString())
|
||||
if (context) {
|
||||
context.close()
|
||||
}
|
||||
}
|
||||
// Safari requires a touch event after the stream has started, hence this workaround
|
||||
// Credit: https://www.mattmontag.com/web/unlock-web-audio-in-safari-for-ios-and-macos
|
||||
function unlockAudioContext (audioContext) {
|
||||
if (audioContext.state !== 'suspended') return
|
||||
const b = document.body
|
||||
const events = ['touchstart', 'touchend', 'mousedown', 'keydown']
|
||||
events.forEach(e => b.addEventListener(e, unlock, false))
|
||||
function unlock () { audioContext.resume().then(clean) }
|
||||
function clean () { events.forEach(e => b.removeEventListener(e, unlock)) }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue