0

次のコードでキャンバスを使用して、HTML5ビデオからブラウザでサムネイルのグループを生成しようとしています。

        var fps = video_model.getFps(); //frames per second, comes from another script
        var start = shot.getStart(); //start time of capture, comes from another script
        var end = shot.getEnd(); //end time of capture, comes from another script

        for(var i = start; i <= end; i += 50){  //capture every 50 frames
            video.get(0).currentTime = i / fps;

            var capture = $(document.createElement("canvas"))
                .attr({
                    id: video.get(0).currentTime + "sec",
                    width: video.get(0).videoWidth,
                    height: video.get(0).videoHeight
                })

            var ctx = capture.get(0).getContext("2d");
            ctx.drawImage(video.get(0), 0, 0, video.get(0).videoWidth, video.get(0).videoHeight);

            $("body").append(capture, " ");

        }

キャプチャの量は正しいですが、問題は、Chromeではすべてのキャンバスが黒く表示され、Firefoxでは常に同じ画像が表示されることです。

問題は、ループが速すぎてキャンバスをペイントできないことかもしれませんが、.drawImage()は非同期であるため、理論的には、次の行にジャンプする前にキャンバスをペイントする必要があります。

この問題を解決する方法について何かアイデアはありますか?ありがとう。

4

1 に答える 1

0

これと何時間も戦った後、私はついに「求められた」イベントに基づいた解決策を思いつきました。これを機能させるには、ビデオを完全にロードする必要があります。

コードは次のようになります。

        var fps = video_model.getFps(); //screenshot data, comes from another script
        var start = shot.getStart();
        var end = shot.getEnd();


        video.get(0).currentTime = start/fps; //make the video jump to the start


        video.on("seeked", function(){ //when the time is seeked, capture screenshot
            setTimeout( //the trick is in giving the canvas a little time to be created and painted, 500ms should be enough
                function(){
                    if( video.get(0).currentTime <= end/fps ){

                        var capture = $(document.createElement("canvas")) //create canvas element on the fly
                        .attr({
                            id: video.get(0).currentTime + "sec",
                            width: video.get(0).videoWidth,
                            height: video.get(0).videoHeight
                        })
                        .appendTo("body");

                        var ctx = capture.get(0).getContext("2d"); //paint canvas
                        ctx.drawImage(video.get(0), 0, 0, video.get(0).videoWidth, video.get(0).videoHeight);

                        if(video.get(0).currentTime + 50/fps > end/fps){
                            video.off("seeked"); //if last screenshot was captured, unbind
                        }else{
                              video.get(0).currentTime += 50/fps; //capture every 50 frames
                        }


                    }
                }
                , 500); //timeout of 500ms


        });

これはChromeとFirefoxでうまくいきました。特定のブラウザの一部のバージョンでは、シークされたイベントがバグになる可能性があることを読みました。

これが誰にとっても役立つことを願っています。誰かがよりクリーンでより良い解決策を思いついたら、それを見るのは素晴らしいことです。

于 2012-07-27T12:05:56.913 に答える