首页 文章

iOS上的Safari中的HTML 5 / QuickTime音频缓存

提问于
浏览
15

我绝望地试图找到一个必须在iOS-Safari(例如iPad,iPad2和iPhone 4)上运行的Web应用程序的解决方案:

这是我前段时间写的一个网络应用程序,它允许用户搜索和收听短音乐样本(MP3,全部从~100 kB到~1.5 MB) . 音频播放器是基于Flash的,因此它目前无法在iOS设备上运行,我将不得不在HTML 5或“直接”QuickTime对象中实现替代方案 .

我的HTML 5和QuickTime替代iOS设备到目前为止工作正常,但有一个主要问题我无法找到解决方案:

与Flash不同,我的iPad 2上的大多数支持HTML 5的浏览器在加载和播放后都不会将音频文件存储在浏览器缓存中 - 既不使用HTML 5音频标签也不使用QuickTime-Object . 每次我从服务器加载一个音频文件进行播放时(使用JavaScript命令,所以不用更改或重新加载整个页面),它会再次完全下载 .

如果用户收听样本A然后收听样本B,Safari忘记播放样本A并再次下载整个MP3,如果我想再次收听它 . 在具有可能窄带宽的移动设备上,这种行为是不可能的 .

有没有办法在Safari的缓存中存储由HTML 5或QuickTime打开的下载的音频文件,因此它记得已经下载了它们 - 就像它缓存了常见的“网络文件”,如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";
}

因此,无论何时加载/播放歌曲,我都可以使用AJAX访问PHP会话,插入播放文件的文件名并通过调用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>

<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-logs清楚地表明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中打开我的测试应用程序外什么也没做 .

播放song01.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”(无论这可能是什么,我猜想由HTML 5音频元素触发的QuickTime插件?)要么没有访问应用程序缓存,要么只是没有实现其中的文件 . 因此,如果我现在将iPad切换到“飞行模式”,Safari将无法访问/加载/播放文件 .

我还尝试使用QuickTime对象而不是HTML 5音频标签(据我所知,Safari中的HTML 5音频和视频总是使用QuickTime?)并使用以下内容控制它:

document.movie1.SetURL('song02.mp3');

没有什么变化,就像使用HTML 5音频一样,加载/播放时会再次下载所有内容 .

即使这样可行仍然存在问题:

为了正确实现,我必须在播放之前在应用程序缓存中加载MP3文件 . 执行此操作时,似乎无法显示“真正的”进度:更新后从应用程序缓存中触发的ProgressEvent似乎不提供有关目前加载的数据和文件的完整大小的任何信息 . 它只是“文件1从2”等等,而不是“真正的”进展,我可以确定类似:“100 kB 1.2 MB加载”,因为我可以使用音频元素 .

Web SQL / Web数据库或本地存储等所有其他存储方法都没有帮助:

我没有看到任何方法将MP3数据放入本地存储或Web数据库和/或再次将其取出发挥它 . HTML 5 Canvas-element有一个toDataURL()函数来生成Base64编码的表示并将其用于存储 - 音频元素似乎没有这样的东西 .

我最后一个真正“脏”的方法是尝试使用AJAX和PHP的组合加载“手动”Base64编码的MP3:PHP脚本输出一个MP3文件的Base64表示并由AJAX加载,所以我可以存储Base64表示例如作为本地存储或在Web数据库中:

$infile = 'song01.mp3';
$contents = file_get_contents($infile);
$base64 = base64_encode($contents);
$audio = 'data:audio/mp3;base64,'.$base64;
echo $audio;

我尝试使用生成的AJAX responseText作为audio-source-tag中的source-argument . 惊喜:它在我的iPad 2上的Safari中不起作用,播放器无法加载“文件”,尽管这在Windows上的Chrome中运行良好 . 可能是Safari / iOS上Base64-URI的大小限制?

再说一遍:即使这在iOS / Safari中有效,我也不知道从AJAX查询中确定真正进展的方法......

我想到的最后一件事是在加载歌曲时没有替换音频或源标签,而是将它们保留在DOM结构中,检查加载歌曲时它是否已存在,只需添加一个新的音频标签歌曲尚未加载 . 不起作用......如果你动态添加多个播放器实例(无论是HTML 5 -tags还是QuickTime-objects),而不是“覆盖”它们,Safari会忘记你偶尔加载第一个MP3在DOM树中插入一个新的音频或QuickTime元素 - 您甚至不必在新实例中加载/播放内容!只要您不播放或插入任何其他音频/媒体相关的内容,重复播放而无需完全重新加载文件 . 顺便说一句:只是在JavaScript中使用Audio-objects并将它们“保存”到一个数组中也不起作用/不会使Safari缓存任何东西 .

如果您处于带宽较低的蜂窝网络中,这会产生大量不必要的流量,并且会花费不必要的长时间!

我现在正在解决这个问题三天,甚至没有接近解决方案......

有任何想法吗?

3 回答

  • 0

    我几乎可以肯定这是设计上的,不能被覆盖; CoreMedia的内容根据需要有目的地流式传输文件,并在播放器被解散时将其丢弃而不进行缓存 . 这是由于存储,电池寿命等有限,因为绝大多数时候,你加载一个媒体文件,然后多次播放,然后摆脱它 . 只要内容类型是媒体类型,就会发生这种情况 .

    另一篇文章引用了在PNG中编码数据以使浏览器缓存它的想法,但我没有尝试过 .

    您可以尝试将各种音频样本合并到一个文件中,然后传输每个样本的开始/停止时间(基本上是索引);然后你可以在一个音频播放器中加载文件并跳转到必要的位置并播放指定的时间 . 如果尚未下载该位置,我相信Safari将使用范围 Headers 在文件中向前跳转(但这可能取决于具体的容器类型以及容器是否具有索引) .

    另一种替代方案是使用可以动态播放音频的流媒体服务器 . 只有当播放器参与但是流静音(正确的协议应该在这种情况下使用最小带宽)时才进行流,然后请求样本触发流服务器播放该样本 . 不幸的是,不理想或非常有效 .

  • 1

    如果有人还在为这些东西拉头(我最近失去了一个周末),iOS 6上的Safari有一个Web Audio API .

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

  • 2

    尝试几周前我在Twitter上看过的这个技巧,但实际上没有时间尝试:添加iframe,并将源设置为媒体文件URL . 这听起来很奇怪,但它来自一个非常受欢迎的JS家伙推文......

    哦,我在这里看到了:How can I autoplay media in iOS >= 4.2.1 Mobile Safari?

    值得一试

相关问题