Recently received a new demand, to achieve the voice reminder of new orders in the PC side and small program side, in fact, many requirements of the front-end is not difficult to achieve, difficult is the limitation of each browser, compatibility is not different, this is no exception.

routine

We all know that HTML5 audio and video have basic attributes like autoplay, for example:

<! -- audio -->
<audio controls autoplay>
  <source src="audio.mp3" type="audio/mp3">
</audio>

<! -- video -->
<video controls autoplay>
  <source src="video.mp4" type="video/mp4">
</video>
Copy the code

Or use JavaScript to control audio and video playback more precisely.

// audio
const audio = new Audio('audio.mp3');
audio.play();

// video
const video = document.createElement('video')
video.src = 'video.mp4';
video.play()
Copy the code

At first glance, there was nothing wrong with it, and the official documentation clearly stated that it was supported, but it was still “too young”, and when the page started to open without any user interaction, Google and Firefox reported an error.

Error as follows:

Google Chrome

Firefox

Google browser prompts are relatively clear, the reason is that users have not yet interacted with Document, this is mainly for user experience issues, so back to the topic, what is the interaction? Both touchStart on the mobile end and MouseDown on the PC end will generate user interaction, provided that it is triggered by the user himself, rather than simulated by JS.

The solution

So now that the browser rules are established (see Google’s Autoplay description), how do we address the requirements and the product managers?

In the author’s opinion, it should be analyzed according to specific needs, such as whether to allow users to interact before playing? So just listen for the Document touchStart or mouseDown event and play it; Or generally we are doing a single page website, just need to log in, so the interaction will be generated in advance, there is no problem.

Back to the requirement mentioned at the beginning of the article, it is basically the second case mentioned above, which requires automatic play, and viewing orders requires login. At first glance, it seems that there is no problem, but there is another problem. User login will have a login expiration rule, the time is generally set at about 30 minutes. If the user just logs out on this page, the login will directly jump to the order list page after the timeout. At this time, the user just waits and does not do any operation, so the audio reminder we made is not reliable.

There are two solutions at this point

  1. After login, intercept a specific URL and redirect it to a page adjacent to the URL;
  2. Give user friendly prompts using the methods described in the Autoplay documentation above;

The second way is as follows

const promise = audio.play();

if(promise ! = =undefined) {
  promise.then(res= > {
   // Playback succeeded
  }).catch(error= > {
   // Remind the user to click activate play and view the new order
  });
}
Copy the code

Since the Play () method returns an instance of a Promise, you can listen for its success or failure to know the result and do something about it. For “click to activate,” it doesn’t matter where you click.

The above is some “curve to save the country” scheme, although not perfect, but I believe that the product manager can understand, after all, browser rules are not our front-end development can easily change 😂. If anyone has a better solution, I hope you can share it to help solve this auto-play puzzle.

Some other problem solving apis

Using AudioContext for audio playback was found to be more compatible, and although it did not solve the auto-play problem in Google Chrome, it played properly in Firefox, while not tested in other browsers or on mobile.

Google Browser reported the following error

Sample code (relatively new API, not recommended)

// Note: Resource files must be supported across domains
(async() = > {const audioCtx = new AudioContext();
  const source = audioCtx.createBufferSource();

  const getData = async() = > {const myRequest = new Request("audio.mp3");

    await fetch(myRequest).then((response) = > {
      response.arrayBuffer().then((buffer) = > {
        audioCtx.decodeAudioData(buffer, (decodedData) = > {
          source.buffer = decodedData;
          source.connect(audioCtx.destination);
        });
      });
    });
  };

  getData();
  source.start(0); }) ();Copy the code

Using the example above, the audio can be played directly in some browsers.

Automatic audio/video playback in small programs

Small program official documentation is introduced, here is not to say.

Reference code

// audio
const innerAudioContext = wx.createInnerAudioContext()
innerAudioContext.src = 'audio.mp3'
innerAudioContext.play();

// video
<video src="video.mp4" controls autoplay="{{true}}" />
Copy the code

A little digression

At the end of his journey, the clouds rose and fell.

Sometimes entangled in the quagmire of technology, repeatedly not its place, suddenly passed, the past ups and downs are a scenery, worth recalling, to gratified with a heart to search up and down.