Загрузка аудио с помощью URL-адреса Blob в Safari

Следующий код работает в Chrome (22.0), но не в Safari (6.0)

<!DOCTYPE html>
<html>
<head>
<script>
function onGo(e) {
  var fr = new FileReader();
  var file = document.getElementById("file").files[0];
  fr.onload = function(e) {
      var data = new Uint8Array(e.target.result);
      var blob = new Blob([data], {type: 'audio/mpeg'});
      var audio = document.createElement('audio'); 
      audio.addEventListener('loadeddata', function(e) { 
          audio.play();
        }, false);
      audio.addEventListener('error', function(e) {
          console.log('error!', e);
        }, false);
      audio.src = webkitURL.createObjectURL(blob);    
    };
  fr.readAsArrayBuffer(file);
}
</script>
</head>
<body>
  <input type="file" id="file" name="file" />
  <input type="submit" id="go" onclick="onGo()" value="Go" />
</body>
</html>

В Safari не вызывается ни обратный вызов (загруженные данные, ни ошибка). Используемый контент - это mp3 файл, который обычно воспроизводится с помощью звукового тега. Есть ли какой-то особый уход для Safari?

Ответ 1

У меня та же проблема, и я потратил пару дней на устранение неполадок. Как pwray, упомянутых в этом другом сообщении, Safari требует расширения файлов для медиа-запросов:

HTML5 Аудиофайлы не загружаются в Safari

Я попытался сохранить свой blob в файл, назвал его file.mp3, и Safari смог загрузить звук таким образом, но после того, как я переименовал файл, чтобы иметь расширение (просто "файл" ), он не нагрузки. Когда я попробовал url, созданный из blob на другой вкладке Safari:

url = webkitURL.createObjectURL(blob);

он сразу же загружает файл под названием "unknown", но когда я пробовал то же самое в Chrome (также на Mac), он показывал содержимое файла в браузере (mp3 файлы начинаются с ID3, затем куча нечитаемые символы). Я еще не мог понять, как я могу заставить url из blob иметь расширение, потому что обычно это выглядит так:

blob:https://example.com/a7e38943-559c-43ea-b6dd-6820b70ca1e2

поэтому конец его выглядит как переменная сеанса.

Здесь я застрял, и мне бы очень хотелось увидеть решение от некоторых умных людей. Благодаря, Стивен

Ответ 2

Иногда звук HTML5 может просто прекратить загрузку без каких-либо видимых причин. Если вы посмотрите на медиа-события (http://www.w3schools.com/tags/ref_eventattributes.asp), вы увидите событие с именем: onStalled ", определение" Script будет запущено, когда браузер не сможет извлечь медиаданные по какой-либо причине ", и кажется, что это должно быть полезно для вас.

Попробуйте прослушивать это событие и при необходимости перезагружать файл с помощью следующего:

audio.addEventListener('onstalled', function(e) { 
      audio.load();
    }, false);

Надеюсь, это поможет!

Ответ 3

Много лет спустя, я считаю, что пример в ОП должен работать просто отлично. До тех пор, пока вы каким-то образом устанавливаете тип mime при создании большого двоичного объекта, как это делает OP выше со свойством type передаваемых параметров:

new Blob([data], {type: 'audio/mpeg'});

Вы также можете использовать элемент <source> внутри аудио-элемента и установить атрибут type элемента <source>. У меня есть пример этого здесь:

https://lastmjs.github.io/safari-object-url-test

И вот код:

const response = await window.fetch('https://upload.wikimedia.org/wikipedia/commons/transcoded/a/ab/Alexander_Graham_Bell%27s_Voice.ogg/Alexander_Graham_Bell%27s_Voice.ogg.mp3');

const audioArrayBuffer = await response.arrayBuffer();
const audioBlob = new Blob([audioArrayBuffer]);
const audioObjectURL = window.URL.createObjectURL(audioBlob);

const audioElement = document.createElement('audio');

audioElement.setAttribute('controls', true);
document.body.appendChild(audioElement);

const sourceElement = document.createElement('source');

audioElement.appendChild(sourceElement);

sourceElement.src = audioObjectURL;
sourceElement.type = 'audio/mp3';

Я предпочитаю просто устанавливать тип MIME BLOB-объекта при его создании. Атрибут/свойство src элемента <source> не может быть обновлен динамически.