HTML 5/QuickTime аудио кеширование в Safari на iOS
Я отчаянно пытаюсь найти решение для веб-приложения, которое должно запускаться на iOS-Safari (например, на iPad, iPad2 и iPhone 4):
Это веб-приложение, которое я написал некоторое время назад, которое позволяет пользователю искать и прослушивать короткие музыкальные сэмплы (MP3, все от ~ 100 кБ до ~ 1,5 МБ). Звуковой проигрыватель основан на Flash, поэтому он не работает на iOS-устройствах в данный момент, и мне придется реализовать альтернативу либо в HTML 5, либо с помощью "прямого" объекта QuickTime.
Оба моих HTML 5- и QuickTime-альтернативы для iOS-устройств работают до сих пор, но есть одна серьезная проблема, с которой я не могу найти решение:
В отличие от Flash, и большинство браузеров с поддержкой HTML 5 в Safari на моем iPad 2 не будут хранить аудиофайлы в браузерах после загрузки и воспроизведения их - ни с аудио-тегами HTML 5, ни с QuickTime-Object. Каждый раз, когда я загружаю аудиофайл для воспроизведения с сервера (с помощью JavaScript-команд, поэтому без изменения или перезагрузки всей страницы), он полностью загружается.
Если пользователь прослушивает образец A, а затем образец B, Safari забыл о том, что сыграл образец A, и снова загружает весь MP3, если мне нравится его слушать снова. На мобильном устройстве с потенциально узкой полосой с таким поведением не может быть и речи.
Есть ли способ сохранить загруженные аудиофайлы, открытые HTML 5 или QuickTime в кеше Safari, чтобы он помнил, что уже загрузил их - например, он кэширует обычные "веб файлы", такие как HTML, CSS или JPEG-изображения, или как Flash-магазины такие объекты в локальном кеше?
Моя первая попытка заключалась в попытке использовать кэш приложений с файлом манифеста - хотя это не является целью для моего приложения... У меня нет статического набора файлов, которые я хочу использовать в кешировании или "доступный в автономном режиме" - я просто хочу кэшировать MP3 файлы, которые пользователь еще играл.
Должно быть возможно использовать "динамический манифест": один, который анализируется модулем Apache PHP и перечисляет файлы, которые были воспроизведены до сих пор из сеанса PHP - примерно так:
session_start();
header("Content-Type: text/cache-manifest, charset=UTF-8");
echo "CACHE MANIFEST\n";
foreach($_SESSION['playedSongs'] as $song)
{
echo $song."\n";
}
Поэтому всякий раз, когда песня загружается/воспроизводится, я могу получить доступ к сеансу PHP с помощью AJAX, вставить имя файла воспроизводимого файла и вручную обновить манифест, вызывая window.applicationCache.update() или .swapCache().
Есть две проблемы с этим:
Прежде всего: он не работает. И я даже не дошел до того, чтобы использовать динамический манифест:
<!DOCTYPE html>
<html manifest="cache.manifest">
<head>
<title>Test</title>
<script type="text/javascript">
function playStuff(id)
{
if(id == 1)
{
window.document.getElementById("audio").innerHTML = '<audio controls preload="automatic" autobuffer><source src="song01.mp3" type="audio/mp3" /></audio>';
}
else if(id == 2)
{
window.document.getElementById("audio").innerHTML = '<audio controls preload="automatic" autobuffer><source src="song02.mp3" type="audio/mp3" /></audio>';
}
}
</script>
</head>
<body>
<div id="audio"></div><br />
<br />
<input type="button" value="playStuff(1)" onclick="playStuff(1)" />
<input type="button" value="playStuff(2)" onclick="playStuff(2)" />
</body>
</html>
Файл cache.manifest выглядит следующим образом:
CACHE MANIFEST
song01.mp3
song02.mp3
и корректно возвращается из Apache как "text/cache-manifest", добавляя
AddType text/cache-manifest manifest
в .htaccess этого каталога.
Apache-журналы ясно показывают, что Safari (соответственно "AppleCoreMedia" ) не заботится о кеше приложения, когда речь заходит о аудио файлах:
Сафари, похоже, подтверждает манифест и действительно загружает файлы:
192.168.0.40 - - [23/Jul/2011:12:45:46 +0200] "GET /websql/index2.html HTTP/1.1" 200 2619 "-" "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5"
192.168.0.40 - - [23/Jul/2011:12:45:46 +0200] "GET /websql/cache.manifest HTTP/1.1" 200 79 "-" "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5"
192.168.0.40 - - [23/Jul/2011:12:45:46 +0200] "GET /websql/cache.manifest?%3E HTTP/1.1" 200 79 "-" "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5"
192.168.0.40 - - [23/Jul/2011:12:45:46 +0200] "GET /websql/song02.mp3 HTTP/1.1" 200 120525 "-" "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5"
192.168.0.40 - - [23/Jul/2011:12:45:46 +0200] "GET /websql/song01.mp3 HTTP/1.1" 200 120525 "-" "Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5"
До этого момента я ничего не делал, кроме как открыть тестовое приложение в Safari.
Воспроизведение песни01.mp3:
192.168.0.40 - - [23/Jul/2011:12:47:25 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 2 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:47:25 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:47:25 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:47:25 +0200] "GET /websql/song01.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:47:25 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:47:29 +0200] "GET /websql/song01.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:47:29 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
Воспроизведение song2.mp3:
192.168.0.40 - - [23/Jul/2011:12:48:04 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 2 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:04 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:04 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:04 +0200] "GET /websql/song02.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:04 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:05 +0200] "GET /websql/song02.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:05 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
Повторное воспроизведение песни1.mp3:
192.168.0.40 - - [23/Jul/2011:12:48:38 +0200] "GET /websql/song01.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:38 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:38 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:38 +0200] "GET /websql/song01.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:38 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:40 +0200] "GET /websql/song01.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:48:40 +0200] "GET /websql/song01.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
Повторное воспроизведение песни2.mp3:
192.168.0.40 - - [23/Jul/2011:12:49:12 +0200] "GET /websql/song02.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:49:12 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:49:12 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:49:12 +0200] "GET /websql/song02.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:49:12 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:49:13 +0200] "GET /websql/song02.mp3 HTTP/1.1" 304 - "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
192.168.0.40 - - [23/Jul/2011:12:49:13 +0200] "GET /websql/song02.mp3 HTTP/1.1" 206 120525 "-" "AppleCoreMedia/1.0.0.8J2 (iPad; U; CPU OS 4_3_3 like Mac OS X; de_de)"
Каждый файл полностью загружается при воспроизведении. Итак, "AppleCoreMedia" (что бы это ни было, плагин QuickTime, который запускается аудио-элементом HTML 5, я полагаю?) Либо не имеет доступа к кэшу приложений, либо просто не понимает файлы в нем, Поэтому, если теперь я переключу iPad на "Режим полета", Safari не сможет получить доступ/загрузить/воспроизвести файлы.
Я также попытался использовать объект QuickTime вместо аудиотекста HTML 5 (насколько я знаю, что аудио и видео HTML 5 в Safari всегда используют QuickTime?) и управляя им чем-то вроде:
document.movie1.SetURL('song02.mp3');
Ничего не меняется, это похоже на использование аудио HTML 5, и все загружается снова при загрузке/воспроизведении.
И даже если это будет работать, все равно будет проблема:
Чтобы правильно реализовать это, мне пришлось бы загрузить MP3 файл в кэш приложения, прежде чем играть в него. При этом кажется невозможным показать "реальный" прогресс: ProgressEvent, который запускается из кэша приложений после его обновления, похоже, не предоставляет никакой информации о загруженных данных до сих пор и о полном размере файла. Это просто "Файл 1 из 2" и т.д., А не "реальный" прогресс, когда я мог бы определить что-то вроде: "100 кБ 1,2 МБ загружен", как я могу сделать с аудиоэлементом.
Все другие подходы к хранению, такие как Web SQL/Web Database или Local Storage, также не помогают:
Я не вижу способа получить данные MP3 в локальном хранилище или в веб-базе данных и/или снова получить его, чтобы воспроизвести его. Элемент Canvas HTML 5 имеет функцию toDataURL(), чтобы создать представление с кодировкой Base64 и использовать его для хранения. Элемент Audio не имеет ничего подобного.
Мой последний действительно "грязный" подход пытался загрузить "вручную" Base64-encoded-MP3 с помощью комбинации AJAX и PHP: PHP- script выводит Base64-представление MP3 файла и загружается AJAX, поэтому я мог бы хранить представление Base64, например как локальное хранилище или в веб-базе данных:
$infile = 'song01.mp3';
$contents = file_get_contents($infile);
$base64 = base64_encode($contents);
$audio = 'data:audio/mp3;base64,'.$base64;
echo $audio;
Я попытался использовать результирующий AJAX responseText в качестве аргумента source в теге audio-source. Suprise: он не работает в Safari на моем iPad 2, плеер просто не загружает "файл", хотя это отлично работает в Chrome на Windows. Возможно ограничение размера для Base64-URI на Safari/iOS?
И снова: даже если это работало в iOS/Safari, я не знаю, как определить реальный прогресс из AJAX-запроса...
Последнее, о чем я думал, не заменяет аудио- или исходные теги при загрузке песни, а оставляет их в DOM-структуре, проверяет, есть ли она там, когда песня загружена, и просто добавьте новый аудио- если песня еще не загружена. Не работает...
Если вы добавляете несколько экземпляров игроков динамически (опять же, независимо от того, есть ли HTML 5-тэги или объекты QuickTime) вместо "перезаписывания", Safari забывает, что когда-либо загружал первый MP3, как только вы даже вставляете новый аудио- или QuickTime -Element в дереве DOM - вам даже не нужно загружать/воспроизводить что-то в новом экземпляре! Повторное воспроизведение без полной перезагрузки файла работает до тех пор, пока вы не воспроизводите или не добавляете какие-либо другие аудио/медиа. BTW: Просто использование аудио-объектов в JavaScript и "сохранение" их в массив не работает либо/не делает кэш Safari ничего.
Это создает много ненужного трафика и занимает ненужное долгое время, если вы находитесь в сотовой сети с низкой пропускной способностью!
Я работаю над этой проблемой уже три дня, даже не приближаясь к решению...
Любые идеи?
Ответы
Ответ 1
Я почти уверен, что это по дизайну и не может быть переопределено; материал CoreMedia целенаправленно передает файл по мере необходимости и отбрасывает его, не кэшируя его, когда игрок уволен. Это связано с ограниченным хранением, временем автономной работы и т.д., Поскольку в большинстве случаев вы загружаете один медиафайл, играете его много раз, а затем избавляетесь от него. Всякий раз, когда тип содержимого является типом носителя, это произойдет.
Другое сообщение ссылается на идею кодирования данных в PNG, чтобы заставить браузер кэшировать его, но я этого не делал.
Вы можете попробовать объединить различные звуковые фрагменты в один файл, а затем передать время начала/остановки для каждого образца (в основном индекс); то вы можете загрузить файл в одном аудиоплеере и перейти в нужное место и играть только за указанное время. Если это место еще не было загружено, я считаю, что Safari будет использовать заголовки диапазонов для перехода вперед в файл (но это может зависеть от того, какой тип контейнера и имеет ли контейнер индекс).
Другой альтернативой будет использование потокового медиа-сервера, который может динамически воспроизводить аудио. Просто передайте поток, когда игрок задействован, но потоковое молчание (правильный протокол должен использовать минимальную полосу пропускания для этого случая), затем запросы на образец запускают потоковый сервер для воспроизведения этого образца. К сожалению, не является идеальным или ужасно эффективным.
Ответ 2
В случае, если кто-то все еще тянет свои волосы поверх этого материала (я недавно потерял выходные), Safari на iOS 6 имеет API веб-аудио.
https://developer.apple.com/technologies/ios6/
Ответ 3
Попробуйте этот трюк, который я видел на своем твиттере несколько недель назад, но на самом деле не получил время попробовать: добавьте iframe и установите источник в URL-адрес медиафайла. Это звучит странно, но это было из очень популярного твита JS...
О, и я вижу это здесь: Как я могу автовоспроизвести носитель в iOS >= 4.2.1 Mobile Safari?
Def стоит попробовать