Yet another workaround for autoplay issues

This commit is contained in:
prlanzarin 2019-07-25 17:36:19 +00:00
parent 90cbb8b597
commit 39cf33b194
4 changed files with 80 additions and 16 deletions

View File

@ -64,7 +64,14 @@ export default class KurentoAudioBridge extends BaseAudioBridge {
audioTag.pause();
audioTag.srcObject = stream;
audioTag.muted = false;
audioTag.play();
audioTag.play().catch((e) => {
const tagFailedEvent = new CustomEvent('mediaTagPlayFailed', { detail: { mediaTag: audioTag } });
window.dispatchEvent(tagFailedEvent);
logger.warn({
logCode: 'sfuaudiobridge_play_error',
extraInfo: { error: e },
}, 'Could not play audio tag, emit mediaTagPlayFailed event');
});
}
resolve(this.callback({ status: this.baseCallStates.started }));
};

View File

@ -21,6 +21,56 @@ export default class Media extends Component {
constructor(props) {
super(props);
this.refContainer = React.createRef();
this.failedTags = [];
this.listeningToTagPlayFailed = false;
this.monitorMediaTagPlayFailures();
}
monitorMediaTagPlayFailures() {
const handleFailTagEvent = (e) => {
e.stopPropagation();
this.failedTags.push(e.detail.mediaTag);
if (!this.listeningToTagPlayFailed) {
this.listeningToTagPlayFailed = true;
// Monitor user action events so we can play and flush all the failed tags
// in the queue when the user performs one of them
window.addEventListener('click', flushFailedTags);
window.addEventListener('auxclick', flushFailedTags);
window.addEventListener('keydown', flushFailedTags);
window.addEventListener('touchstart', flushFailedTags);
}
}
const flushFailedTags = () => {
window.removeEventListener('click', flushFailedTags);
window.removeEventListener('auxclick', flushFailedTags);
window.removeEventListener('keydown', flushFailedTags);
window.removeEventListener('touchstart', flushFailedTags);
while (this.failedTags.length) {
const mediaTag = this.failedTags.shift();
if (mediaTag) {
mediaTag.play().catch(e => {
// Ignore the error for now.
});
}
};
this.listeningToTagPlayFailed = false;
}
// Monitor tag play failure events, probably due to autoplay. The callback
// puts the failed tags in a queue which will be flushed on a user action
// by the listeners created @handleFailTagEvent. Once the queue is flushed, all
// user action listeners are removed since the autoplay restriction should be over.
// Every media tag in the app should have a then/catch handler and emit
// this event accordingly so we can try to circumvent autoplay without putting
// a UI block/prompt.
// If a tag fail to play again for some odd reason, the listeners will be
// reattached (see this.listeningToTagPlayFailed) and flushFailedTags runs again
window.addEventListener("mediaTagPlayFailed", handleFailTagEvent);
}
componentWillUpdate() {

View File

@ -58,16 +58,14 @@ class VideoListItem extends Component {
componentDidUpdate() {
const playElement = (elem) => {
if (elem.paused) {
const p = elem.play();
if (p && (typeof Promise !== 'undefined') && (p instanceof Promise)) {
// Catch exception when playing video
p.catch((e) => {
logger.warn({
logCode: 'videolistitem_component_play_error',
extraInfo: { error: e },
}, 'Could not play video');
});
}
elem.play().catch((error) => {
const tagFailedEvent = new CustomEvent('mediaTagPlayFailed', { detail: { mediaTag: elem } });
window.dispatchEvent(tagFailedEvent);
logger.warn({
logCode: 'videolistitem_component_play_error',
extraInfo: { error },
}, 'Could not play video tag, emit mediaTagPlayFailed event');
});
}
};

View File

@ -325,11 +325,20 @@ function WebRtcPeer(mode, options, callback) {
const MAX_RETRIES = 5;
let attempt = 0;
const playVideo = () => {
if (!played && attempt < MAX_RETRIES) {
remoteVideo.play().catch(e => {
attempt++;
playVideo(remoteVideo);
}).then(() => { remoteVideo.muted = false; played = true; attempt = 0;});
if (!played) {
if (attempt < MAX_RETRIES) {
remoteVideo.play()
.then(() => { remoteVideo.muted = false; played = true; attempt = 0;})
.catch(e => {
attempt++;
setTimeout(() => {
playVideo(remoteVideo);
}, 500);
});
} else {
const tagFailedEvent = new CustomEvent('mediaTagPlayFailed', { detail: { mediaTag: remoteVideo } });
window.dispatchEvent(tagFailedEvent);
}
}
}