IE 9 and 10 yield unexpected and inconsistent Medi

2019-06-21 05:32发布

问题:

We have a set of HTML blocks -- say around 50 of them -- which are iteratively parsed and have Audio objects dynamically added:

var SomeAudioWrapper = function(name) {

  this.internal_player = new Audio();

  this.internal_player.src = this.determineSrcFromName(name);
     // ultimately an MP3

  this.play = function() {
    if (someOtherConditionsAreMet()) {
      this.internal_player.play();
    }
  }

}

Suppose we generate about 40 to 80 of these on page load, but always the same set for a particular configuration. In all browsers tested, this basic strategy appears to work. The audio load and play successfully.

In IE's 9 and 10, a transient bug surfaces. On occasion, calling .play() on the inner Audio object fails. Upon inspection, the inner Audio object has a .error.code of 4 (MEDIA_ERR_SRC_NOT_SUPPORTED). The file's .duration shows NaN.

However, this only happens occasionally, and to some random subset of the audio files. E.g., usually file_abc.mp3 plays, but sometimes it generates the error. The network monitor shows a successful download in either case. And attempting to reload the file via the console also fails -- and no requests appears in IE's network monitor:

var a = new Audio();
a.src = "the_broken_file.mp3";
a.play(); // fails
a.error.code; // 4

Even appending a query value fails to refetch the audio or trigger any network requests:

var a = new Audio();
a.src = "the_broken_file.mp3?v=12345";
a.play(); // fails
a.error.code; // 4

However, attempting the load the broken audio file in a new tab using the same code works: the "unsupported src" plays perfectly.

Are there any resource limits we could be hitting? (Maybe the "unsupported" audio finishes downloading late?) Are there any known bugs? Workarounds?

I think we can pretty easily detect when a file fails. For other compatibility reasons we run a loop to check audio progress and completion stats to prevent progression through the app (an assessment) until the audio is complete. We could easily look for .error values -- but if we find one, what do we do about it!?

Addendum: I just found a related question (IE 9/10/11 sound file limit) that suggests there's an undocumented limit of 41 -- not sure whether that's a limit of "41 requests for audio files", "41 in-memory audio objects", or what. I have yet to find any M$ documentation on the matter -- or known solutions.

回答1:

Have you seen these pages on the audio file limits within IE? These are specific to Sound.js, but the information may be applicable to your issue:

https://github.com/CreateJS/SoundJS/issues/40 ...

Possible solution as mentioned in the last comment: "control the maximum number of audio tags depending on the platform and reuse these instead of recreating them"

Additional Info: http://community.createjs.com/kb/faq/soundjs-faq (see the section entitled “I load a lot of sounds, why am running into errors in Internet Explorer?”)



回答2:

I have not experienced this problem in Edge or IE11. But, I wrote a javascript file to run some tests by looping through 200 audio files and seeing what happens. What I found is that the problem for IE9 and IE10 is consistent between ALL tabs. So, you are not even guaranteed to be able to load 41 files if other tabs have audio opened.

The app that I am working on has a custom sound manager. Our solution is to disable preloading audio for IE9 and IE10 (just load on demand) and then when the onended or onpause callback gets triggered, to run:

this.src = '';

This will free up the number of audio that are contained in IE. Although I should warn that it may make a request to the current page the user is on. When the play method in the sound manager is called again, set the src and play it.

I haven't tested this code, but I wrote something similar that works. What I think you could do for your implementation, is resolve the issue by using a solution like this:

var isIE = window.navigator.userAgent.match(/MSIE (9|10)/);

var SomeAudioWrapper = function(name) {
  var src = this.determineSrcFromName(name);

  this.internal_player = new Audio();

  // If the browser is IE9 or IE10, remove the src when the
  // audio is paused or done playing. Otherwise, set the src
  // at the start.
  if (isIE) {
    this.internal_player.onended = function() {
      this.src = '';
    };
    this.internal_player.onpause = this.internal_player.onended;
  } else {
    this.internal_player.src = src;
  }

  this.play = function() {
    if (someOtherConditionsAreMet()) {
      // If the browser is IE, set the src before playing.
      if (isIE) {
          this.internal_player.src = src;
      }

      this.internal_player.play();
    }
  }

}