Использование локального файла для Web Audio API в Javascript
Я пытаюсь заставить звук работать в моей игре для iPhone с помощью API Web Audio. Проблема в том, что это приложение полностью на стороне клиента. Я хочу хранить свои 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. Uncaught Ошибка: NETWORK_ERR: исключение XMLHttpRequest 101
Я понимаю риски безопасности при чтении локальных файлов, но в вашем собственном домене все должно быть в порядке?
4 ответа
У меня была такая же проблема, и я нашел это очень простое решение.
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" />
Вы можете проверить здесь: http://jsfiddle.net/Tv8Cm/
Хорошо, у меня ушло два дня на создание прототипа различных решений, и я наконец понял, как я могу это сделать, не сохраняя свои ресурсы на сервере. Есть несколько блогов, которые подробно описывают это, но я не смог найти полное решение в одном месте, поэтому я добавляю его здесь. Опытные программисты могут посчитать это немного хакерским, но это единственный способ увидеть, как это работает, поэтому, если у кого-то есть более изящное решение, я бы хотел услышать его.
Решением было сохранить мои звуковые файлы в виде строки в кодировке Base64. Звуковые файлы относительно небольшие (менее 30 КБ), поэтому я надеюсь, что производительность не будет слишком большой проблемой. Обратите внимание, что я поставил "xxx" перед некоторыми гиперссылками, так как мой статус n00b означает, что я не могу опубликовать более двух ссылок.
Шаг 1: создайте звуковой шрифт Base 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's destination (the speakers)
source.noteOn(0);
}, function(err) { console.log("err(decodeAudioData): "+err); });
И это все! У меня это работает через настольную версию Chrome, а также работает на мобильном Safari (конечно, только для iOS 6, так как Web Audio не поддерживается в более старых версиях). Загрузка в Safari для мобильных устройств занимает пару секунд (против настольного Chrome менее 1 секунды), но это может быть связано с тем, что он тратит время на загрузку звуковых шрифтов. Это также может быть тот факт, что iOS предотвращает воспроизведение звука, пока не произойдет событие взаимодействия с пользователем. Мне нужно больше работать, глядя на то, как это работает.
Надеюсь, это спасет кого-то еще от горя, через которое я прошел.
Поскольку приложения ios находятся в "песочнице", веб-представление (в основном сафари, обернутое в телефонную пробку) позволяет вам хранить ваш mp3-файл локально. То есть, нет проблемы безопасности "междоменного".
Начиная с ios6, так как предыдущие версии ios не поддерживали веб-аудио API
Используйте HTML5 Audio tag для воспроизведения аудио файла в браузере.
Ajax-запрос работает с протоколом http, поэтому, когда вы пытаетесь получить аудиофайл, используя file://, браузер помечает этот запрос как междоменный запрос. Установите следующий код в заголовке запроса -
header('Access-Control-Allow-Origin: *');