HTML 5 / Кэширование аудио QuickTime в Safari на iOS - PullRequest
15 голосов
/ 25 июля 2011

Я отчаянно пытаюсь найти решение для веб-приложения, которое должно работать на iOS-Safari (например, на iPad, iPad2 и iPhone 4):

Это веб-приложение, которое я написал некоторое время назад, которое позволяет пользователю искать и прослушивать короткие музыкальные сэмплы (MP3, все от ~ 100 кБ до ~ 1,5 МБ). Аудиоплеер основан на Flash, поэтому на данный момент он не работает на iOS-устройствах, и мне придется реализовать альтернативу либо в HTML 5, либо с «прямым» объектом QuickTime.

Мои HTML 5- и QuickTime-альтернативы для iOS-устройств пока работают нормально, но есть одна большая проблема, решение которой я не могу найти:

В отличие от Flash и большинства браузеров, поддерживающих HTML 5, в Windows Safari на моем iPad 2 не будут сохранять аудиофайлы в кэше браузера после загрузки и воспроизведения - ни с аудиотегами HTML 5, ни с QuickTime-объектом. Каждый раз, когда я загружаю аудиофайл для воспроизведения с сервера (с помощью 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») не заботится о кеше приложения, когда дело доходит до аудио-файлов:

Кажется, само Safari подтверждает манифест и действительно предварительно загружает файлы:

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)"

Повторное воспроизведение song1.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)"

Повторное воспроизведение song2.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 в Local Storage или Web Database и / или вытащить ихснова играть в нее.Canvas-элемент HTML 5 имеет функцию toDataURL () - для создания представления в кодировке Base64 и использования его для хранения - у Audio-элемента, похоже, нет ничего подобного.

Мой последний действительно "грязный "подход пытался загрузить" вручную "Base64-закодированные MP3-файлы с комбинацией AJAX и PHP: PHP-скрипт выводит 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 в качестве аргумента источника в теге аудио-источника.Сюрприз: он не работает в Safari на моем iPad 2, проигрыватель просто не может загрузить «файл», хотя это прекрасно работает в Chrome на Windows.Возможно ли ограничение размера для Base64-URI в Safari / iOS?

И снова: даже если бы это работало в iOS / Safari, я не знаю способа определить реальный прогресс с помощью AJAX-запроса...

Последнее, о чем я думал, это не замена тегов audio или source при загрузке песни, а оставление их в DOM-структуре, проверьте, существует ли она уже при загрузке песни, и простодобавьте новый аудио-тег, если песня еще не была загружена.Не работает ... Если вы добавляете несколько экземпляров проигрывателя динамически (опять же, независимо от того, являются ли теги HTML 5 или объекты QuickTime) вместо того, чтобы «перезаписывать» их, Safari забывает, что когда-либо загружал первый MP3, как только вывставьте новый аудио или QuickTime-элемент в дерево DOM - вам даже не нужно загружать / проигрывать что-либо в новом экземпляре!Повторное воспроизведение без полной перезагрузки файла работает только до тех пор, пока вы не воспроизводите или не вставляете что-либо другое, связанное со звуком / мультимедиа.Кстати: простое использование аудио-объектов в JavaScript и «сохранение» их в массиве тоже не работает / не делает кеширование Safari.

Это создает много ненужного трафика и отнимает много времени, если выВы в сотовой сети с низкой пропускной способностью!

Я работаю над этой проблемой уже три дня, даже не приблизившись к решению ...

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 02 сентября 2011

Я почти уверен, что это сделано специально и не может быть отменено; материал CoreMedia преднамеренно передает поток по мере необходимости и выбрасывает его, не кэшируя его, когда игрок закрывается. Это связано с ограниченным объемом памяти, временем автономной работы и т. Д., Поскольку в большинстве случаев вы загружаете один медиа-файл, воспроизводите его много раз, а затем избавляетесь от него. Когда тип содержимого является типом носителя, это произойдет.

В другом посте упоминается идея кодирования данных в PNG, чтобы браузер кешировал их, но я не пытался это сделать.

Вы можете попробовать объединить различные аудиосэмплы в один файл, а затем передать время начала / остановки для каждого семпла (в основном индекс); затем вы можете загрузить файл в один аудиоплеер и перейти в нужное место и воспроизводить только указанное время. Если это местоположение еще не было загружено, я полагаю, что Safari будет использовать заголовки диапазона для перемещения вперед в файле (но это может зависеть от того, какой именно контейнер и имеет ли индекс индекс).

Другой альтернативой может быть использование сервера потокового мультимедиа, который может динамически воспроизводить звук. Просто включите поток, когда проигрыватель занят, но потоковое молчание (правильный протокол должен использовать минимальную пропускную способность для этого случая), а затем запросы на выборку запускают потоковый сервер для воспроизведения этого образца. К сожалению, не идеальный или ужасно эффективный.

1 голос
/ 23 июня 2012

На тот случай, если кто-то все еще тянет свои волосы за это (недавно я потерял выходные), Safari на iOS 6 имеет API веб-аудио.

https://developer.apple.com/technologies/ios6/

0 голосов
/ 07 сентября 2011

Попробуйте этот трюк, который я видел в своем твиттере несколько недель назад, но на самом деле у него не было времени попробовать: добавьте iframe и установите в качестве источника URL-адрес медиа-файла. Звучит странно, но это был очень популярный твит с парнем из JS ...

О, и я вижу это здесь: Как я могу автоматически воспроизводить мультимедиа в iOS> = 4.2.1 Mobile Safari?

Def стоит попробовать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...