5

HTML5 を使用して、モバイル デバイスで背景が透明なビデオを再生する必要があります。Windows Phone では、ビデオ タグの現在のフレームをキャプチャして、キャンバスに表示できます。しかし、それは Android および iOS デバイスでは機能しません (セキュリティ上の理由からだと思いますか?)。

私の解決策は、FFMPEG を使用して .flv を分割し、それらのフレームをつなぎ合わせてスプライト シートのような大きな画像にすることでした。

問題は、新しいフレーム シートに切り替えると、アニメーションが「ハング」することです。これを視覚的に確認しただけで、コンソールを介して (現在のスプライト シートの行を変更したときにログを記録することによって)、スプライト シートを変更したときにハングする方法と、同じシートを何度もループするだけです。

事前にすべての画像を事前にロードします。

var frameImages = [];

for(var i = 0; i < 35; i++)
{
  frameImages.push(new Image());
  frameImages[i].src = 'frame' + i + '.png';

  console.log(frameImages[i].src);

  frameImages[i].onload = function()
  {
    // Notify us that it's been loaded.
    console.log("Image loaded");
  }
}

そして、次のように再生します。

processFrame = function()
{
    outputCanvas.width = outputCanvas.width;
    output.drawImage(frameImages[currentFrame], (curCol*153), (curRow*448), 153, 448, 0, 0, 153, 448);
    curCol += 1;

    if(curCol >= maxCol)
    {
      curCol = 0;
      curRow += 1;

      if(curRow >= maxRow)
      {
        curRow = 0;
        currentFrame++;
      }
    }
  }
}

var mozstart = window.mozAnimationStartTime;

step = function(timestamp) {

  var diff = (new Date().getTime() - start) - time;
  if(diff >= frameDelay)
  {
    processFrame();
    time += frameDelay;
  }
}

Win 7マシンとChromeを搭載したNexus 7のChrome v 23.0.1271.97 mでこれを試しました。


http://savedbythecode.com/spokes/mozanimation.php - これは mozAnimationStartTime と http://savedbythecode.com/spokes/newplayer.php を使用してい
ます-これは各ステップで調整される通常の JS タイマーを使用しています( http://www.sitepoint.com/creating-accurate-timers-in-javascript/から)

何か案は?問題は十分に明確でしたか?

ありがとう、ケビン

4

3 に答える 3

2

クールなコード。ビデオタグだけを使用できないのはなぜですか(オプション6を参照)。とにかく、私が考えることができる問題をリストし、それがあなたに役立つことを願っています:

  1. 以前のコードとの一貫性を保つため、またDoug Crockfordの慈悲深いゴーストをチャネリングすると、JavaScriptコードからグリッチを取り除くのに役立つ可能性があるため、:に変更++してください。+= 1

  2. 一連の画像を1つの「スプライトシート」につなぎ合わせます。これらのシートの次のシートに移動するときに、コードがハングします。したがって、コードはまだ機能していないため、テストとして、各フレームのサブイメージを循環するすべてのループを削除し、frameImages配列の各フレームを各レンダリングでキャンバスに直接出力して、まだハングするかどうかを確認します。この結果により、コードがframeImagesの次のフレームに到達できるかどうか、または到達できないかどうかがわかります。これにより、バグの原因に近づく可能性があります。

  3. currentFrameはvarで宣言され、processFrameのスコープ内にありますか?var currentFrame = 0;そうでない場合は、定義した場所の上のどこかに置くだけ ですfunction processFrame(...

  4. 「それから私はそのようにプレイします」と言うとき、すべてのオンロードが起動した後、 promiseを使用しますか、それとも同等にアニメーション開始関数を呼び出しますか?これを行う方法は次のとおりです。起動するオンロードごとに1回カウンターをインクリメントし、そのたびにカウンターが必要なロードの総数と等しいかどうかを確認してから、アニメーションの開始を呼び出します。 私の勘では、内部が異なるため、これらは異なるブラウザ間で最も変動しやすいように見えるため、キャッシュの問題です。

  5. 画像を変更するときにキャンバスの内部状態をリセットすると役立つ場合があるため、drawImage呼び出しの合間に、currentFrameを更新するときにキャンバスをクリアしてみてください。

  6. HTML5ビデオタグを使用してアルファと透明度を実行できます。いくつかのsvg変換を使用するだけです。このSOの回答で述べられているように、これらは簡単に実行できます

于 2013-01-26T06:41:20.940 に答える
2

あまり正統ではない別の解決策を次に示します。ビデオをキャンバス入力として使用し、getImageData を使用して各フレームをグリーン スクリーンにします。

基本的に、ビデオタグとキャンバスがあります

<video id='source' style='display: none;'>
   <source>whatever.mp4</source>
   <source>whatever.ogg</source>
</video>
<canvas id='screen' width='videoWidth' height='videoHeight></canvas>

次に、描画機能を設定します

var t = null;
document.getElementById('source').addEventListener('playing', function(){
   var vid = this;   
   t = setInterval(function(){
       if (vid.paused || vid.ended){
          clearInterval(t);
          return
       } else {
          drawFrame();
       }
   }, 20)
}, false)

そして、あなたのドローフレーム機能は

function drawFrame(){
   var ctx = document.getElementById('screen').getContext('2d'),
       vid = document.getElementById('source');

   ctx.drawImage(vid, 0, 0);
   var tolerance = 0.2,
       bgColor = [0, 255, 0], //or whatever 
       imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height),
       len = imageData.data.length;

   for (var i=0; i<len; i+=4){
      var r = imageData.data[i],
          g = imageData.data[i+1],
          b = imageData.data[i+2];

      //There's lots of different color comparing methods, just check google
      var dif = colorCompare([r, g, b], bgColor);
      if (dif < tolerance){
         imageData.data[i+3] = 255;
      }
   }

   ctx.putImageData(imageData, 0, 0);
}

必要なパフォーマンス レベルを達成するために、さまざまな部分を試してみることができます。比較的小さい (次元的に) ビデオの場合、パフォーマンスは問題になりません。画面のちらつきを避けるためにバッファキャンバスを使用する必要があるかもしれませんが、私はそれを疑っています. また、許容変数を調整して、発生する可能性のあるハロー効果を回避できます。

それが最善の解決策であるとは言いませんが、間違いなく実行可能な解決策であり、追加の作業を必要とせずに入力ビデオを変更するだけでビデオを変更したい場合に機能する解決策です.

于 2013-01-26T19:55:12.483 に答える
0

これを見たかどうかはわかりませんが、jquery キューの利用について考えたことはありますか? ブラウザにロードすると、一部のフレームが表示されない、または空白になってから戻ってくるなどのことがわかります。以前はキューを使用して、"チェーン「特定の順序で一緒に....それで、各「画像フレーム」を同期的にロードして、各フレームが正しい順序でロードされるようにすることができる領域である可能性がありますか?

http://api.jquery.com/queue/

于 2013-01-26T23:19:35.763 に答える