web-dev-qa-db-ja.com

JavaScriptでWeb Audio APIのローカルファイルを使用する

Web Audio APIを使用して、iPhoneゲームでサウンドを機能させようとしています。問題は、このアプリが完全にクライアント側であることです。 mp3をローカルフォルダーに保存し(ユーザー入力を使用せずに)、XMLHttpRequestを使用してデータを読み取れないようにしたいと考えています。 FileSystemの使用を検討していましたが、Safariではサポートされていません。

代替手段はありますか?

編集:以下の回答をありがとう。残念ながら、オーディオAPIはゲームにとって恐ろしく遅いです。私はこれを機能させていました、そして待ち時間はユーザーエクスペリエンスを受け入れられないものにするだけです。明確にするために、私が必要なのは

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

しかし、これは私にエラーを与えます-

XMLHttpRequestはfile:///sounds/beep-1.mp3をロードできません。クロスオリジン要求はHTTPでのみサポートされています。キャッチされなかったエラー:NETWORK_ERR:XMLHttpRequest Exception 101

ローカルファイルを読み取る際のセキュリティリスクは理解していますが、確かに自分のドメイン内で問題ありませんか?

25
user1904515

私は同じ問題を抱えていて、この非常に単純な解決策を見つけました。

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

ここでテストできます: http://jsfiddle.net/Tv8Cm/

38
João Mosmann

OK、2日間かけてさまざまなソリューションのプロトタイピングを行い、リソースをサーバーに保存せずにこれを実行する方法をようやく見つけました。これについて詳しく説明しているブログはいくつかありますが、1つの場所で完全なソリューションを見つけることができなかったため、ここに追加します。これは熟練したプログラマーにとっては少しハックだと思われるかもしれませんが、これが私がこれが機能していることを確認できる唯一の方法であるため、誰かより優れた解決策があれば、ぜひ聞いてみたいと思います。

解決策は、サウンドファイルをBase64エンコード文字列として保存することでした。サウンドファイルは比較的小さい(30kb未満)ので、パフォーマンスがそれほど問題にならないことを願っています。私のn00bステータスは2つを超えるリンクを投稿できないことを意味するため、一部のハイパーリンクの前に「xxx」を付けていることに注意してください。

ステップ1:Base 64サウンドフォントを作成します

まず、mp3をBase64エンコードされた文字列に変換し、それをJSONとして保存する必要があります。私のためにこの変換を行うウェブサイトをここで見つけました-xxxhttp://www.mobilefish.com/services/base64/base64.phpテキストエディターを使用してリターン文字を削除する必要があるかもしれませんが、例が必要な人のためにここにピアノの音色-xxxhttps://raw.github.com/mudcube/MIDI.js/master/soundfont/acoustic_grand_piano-mp3.js私の例を使用するには、ヘッダー部分を削除する必要があることに注意してくださいdata:audio/mpeg; base64、

ステップ2:サウンドフォントをArrayBufferにデコードする

これを自分で実装することもできますが、これを完全に実行するAPIを見つけました(なぜホイールを再発明するのですか?)- https://github.com/danguer/blog-examples/blob/master/js/ base64-binary.js - here から取得したリソース

ステップ3:残りのコードを追加する

かなり簡単

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

以上です!私はこれを私のデスクトップバージョンのChrome=とモバイルSafariで実行しています(もちろん、古いバージョンではWeb Audioがサポートされていないため、iOS 6のみです)。ロードに数秒かかります。モバイルSafari(デスクトップChromeでは1秒未満)ですが、サウンドフォントのダウンロードに時間を費やしていることが原因である可能性があります。また、ユーザーインタラクションイベントが発生するまでiOSがサウンドの再生を妨げている可能性もあります。私はそれがどのように機能するかを見てさらに仕事をする必要があります。

これが私が経験した悲しみを他の誰かが救うことを願っています。

16
user1904515

IOSアプリはサンドボックス化されているため、Webビュー(基本的にはPhoneGapでラップされたSafari)では、MP3ファイルをローカルに保存できます。つまり、「クロスドメイン」のセキュリティ問題はありません。

以前のバージョンのiosはWebオーディオAPIをサポートしていなかったため、これはios6の時点のものです。

1
Jarrod