Использование локального файла для API веб-аудио в Javascript
Я пытаюсь получить звук, работающий над своей игрой iPhone, используя API веб-аудио. Проблема в том, что это приложение полностью на стороне клиента. Я хочу хранить мои mp3 файлы в локальной папке (и без ввода пользовательского ввода), поэтому я не могу использовать XMLHttpRequest для чтения данных. Я изучал использование FileSystem, но Safari не поддерживает его.
Есть ли альтернатива?
Изменить: Спасибо за ответы ниже. К сожалению, Audio API ужасно медленный для игр. У меня была эта работа, и задержка просто сделала пользователя неприемлемым. Чтобы уточнить, что мне нужно, это что-то похожее -
var request = new XMLHttpRequest();
request.open('GET', 'file:///./../sounds/beep-1.mp3', true);
request.responseType = 'arraybuffer';
request.onload = function() {
context.decodeAudioData(request.response, function(buffer) {
dogBarkingBuffer = buffer;
}, onError);
}
request.send();
Но это дает мне ошибки -
XMLHttpRequest не может загрузить файл:///sounds/beep-1.mp3. Запросы на кросс-начало поддерживаются только для HTTP.
Ошибка поиска: NETWORK_ERR: Исключение XMLHttpRequest 101
Насколько я понимаю, риски безопасности при чтении локальных файлов, но, безусловно, в вашем собственном домене должны быть в порядке?
Ответы
Ответ 1
У меня была та же проблема, и я нашел это очень простое решение.
audio_file.onchange = function(){
var files = this.files;
var file = URL.createObjectURL(files[0]);
audio_player.src = file;
audio_player.play();
};
<input id="audio_file" type="file" accept="audio/*" />
<audio id="audio_player" />
Ответ 2
Хорошо, мне потребовалось два дня прототипирования различных решений, и я, наконец, понял, как я могу это сделать, не сохраняя свои ресурсы на сервере. Там несколько блогов, которые подробно описывают это, но я не мог найти полное решение в одном месте, поэтому я добавляю его здесь. Это можно считать немного взломанным опытными программистами, но это единственный способ увидеть, как это работает, поэтому, если у кого-то есть более элегантное решение, я бы хотел его услышать.
Решение заключалось в том, чтобы сохранить мои звуковые файлы в виде кодированной в Base64 строки. Звуковые файлы относительно малы (менее 30 КБ), поэтому я надеюсь, что производительность не будет слишком большой проблемой. Обратите внимание, что я помещал "xxx" перед некоторыми гиперссылками, так как мой статус n00b означает, что я не могу разместить более двух ссылок.
Шаг 1: создайте звуковой шрифт базы 64
Сначала мне нужно преобразовать свой mp3 в кодировку Base64 и сохранить ее как JSON. Я нашел сайт, который делает это преобразование для меня здесь - xxxhttp://www.mobilefish.com/services/base64/base64.php
Возможно, вам придется удалить возвращаемые символы с помощью текстового редактора, но для тех, кому нужен пример, я нашел здесь несколько фортепианных тонов - xxxhttps://raw.github.com/mudcube/MIDI.js/master/soundfont/acoustic_grand_piano-mp3.js
Обратите внимание, что для работы с моим примером вам необходимо удалить данные части заголовка: audio/mpeg; base64,
Шаг 2. Декодирование звукового шрифта в ArrayBuffer
Вы могли бы реализовать это самостоятельно, но я нашел API, который делает это отлично (зачем изобретать колесо, правильно?) - https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js
Ресурс взят из - здесь
Шаг 3: добавление остальной части кода
Довольно простой
var cNote = acoustic_grand_piano.C2;
var byteArray = Base64Binary.decodeArrayBuffer(cNote);
var context = new webkitAudioContext();
context.decodeAudioData(byteArray, function(buffer) {
var source = context.createBufferSource(); // creates a sound source
source.buffer = buffer;
source.connect(context.destination); // connect the source to the context destination (the speakers)
source.noteOn(0);
}, function(err) { console.log("err(decodeAudioData): "+err); });
И это! У меня это работает через мою настольную версию Chrome, а также работает на мобильном Safari (iOS 6, конечно, поскольку Web Audio не поддерживается в более старых версиях). Загрузка на мобильный Safari (не менее 1 секунды на настольном Chrome) занимает пару секунд, но это может быть связано с тем, что он тратит время на загрузку звуковых шрифтов. Также может случиться так, что iOS не позволяет воспроизводить звук до тех пор, пока не произойдет событие взаимодействия с пользователем. Мне нужно сделать больше работы, глядя на то, как она работает.
Надеюсь, это спасет кого-то еще от горя, которое я пережил.
Ответ 3
Поскольку приложения ios изолированы песочницей, веб-просмотр (в основном сафари, завернутый в телефонную заставку) позволяет вам хранить ваш mp3 файл локально. I.e, проблема защиты "кросс-домена" отсутствует.
Это относится к ios6, поскольку предыдущие версии ios не поддерживали веб-аудио api
Ответ 4
Используйте HTML5 Audio tag для воспроизведения аудиофайла в браузере.
Ajax-запрос работает с протоколом http, поэтому, когда вы пытаетесь получить аудиофайл с помощью файла://, браузер помечает этот запрос как запрос перекрестного домена. Задайте следующий код в заголовке запроса -
header('Access-Control-Allow-Origin: *');