41

私たちは HTML5 ゲームを作っているので、iOS 6 が Web Audio API をサポートしているのを見て本当に興奮しました。ただし、Web Audio API を使用して iOS 6 でサウンドを再生することはできません。サンプルはデスクトップ Chrome で正常に動作します。

これは、タッチ コントロールを備え、Web Audio API を介してオーディオを再生する HTML5 ゲームです (存在する場合 - 存在しない場合は、HTML5 オーディオにフォールバックします)。

http://www.scirra.com/labs/sbios6b/

編集: @Srikumar はいくつかの回避策を提案しました。以下のバージョンで適用しました。それでもうまくいきません!

http://www.scirra.com/labs/sbios6f/

デスクトップ Chrome ではすべて問題なく再生されますが、iOS 6 ではまったく音が出ません。私は Windows 開発のみを行っているため、デバッグに問題があり、iOS 6 ではデバッグ モードがリモート Web インスペクターに置き換えられましたが、これはどうやら Windows の Safari では使用できないようです。いくつかのアラートを使用して、Web Audio API を正しく識別し、それを使用し、Vorbis サポートを検出しないため、AAC オーディオにフォールバックし、バッファをデコードしてから再生し、エラーはスローされませんが、何も聞こえません。そして、もちろん、音量を最大にしてみました:)

iOS 6 は AAC を正常に再生できるため、コーデックの問題は発生しないはずです。.m4a のいずれかを参照してゲームを再生すると、Safari から直接アクセスして正常に再生されます。

ここで iOS 6 の Web Audio API の例を見る: http://chromium.googlecode.com/svn/trunk/samples/audio/samples.html - それらのいくつかは機能し、他のものは機能しません。たとえば、Chrome オーディオ ビジュアライザーは機能しますが、Javascript Droneは機能しません。

iOS 6 の Web オーディオとデスクトップ Chrome の間には、微妙な非互換性があるはずです。私は何が欠けていますか?

4

12 に答える 12

51

編集 (2015 年 11 月): iOS 9 では、イベントでオーディオを開始できなくなりましたtouchstart。これにより、以下のソリューションが機能しなくなります。ただし、touchendイベントでは機能します。iOS 6 の元の回答はそのまま残されていますが、iOS 9 をサポートするには、必ず を使用してくださいtouchend

賞金首の質問に答えて申し訳ありませんが、何時間ものデバッグの末、ようやく答えが見つかりました。iOS 6 の Safari は、事実上、Web Audio API がミュートされた状態で起動します。ユーザー入力イベントでサウンドを再生しようとするまで、ミュートは解除されません(バッファー ソースを作成し、それを宛先に接続し、 を呼び出しますnoteOn())。この後、ミュートが解除され、オーディオが無制限に再生されます。これは、Web Audio API が iOS 6 でどのように機能するかについて文書化されていない側面です ( Apple のドキュメントはこちらにあります。うまくいけば、すぐにこれについて言及して更新されます!)

ユーザーは、ゲームに夢中になって、画面に何度も触れている可能性があります。しかし、それはミュートされたままになります。[編集: iOS 9 以降の場合] のようなユーザー入力イベント内で再生する必要があり、その後、すべてのオーディオのミュートが解除されます。その後、いつでもオーディオを再生できます (ユーザー入力イベントである必要はありません)。touchstarttouchend

これは、HTML5 オーディオの制限とは異なることに注意してください。通常、オーディオはユーザー入力イベントでのみ開始でき、一度に 1 つのサウンドしか再生できません。Web Audio API は、最初の play-in-user-input の後に完全にミュートを解除するため、いつでもサウンドを再生でき、その後、それらをポリフォニックにミックスしたり、クールなエフェクトを処理したりできます。

これは、Web Audio API を使用して既に Web 上にある多くのゲームがオーディオを再生しないことを意味します。これは、タッチ イベントで noteOn を発行しないためです。最初のユーザー入力イベントを待つように調整する必要があります。

これを回避するには、いくつかの方法があります。ユーザーが画面に触れるまで、タイトルの音楽を再生しないでください。最初の「タッチしてオーディオを有効にする」画面を表示し、サウンドを再生してから、タッチするとゲームを開始します。うまくいけば、これは同じ問題を抱えている他の誰かがデバッグを試みる時間を節約するのに役立ちます!

于 2012-09-24T16:39:30.950 に答える
7

Mac の Safari 6 で Web Inspector を使用してデバッグを試みることができます。

  1. モバイル Safari の設定/詳細で「Webkit インスペクター」を有効にします。
  2. USB ケーブルを使用して、Safari 6 を実行している Mac にデバイスを接続します。
  3. ページ/ゲームを読み込む
  4. メニューの [開発] -> [デバイス名] -> [ページ URL] に移動します。

私にとってはそのままではうまくいきませんが、数回試してみると、問題を絞り込むのに役立ちます。

どうやらユーザーのアクションによってのみオーディオをトリガーできるということもあります。iPhone4 の iOS6 で動作する一部のコードは、iPad (iOS6 も) ではサウンドを再生しないため、これが正しいかどうかはわかりません。

更新: iPhone4+iOS6 で Web オーディオに成功。iOS6 で新しいオーディオ コンテキストを作成すると、しばらくの間 "currentTime" が 0 のままになることがわかりました。それを動かすには、まずダミーの API 呼び出しを実行する必要があります (createGainNode()結果を like して破棄します)。サウンドは currentTime の実行が開始されたときにのみ再生されますが、currentTime で正確にサウンドをスケジュールすることは機能していないようです。それらは少し未来にある必要があります (例: 10ms)。次の関数を使用してcreateAudioContext、コンテキストがノイズを発生させる準備が整うまで待機できます。iPhone ではユーザーの操作は必要ないようですが、iPad ではまだそのような成功はありません。

function createAudioContext(callback, errback) {
    var ac = new webkitAudioContext();
    ac.createGainNode(); // .. and discard it. This gets 
                         // the clock running at some point.

    var count = 0;

    function wait() {
        if (ac.currentTime === 0) {
            // Not ready yet.
            ++count;
            if (count > 600) {
                errback('timeout');
            } else {
                setTimeout(wait, 100);
            }
        } else {
            // Ready. Pass on the valid audio context.
            callback(ac); 
        }
    }

    wait();
}

その後、ノートを演奏するときは、 を呼び出さず.noteOn(ac.currentTime).noteOn(ac.currentTime + 0.01)代わりに呼び出します。

なぜそんなことをしなければならないのか、私に聞かないでください。それが今のやり方です - つまりクレイジーです。

于 2012-09-22T03:49:22.447 に答える
3

それで、私はそれを理解したと思います。

これは、サウンドの再生を許可する前にユーザーの操作を要求する Apple の問題です。少なくとも私にとっては、ユーザーが呼び出した場合を除いて、オーディオ コンテキストを作成するべきではないことがわかりました。ページの読み込み時にコンテキストを作成し、ユーザー アクションで createGainNode などを使用するだけでは不十分です。

あなたの場合、ユーザーが「タッチして開始」ボタンをクリックしたときにコンテキストを作成します。

于 2012-09-24T08:01:32.087 に答える
1

iOSでのHTML5 オーディオのオーディオ制限に遭遇し、次の方法で問題を回避しました。

1) サイレント オーディオ ファイルでオーディオ要素を作成し、最初にタッチ イベント (「ゲーム開始」ボタンなど) で再生し、すぐに一時停止します。

2) Audio src を切り替え、短いタイムアウト後に Audio 要素を再生するサウンドスイッチャー関数を構築します。

3) 任意のイベントでサウンド スイッチャー関数を呼び出す (タッチ イベントである必要はありません)。

これが機能するのは、Audio Element が無音のオーディオ ファイルで最初のタッチでミュート解除され、ミュート解除されたままであるため、ソースをオンザフライで切り替えることができるためです。

switchSound: (id) ->
        @soundSwitch.pause()
        @soundSwitch.src = @sounds[id]._src

        clearTimeout @switchSoundDelay
        @switchSoundDelay = setTimeout =>
            # @soundSwitch.volume = 1
            @soundSwitch.play()
        ,50 
于 2014-08-07T07:34:23.180 に答える
1

元の質問に答えると、iPhone 4S/iOS 6 および MacOSX でのファイル形式に問題があることが確認できます。MP3 ファイルが Safari に「不適切」である場合、デコードがうまくいかず、 AudioContext.createBuffer(array, bool) を呼び出すとエラーが発生します。

奇妙なことは、他の人が指摘したように、「SYNTAX_ERR、DOM Exception 12」というエラーに関するものです。これはバグだと思います....

Safari 6.0 (7536.25) を使用する MacOS でも同じ動作です。

于 2012-09-28T16:35:19.383 に答える
1

2015 ソリューション用に更新されました: 皆さん、ios6+ の Web オーディオの問題に取り組んでいる場合は、これらのリンクがヘルプとして見つかりました。

-これはコード ソリューションを含む優れた記事です: http://matt-harrison.com/perfect-web-audio-on-ios-devices-with-the-web-audio-api/

-上記の ^ ソリューション記事が書かれた後の API の更新はこちらhttps://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext

-以下は、2 番目の記事の変更を使用して、最初の記事に対する私の更新されたソリューションです。私が抱えていた問題は、奇妙な not-enough-args エラーをスローする iOS 7 サファリでした。これで修正されました:

define(function() {

  try {
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    window.audioContext = new window.AudioContext();
  } catch (e) {
    console.log("No Web Audio API support");
  }
/*
 * WebAudioAPISoundManager Constructor
 */
 var WebAudioAPISoundManager = function (context) {
  this.context = context;
  this.bufferList = {};
  this.playingSounds = {};
};

/*
 * WebAudioAPISoundManager Prototype
 */
 WebAudioAPISoundManager.prototype = {
   addSound: function (url) {
      // Load buffer asynchronously
      var request = new XMLHttpRequest();
      request.open("GET", url, true);
      request.responseType = "arraybuffer";

      var self = this;

      request.onload = function () {
        // Asynchronously decode the audio file data in request.response
        self.context.decodeAudioData(
          request.response,

          function (buffer) {
            if (!buffer) {
              alert('error decoding file data: ' + url);
              return;
            }
            self.bufferList[url] = buffer;
          });
      };

      request.onerror = function () {
        alert('BufferLoader: XHR error');
      };

      request.send();
    },
    stopSoundWithUrl: function(url) {
      if(this.playingSounds.hasOwnProperty(url)){
        for(var i in this.playingSounds[url]){
          if(this.playingSounds[url].hasOwnProperty(i)) {
            this.playingSounds[url][i].stop(0);
          }
        }
      }
    }
  };

/*
 * WebAudioAPISound Constructor
 */
 var WebAudioAPISound = function (url, options) {
  this.settings = {
    loop: false
  };

  for(var i in options){
    if(options.hasOwnProperty(i)) {
      this.settings[i] = options[i];
    }
  }

  this.url = '/src/www/assets/audio/' + url + '.mp3';
  this.volume = 1;
  window.webAudioAPISoundManager = window.webAudioAPISoundManager || new WebAudioAPISoundManager(window.audioContext);
  this.manager = window.webAudioAPISoundManager;
  this.manager.addSound(this.url);
    // this.buffer = this.manager.bufferList[this.url];
  };

/*
 * WebAudioAPISound Prototype
 */
 WebAudioAPISound.prototype = {
  play: function () {
    var buffer = this.manager.bufferList[this.url];
    //Only play if it's loaded yet
    if (typeof buffer !== "undefined") {
      var source = this.makeSource(buffer);
      source.loop = this.settings.loop;
        source.start(0);

        if(!this.manager.playingSounds.hasOwnProperty(this.url)) {
          this.manager.playingSounds[this.url] = [];
        }
        this.manager.playingSounds[this.url].push(source);
      }
    },
    stop: function () {
      this.manager.stopSoundWithUrl(this.url);
    },
    getVolume: function () {
      return this.translateVolume(this.volume, true);
    },
    //Expect to receive in range 0-100
    setVolume: function (volume) {
      this.volume = this.translateVolume(volume);
    },
    translateVolume: function(volume, inverse){
      return inverse ? volume * 100 : volume / 100;
    },
    makeSource: function (buffer) {
      var source = this.manager.context.createBufferSource();
      var gainNode = this.manager.context.createGain();
      source.connect(gainNode);
      gainNode.gain.value = this.volume;
      source.buffer = buffer;
      // source.connect(gainNode);
      gainNode.connect(this.manager.context.destination);
      return source;
    }
  };

  return WebAudioAPISound;
});
于 2015-11-17T17:24:17.137 に答える
0

これは実際の答えではなく、まだうまくいかない場合の方向性です。iOS6 は、一部のデバイス (特に特定の期間に製造された 64GB 4 で、実際にはハードウェアに関連していない可能性があるため、他のデバイスを見たことがあります)でオーディオの問題があり、不思議なことに一部の種類のサウンドの再生を停止します (一部のデバイスでは、着信音や音声ではありません)。理由、しかし他の多くの音)、そしてそれの音量スライダーは消えます. 電源コードに接続されていない場合にのみ発生するため、デバッグが非常に難しいことで知られています (常に発生するとは限りませんが、キャッチできる場合もあります)。

コンソールで、VirtualAudio_Device からの ASSERTION FAILURE メッセージと、さまざまなコーデックを調べます。これはあなたの特定の問題とは何の関係もないかもしれませんが、繰り返しになりますが、サウンド デバイスのある領域のバグが別の領域に関連している可能性があります。少なくとも、他に何も役に立たない場合は調査する必要があります。

于 2012-09-29T19:58:48.970 に答える
0

すべての単純なソリューションを使用するのに問題があります。特に音を何回も鳴らしたいとき。

だから私はこの js ライブラリを使用しています: http://pupunzi.open-lab.com/2013/03/13/making-html5-audio-actually-work-on-mobile

于 2013-12-21T20:57:19.143 に答える
0

この API は iOS 6.1 では壊れているように見えます。または少なくとも、現在この API で動作するサイトがないことを意味する重大な変更があります。

于 2013-02-15T15:50:31.553 に答える