2011-07-25 8 views
15

Estoy desesperadamente tratando de encontrar una solución para una aplicación web que tiene que ejecutarse en un IOS-Safari (por ejemplo, en el iPad, iPad2 y iPhone 4):HTML 5/QuickTime almacenamiento en caché de audio en Safari en iOS

Es una aplicación web que escribí hace algún tiempo que permite al usuario buscar y escuchar muestras de música cortas (MP3, todo desde ~ 100 kB a ~ 1.5 MB). El reproductor de audio está basado en Flash, por lo que no funciona en dispositivos iOS en este momento y tendré que implementar una alternativa en HTML 5 o con un objeto QuickTime "directo".

Tanto mi HTML 5 y QuickTime-alternativas para iOS dispositivos funcionan muy bien hasta ahora, pero hay un gran problema que no puedo encontrar una solución a:

A diferencia de la mayoría de Flash y HTML 5-navegadores capaces de Windows Safari en mi iPad 2 no almacenará los audiofiles en el browsercache después de cargarlos y reproducirlos, ni con etiquetas de audio HTML 5 ni con QuickTime-Object. Cada vez que cargo un archivo de audio para reproducirlo desde el servidor (con Comandos de JavaScript, sin cambiar o volver a cargar toda la página), vuelve a descargarse por completo.

Si un usuario escucha la muestra A y luego muestra B, Safari se olvidó de haber reproducido la muestra A y descarga todo el MP3 nuevamente si me gusta volver a escucharlo. En un dispositivo móvil con un ancho de banda potencialmente estrecho, este comportamiento está fuera de cuestión.

Hay una forma de almacenar audiofilos descargados por HTML 5 o QuickTime en la memoria caché de Safari para que los recuerde haberlos descargado, como en caché los "archivos web" habituales como HTML, CSS o imágenes JPEG, o como Flash almacena tales objetos en su caché local?

Mi primer intento fue tratar de usar el caché de la aplicación con un archivo de manifiesto, aunque este no es realmente el propósito para mi aplicación ... No tengo un conjunto estático de archivos que quiero tener en caché o "disponible sin conexión": solo quiero almacenar en caché los archivos MP3 que el usuario ya ha reproducido.

Debería ser posible utilizar un "manifiesto dinámica": Uno que es analizada por el módulo de Apache PHP y una lista de los archivos reproducidos hasta el momento de una sesión de PHP - algo como esto:

session_start(); 

header("Content-Type: text/cache-manifest, charset=UTF-8"); 
echo "CACHE MANIFEST\n"; 
foreach($_SESSION['playedSongs'] as $song) 
{ 
     echo $song."\n"; 
} 

Así que cada vez se carga/reproduce una canción, pude acceder a la sesión de PHP con AJAX, insertar el nombre del archivo reproducido y actualizar manualmente el manifiesto llamando a window.applicationCache.update() o .swapCache().

Hay dos problemas con este:

En primer lugar: No funciona. Y ni siquiera llegar al punto de tratar de utilizar un manifiesto dinámica:

<!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> 

El cache.manifest se ve así:

CACHE MANIFEST 

song01.mp3 
song02.mp3 

y se devuelve correctamente desde Apache como "text/cache-manifest "agregando

AddType text/cache-manifest manifest 

al .htaccess de este directorio.

Los Apache-logs muestran claramente que el Safari (respectivamente "AppleCoreMedia") no se preocupa por el caché de la aplicación cuando se trata de archivos de audio:

Safari sí parece reconocer el manifiesto y de hecho la precarga archivos:

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" 

Hasta este momento no hice más que abrir mi aplicación de prueba en Safari.

Jugar 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 Jugar:

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

Jugar song1.mp3 nuevo:

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

Juego song2.mp3 nuevo:

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

Todos los archivos se vuelven a descargar completamente al reproducirlo. Así que "AppleCoreMedia" (cualquiera que sea esto exactamente, el complemento QuickTime que se desencadena por el elemento de audio HTML 5, supongo?) O bien no tiene acceso a la memoria caché de la aplicación o simplemente no se da cuenta de los archivos en ella . Entonces, si cambio mi iPad a "Modo Avión" ahora, Safari no puede acceder/cargar/reproducir los archivos.

También he intentado usar un QuickTime a objetos en lugar de un audio-etiqueta HTML 5 (por lo que yo sé HTML 5 audio y vídeo en Safari siempre usar QuickTime?) Y controlarlo con algo como:

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

Nada cambia, es como usar audio HTML 5 y todo vuelve a descargarse cuando lo carga/reproduce.

E incluso si esto no funciona todavía estaría un problema:

Para aplicar correctamente que iba a tener que cargar el archivo MP3 en el caché de la aplicación antes de reproducirlo. Al hacer esto, parece imposible mostrar un progreso "real": el ProgressEvent que se activa desde la caché de la aplicación después de actualizarlo no parece proporcionar ninguna información sobre los datos cargados hasta el momento y el tamaño completo de un archivo. Es solo "Archivo 1 de 2" y así sucesivamente, y no un progreso "real" donde pude determinar algo así como: "100 kB de 1.2 MB cargados", como puedo hacer con el elemento de audio.

Todos los otros almacenamiento enfoque, tales como Web/Base de datos SQL Web o almacenamiento local no son de ayuda, ya sea:

no veo ninguna manera de conseguir los datos MP3 en almacenamiento o en la web de base de datos local y/o conseguir de nuevo para jugarlo. El elemento Canvas de HTML 5 tiene una función toDataURL() para producir una representación codificada en Base64 y usarla para el almacenamiento: el elemento de audio no parece tener algo como esto.

Mi último enfoque realmente "sucio" fue tratar de cargar MP3 codificados en Base64 "manualmente" con una combinación de AJAX y PHP: Un script PHP genera una representación Base64 de un archivo MP3 y es cargado por AJAX , así que podría almacenar la representación de Base64, por ejemplocomo almacenamiento local o en la base de datos Web:

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

He intentado utilizar el AJAX responseText resultante como la fuente de argumento en una fuente-etiquetas de audio. Suprise: No funciona en Safari en mi iPad 2, el reproductor simplemente no carga el "archivo", aunque esto funciona bien en Chrome en Windows. ¿Posiblemente una limitación de tamaño para Base64-URI en Safari/iOS?

Y otra vez: Incluso si esto estaba trabajando en IOS/Safari no sé de una manera de determinar un progreso real a partir de una consulta AJAX ...

La última cosa que estaba pensando no era reemplazando las etiquetas de audio o fuente cuando carga una canción pero dejándolas en la estructura DOM, verifique si ya está allí cuando se cargue una canción y simplemente agregue una nueva etiqueta de audio si todavía no se ha cargado una canción. No funciona ... Si agrega varias instancias de jugador dinámicamente (una vez más, no importa si se trata de etiquetas HTML 5 u objetos QuickTime) en lugar de "sobreescribirlas", Safari se olvida de haber cargado el primer MP3 tan pronto como usted incluso inserte un nuevo elemento de audio o QuickTime en el árbol DOM; ¡ni siquiera tiene que cargar/reproducir algo en la nueva instancia! La reproducción repetida sin la recarga completa del archivo solo funciona siempre que no reproduzca ni inserte nada más relacionado con audio/medios. Por cierto: solo el uso de Audio-objetos en JavaScript y "guardarlos" en una matriz tampoco funciona/no hace que Safari cache nada.

Esto produce mucho tráfico innecesario y toma mucho tiempo innecesario si está en una red celular con un ancho de banda bajo.

estoy trabajando en este problema para los tres días sin ni siquiera acercarse a una solución ...

¿Alguna idea?

+2

+1 para la presentación :) Me reetiquetado que en el iPhone porque no es iPad etiqueta específica y el iPhone está suscrito por más gente. – Kay

+0

Quizás esto contenga algunos enlaces e información interesantes http://stackoverflow.com/questions/1612116/html5-local-storage-of-audio-element-source-is-it-possible – Kay

+0

Definitivamente algunos datos interesantes en ese Kay, pero no hay respuestas para los problemas de IOS. –

Respuesta

2

Estoy casi seguro de que esto es por diseño y no puede ser anulado; el material de CoreMedia transmite el archivo de manera intencionada según sea necesario y lo descarta sin almacenarlo en la memoria caché cuando el reproductor se cierra. Esto se debe al almacenamiento limitado, la duración de la batería, etc., ya que la gran mayoría de las veces, carga un archivo multimedia, lo reproduce varias veces y luego se deshace de él. Siempre que el tipo de contenido sea un tipo de medio, esto sucederá.

Otra publicación hace referencia a la idea de codificar los datos en un archivo PNG para que el navegador los guarde en caché, pero no lo he intentado.

Puede intentar fusionar las distintas muestras de audio en un archivo y luego transmitir las horas de inicio/detención de cada muestra (un índice básicamente); luego puede cargar el archivo en un solo reproductor de audio y saltar a la ubicación necesaria y jugar solo por el tiempo especificado. Si esa ubicación aún no se ha descargado, creo que Safari usará encabezados de rango para avanzar en el archivo (pero eso puede depender exactamente del tipo de contenedor y si el contenedor tiene un índice).

Otra alternativa sería utilizar un servidor de transmisión de medios que pueda reproducir audio de forma dinámica. Simplemente haga funcionar la transmisión cuando el reproductor esté activado pero transmitiendo silencio (el protocolo correcto debería usar un ancho de banda mínimo para este caso), luego las solicitudes de una muestra activan el servidor de transmisión para que reproduzca esa muestra. No es ideal o terriblemente eficiente por desgracia.

0

Pruebe este truco que he visto en mi twitter hace algunas semanas, pero que nunca me dio tiempo de probar: añada un iframe y establezca el origen en la URL del archivo multimedia. Suena raro, pero era de un tweet de JS muy popular ...

Ah, y me ven aquí: How can I autoplay media in iOS >= 4.2.1 Mobile Safari?

duda vale la pena intentarlo

1

Por si alguien todavía está tirando de los pelos sobre esta materia (I perdido un fin de semana para que recientemente), Safari en iOS 6 tiene una API de Web Audio.

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

+0

No debe hablar sobre las características de la versión beta de iOS en público. – Till

+0

¿Por qué no? Es información pública en Apple.com: "Las nuevas funciones de Safari en iOS 6 le permiten crear audio para aplicaciones web interactivas usando Web Audio API". Esta es una buena noticia, en realidad estoy creando juegos para niños en HTML 5 para iPad y estoy teniendo problemas con el retraso del sonido. – SondreB

Cuestiones relacionadas