fix autoplay.

This commit is contained in:
Miroslav Šedivý 2023-05-01 00:29:26 +02:00
parent 645c4aa184
commit 13caeb3746

View File

@ -1,7 +1,7 @@
<template> <template>
<div ref="component" class="neko-component"> <div ref="component" class="neko-component">
<div ref="container" class="neko-container"> <div ref="container" class="neko-container">
<video ref="video" :autoplay="autoplay" :muted="autoplay" playsinline /> <video ref="video" playsinline />
<neko-screencast <neko-screencast
v-show="screencast && screencastReady" v-show="screencast && screencastReady"
:image="fallbackImage" :image="fallbackImage"
@ -407,8 +407,31 @@
this.connection.reloadConfigs() this.connection.reloadConfigs()
} }
public play() { public async play() {
this._video.play() // if autoplay is disabled, play() will throw an error
// and we need to properly save the state otherwise we
// would be thinking we're playing when we're not
try {
await this._video.play()
} catch (e: any) {
if (this._video.muted) {
throw e
}
// video.play() can fail if audio is set due restrictive
// browsers autoplay policy -> retry with muted audio
try {
this._video.muted = true
await this._video.play()
// unmute on users first interaction
document.addEventListener('click', this.autoUnmute, { once: true })
this.control.once('overlay.click', this.autoUnmute)
} catch (e: any) {
// if it still fails, we're not playing anything
this._video.muted = false
throw e
}
}
} }
public pause() { public pause() {
@ -423,6 +446,16 @@
this._video.muted = false this._video.muted = false
} }
// when autoplay fails, we mute the video and wait for the user
// to interact with the page to unmute it again
public autoUnmute() {
this.unmute()
// remove listeners
document.removeEventListener('click', this.autoUnmute)
this.control.removeListener('overlay.click', this.autoUnmute)
}
public setVolume(value: number) { public setVolume(value: number) {
if (value < 0 || value > 1) { if (value < 0 || value > 1) {
throw new Error('volume must be between 0 and 1') throw new Error('volume must be between 0 and 1')
@ -557,7 +590,7 @@
this.fallbackImage = image this.fallbackImage = image
// this ensures that fallback mode starts immediatly // this ensures that fallback mode starts immediatly
this._video.pause() this.pause()
}) })
this.connection.webrtc.on('track', (event: RTCTrackEvent) => { this.connection.webrtc.on('track', (event: RTCTrackEvent) => {
@ -577,17 +610,12 @@
} }
if (this.autoplay || this.connection.activated) { if (this.autoplay || this.connection.activated) {
this._video.play() this.play()
} }
}, },
{ once: true }, { once: true },
) )
}) })
// unmute on users first interaction
if (this.autoplay) {
document.addEventListener('click', this.unmute, { once: true })
}
} }
beforeDestroy() { beforeDestroy() {
@ -595,8 +623,8 @@
this.connection.destroy() this.connection.destroy()
this.clear() this.clear()
// remove users first interaction event // removes users first interaction events
document.removeEventListener('click', this.unmute) this.autoUnmute()
} }
@Watch('controlling') @Watch('controlling')