web-dev-qa-db-fra.com

Utilisation d'un fichier local pour l'API Web Audio en Javascript

J'essaie de faire fonctionner le son sur mon jeu iPhone à l'aide de l'API Web Audio. Le problème est que cette application est entièrement côté client. Je veux stocker mes mp3 dans un dossier local (et sans être piloté par l'utilisateur), donc je ne peux pas utiliser XMLHttpRequest pour lire les données. Je cherchais à utiliser FileSystem mais Safari ne le prend pas en charge.

Y a-t-il une alternative?

Modifier: Merci pour les réponses ci-dessous. Malheureusement, l'API audio est horriblement lente pour les jeux. J'ai eu ce travail et la latence rend l'expérience utilisateur inacceptable. Pour clarifier, ce dont j'ai besoin, c'est comme -

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();

Mais cela me donne les erreurs -

XMLHttpRequest ne peut pas charger le fichier: ///sounds/beep-1.mp3. Les demandes d'origine croisée ne sont prises en charge que pour HTTP. Erreur non interceptée: NETWORK_ERR: exception XMLHttpRequest 101

Je comprends les risques de sécurité liés à la lecture de fichiers locaux, mais votre propre domaine devrait sûrement être correct

25
user1904515

J'ai eu le même problème et j'ai trouvé cette solution très simple.

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

Vous pouvez tester ici: http://jsfiddle.net/Tv8Cm/

38
João Mosmann

Ok, il m'a fallu deux jours pour prototyper différentes solutions et j'ai enfin compris comment je peux le faire sans stocker mes ressources sur un serveur. Il y a quelques blogs qui détaillent cela, mais je n'ai pas pu trouver la solution complète au même endroit, donc je l'ajoute ici. Cela peut être considéré comme un peu hacky par des programmeurs chevronnés, mais c'est la seule façon dont je peux voir cela fonctionner, donc si quelqu'un a une solution plus élégante, j'aimerais l'entendre.

La solution était de stocker mes fichiers audio sous forme de chaîne encodée en Base64. Les fichiers audio sont relativement petits (moins de 30 Ko), j'espère donc que les performances ne seront pas trop problématiques. Notez que je mets 'xxx' devant certains des hyperliens car mon statut n00b signifie que je ne peux pas poster plus de deux liens.

Étape 1: créer une police audio Base 64

Je dois d'abord convertir mon mp3 en une chaîne encodée en Base64 et le stocker en JSON. J'ai trouvé un site Web qui effectue cette conversion pour moi ici - xxxhttp: //www.mobilefish.com/services/base64/base64.php Vous devrez peut-être supprimer les caractères de retour à l'aide d'un éditeur de texte, mais pour ceux qui ont besoin d'un exemple, j'ai trouvé certains sons de piano ici - xxxhttps: //raw.github.com/mudcube/MIDI.js/master/soundfont/acoustic_grand_piano-mp3.js Notez que pour travailler avec mon exemple, vous devez supprimer la partie d'en-tête data: audio/mpeg; base64,

Étape 2: décoder la police audio en ArrayBuffer

Vous pouvez l'implémenter vous-même mais j'ai trouvé une API qui fait cela parfaitement (pourquoi réinventer la roue, non?) - https://github.com/danguer/blog-examples/blob/master/js/ base64-binary.js Ressource tirée de - ici

Étape 3: ajout du reste du code

Assez simple

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); });

Et c'est tout! Je travaille avec ma version de bureau de Chrome et fonctionne également sur Safari mobile (iOS 6 bien sûr, car Web Audio n'est pas pris en charge dans les anciennes versions). Le chargement prend quelques secondes sur Safari mobile (Vs moins de 1 seconde sur Chrome de bureau), mais cela peut être dû au fait qu'il passe du temps à télécharger les polices sonores. Il peut également être le fait qu'iOS empêche la lecture du son jusqu'à ce qu'un événement d'interaction utilisateur se soit produit. J'ai besoin de faire plus de travail pour voir comment cela fonctionne.

J'espère que cela sauvera quelqu'un d'autre du chagrin que j'ai vécu.

16
user1904515

Parce que les applications ios sont en bac à sable, la vue Web (essentiellement safari enveloppé dans un espace de téléphone) vous permet de stocker votre fichier mp3 localement. C'est-à-dire qu'il n'y a pas de problème de sécurité "interdomaine".

C'est à partir d'ios6 car les versions précédentes d'ios ne prenaient pas en charge l'API audio Web

1
Jarrod