web-dev-qa-db-ja.com

setTimeoutを使用してループ内でビデオを再生する

動画をループ再生したい。何らかの理由で、終了したイベントでビデオの送信元を変更したくありません。そこで、ループ内の各ビデオのビデオ要素を作成しました。また、配列にビデオsrcと再生時間があります。

これが私のアイデアです。現在再生中のビデオタグのみが表示されます。その他は非表示になります。終了イベントを使用する代わりに、setTimeout関数を使用したいと思います。ビデオの長さは遅延パラメータになります。

しかし、それらはすべて一緒に遊びます。順番にプレイさせることができませんでした。

これが私がこれまでに行ったことです:

videoArray = [
    {"video":video1.mp4, "duration": 5},
    {"video":video2.mp4, "duration": 7},
    {"video":video3.mp4, "duration": 9},
    {"video":video4.mp4, "duration": 10},
]

for (var j = 0; j < videoArray.length; j++){
    var video = document.createElement("video");
    video.src=videoArray[j];
    video.id="video-"+j;
    video.preload = "metadata";
    video.type="video/mp4";
    video.autoplay = true; 
    video.style.display="none";
    document.body.appendChild(video); 
}

for (var count = 0; count < videoArray.length; count++) {
    (function(num){
        setTimeout(function() {
            videoArray[num].video.style.display="block";
            videoArray[num].video.play();
        }, 1000 * videoArray[num].duration);
        videoArray[num].video.style.display="none";
    })(count);
}
4
linepisode

あなたが何か奇妙なことを達成しようとしていること、そしてあなたのコード例がコンパイルされないという事実は別として。私がそれを見ると、あなたはそれを手に入れました。欠けているのはpause()と_display = "none"_だけです。最小限の編集で、必要なものが手に入ります。

_const videoArray = [
    {"video":"video1.mp4", "duration": 5}, // of cause you need "" 
    {"video":"video2.mp4", "duration": 7},
    {"video":"video3.mp4", "duration": 9},
    {"video":"video4.mp4", "duration": 10},
]

for (let j = 0; j < videoArray.length; j++){
    const video = document.createElement("video");
    // you need to save DOM nodes somewhere to use them in the second loop
    videoArray[j].video_el = video
    video.src=videoArray[j].video; // `.video` is added
    video.id="video-"+j;
    video.preload = "metadata";
    video.type="video/mp4";
    video.autoplay = true; 
    video.style.display="none";
    document.body.appendChild(video); 
}

for (var count = 0; count < videoArray.length; count++) {
    (function(num){
        setTimeout(function() {
            // add this to hide previous video node and stop video from playing 
            if( num ) {
                videoArray[num-1].video_el.style.display="none";
                videoArray[num-1].video_el.pause()
            }
            // videoArray[num].video - is a string, not a DOM node
            // so, you need to change this:
            // videoArray[num].video.style.display="block";
            // for this:
            videoArray[num].video_el.style.display="block";
            // no need. `autoplay` is set to `true` in the first loop
            // videoArray[num].video_el.play();
        }, 1000 * videoArray[num].duration);
        // no need. already done in the first loop
        // videoArray[num].video_el.style.display="none";
    })(count);
}
_

しかし多くの欠陥があります:

  1. setTimeoutはネットワークの遅延やその他の時間関連の問題を考慮しないため、おそらくビデオシーケンスがシームレスに再生されません。
  2. 最初のフローのため、およびdurationの値が正確であるとは思えないため、pause()を使用する必要があります。
  3. @IslamElshobokshyがあなたの質問へのコメントで述べたように、_play/pause_を使用することはそれほど単純ではありません。
  4. ユーザーがページを開いてそれ以上何もしない場合は、次のようになります。

    キャッチされていない(約束どおり)DOMException:play()は、ユーザーが最初にドキュメントを操作しなかったために失敗しました。

    chromeで。そして

    自動再生は、ユーザーによって承認された場合、サイトがユーザーによってアクティブ化された場合、またはメディアがミュートされている場合にのみ許可されます。
    NotAllowedError:おそらくユーザーが権限を拒否したため、現在のコンテキストではユーザーエージェントまたはプラットフォームによって再生メソッドが許可されていません。

    firefoxで。

ですから、結局、endedイベントとmuted属性(最後の問題を軽減するため)を使用する方が良いでしょう。

_for (let j = 0; j < videoArray.length; j++){
    const video = document.createElement("video")
    videoArray[j].video_el = video

    video.src      = videoArray[j].video
    video.id       = "video-"+j
    video.preload  = "metadata"
    video.type     = "video/mp4"
    video.autoplay = true

    // show the first video right away
    if( j !== 0 ) video.style.display = "none"
    // set muted attribute
    video.muted = "muted"
    // play next video after the previous had ended
    video.addEventListener('ended', (num => function() {
        this.style.display = "none";
        if( num !== videoArray.length-1 ) {
            videoArray[num+1].video_el.style.display="block";
            // only needed if `muted` is not set 
            videoArray[num+1].video_el.play();
        }
    })(j), false);

    document.body.appendChild(video); 
}
_

muted属性がオプションでない場合は、bodyにいくつかのイベントリスナーを追加して、ユーザーがページとの対話を開始するとすぐに最初の動画でplay()を呼び出すことができます。また、autoplayの詳細については、こちらをご覧ください: https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide

0
x00