"pause () 호출로 인해 play () 요청이 중단되었습니다"오류를 방지하는 방법은 무엇입니까?


107

사용자가 클릭하면 소리가 나는 웹 사이트를 만들었습니다. 사운드가 겹치는 것을 방지하기 위해 코드를 추가해야했습니다.

n.pause();
n.currentTime = 0;
n.play();

그러나 그로 인해 오류가 발생합니다. The play() request was interrupted by a call to pause()
사운드 이벤트가 다른 트리거 직후에 트리거 될 때마다 나타납니다. 소리는 여전히 잘 재생되지만이 오류 메시지가 계속해서 표시되는 것을 방지하고 싶습니다. 어떤 아이디어?


오류입니까, 아니면 더 많은 통지입니까?
dandavis

오류입니다. 다음은 전체 오류입니다. Uncaught (약속에서) DOMException : play () 요청이 pause () 호출에 의해 중단되었습니다.
Owen M

7
최신 버그이므로 걱정하지 마세요. bugs.chromium.org/p/chromium/issues/detail?id=593273
dandavis

3
이것에 대한 간단한 수정은 재생을 호출하거나 서로 즉시 일시 중지하지 않는 것입니다. 대신 미디어 이벤트를 사용하여 일시 중지 또는 재생시기를 결정하십시오. 예 : onCanPlay(). 이 모든 대답은 더러운 해킹입니다.
Martin Dawson

1
나는 반대의 문제가 있었다. 나는 n.play() 그때 시도했다 n.pause(). 이를 위해이 웹 기초 도움말 에서 솔루션에 대해 설명합니다. tl; dr :n.play().then(() => { n.pause()})
totymedli

답변:


84

최근에도이 문제가 발생했습니다.이 문제는 play()과 사이의 경쟁 조건 일 수 있습니다 pause(). 이 문제에 대한 언급이 있거나 여기에 관련된 내용이있는 것 같습니다 .

으로 @Patrick는 지적, pause위의 반응 용액 작동하지 않습니다, 약속 (또는 아무것도를) 반환하지 않습니다. MDN에는에 문서가 없지만 Media Elementspause() 에 대한 WC3 초안 에서 다음 과 같이 말합니다.

media.pause ()

paused 속성을 true로 설정하고 필요한 경우 미디어 리소스를로드합니다.

따라서 paused타임 아웃 콜백에서 속성을 확인할 수도 있습니다 .

이 훌륭한 SO 답변을 기반으로 비디오가 실제로 재생되는지 여부를 확인할 수있는 방법이 있으므로 오류없이 안전하게 play ()를 트리거 할 수 있습니다.

var isPlaying = video.currentTime > 0 && !video.paused && !video.ended 
    && video.readyState > 2;

if (!isPlaying) {
  video.play();
}

그렇지 않으면 @Patrick대답 이 작동합니다.


1
@ regency-software가 말했듯이 pause 메소드는 Promise (.pause ()에 문서가 없음)를 반환하지 않고 "정의되지 않음"만 반환합니다. 따라서이 솔루션은 play () 다음 pause () 경우에만 적용 할 수 있습니다.
Splact

정보에 감사드립니다-@regency 소프트웨어가 게시 한 내용을 반영하여 내 답변을 업데이트했으며 이는 정확했으며 작동하는 솔루션도 있습니다 :-).
JohnnyCoder

대기 시간으로 150ms에 어떻게 도착 했습니까? 크롬 문제인 것 같습니다 : bugs.chromium.org/p/chromium/issues/detail?id=593273
connect2krish

시간 초과 이유는 @Regency Software답변 을 참조하십시오 . 나는 그들의 대답을 확장했는데 이것은 좋은 해결책이었습니다. 또한 내 답변은 답변의 시작 부분에 제공 한 링크를 참조합니다.
JohnnyCoder

스트리밍 비디오에는 작동하지 않습니다. WebRTC 비디오를 초기화하는 경우 여전히 콘솔에 예외가 발생합니다.
Stepan Yakovenko

70

몇 시간의 검색과 작업 끝에 완벽한 해결책을 찾았습니다 .

// Initializing values
var isPlaying = true;

// On video playing toggle values
video.onplaying = function() {
    isPlaying = true;
};

// On video pause toggle values
video.onpause = function() {
    isPlaying = false;
};

// Play video function
function playVid() {      
    if (video.paused && !isPlaying) {
        video.play();
    }
} 

// Pause video function
function pauseVid() {     
    if (!video.paused && isPlaying) {
        video.pause();
    }
}

그 후에 가능한 한 빨리 재생 / 일시 중지 를 전환 할 수 있으며 제대로 작동 합니다.


1
이것이 제가 문제를 해결 한 방법입니다. 시간 초과에 의존하는 것보다 훨씬 더 나은 솔루션이라고 생각합니다
Malcor

@Malcor이 모두를 위해 문제를 해결할 것입니다, 감사
Nebojsa Sapic에게

어떤 사람들은이 답변에 대해 더 빨리 찬성 할 수 있도록 현상금을 걸 수 있습니까?
AddingColor

1
정답으로 표시되지 않은 이유는 무엇입니까? 확실히 이것은 시간 제한이있는 해킹이 아닌 해결책입니다.
jeron-diovis

15
두 개의 변수가 필요한 이유는 무엇입니까? 나는 이것이 나쁜 해결책이라고 말하는 것이 아닙니다. 그럭저럭하려고.
benevolentprof

20

나는이 문제를 겪었고 pause ()를 누른 다음 play ()를 눌러야하는 경우가 있지만 pause (). then ()을 사용할 때 정의되지 않습니다.

일시 중지 후 150ms 재생을 시작하면 문제가 해결된다는 것을 알았습니다. (곧 Google이 수정되기를 바랍니다.)

playerMP3.volume = 0;
playerMP3.pause();

//Avoid the Promise Error
setTimeout(function () {      
   playerMP3.play();
}, 150);

150ms를 의미한다면? 나는 몇 가지 다른 가치를 시도하고 내 목적을 위해 이것을 결정했습니다. 저는 Chrome과 Android를 대상으로하고 있었고 앱의 요구 사항에 맞았습니다. 더 낮을 수 있습니다.
Patrick

3
그래서 그것은 당신의 impl 이외의 다른 것과 관련이없는 것처럼 거의 임의의 값입니다. 설명에 감사드립니다!
y_nk

여러 사운드를 재생하기 위해 동일한 요소를 사용하고 있습니까? 그것은 부하 문제를 설명 할 것입니다. 동일한 요소를 통해 다른 사운드를 재생하는 동안 하나의 사운드가로드됩니다. 더 나은 / 최상의 경험을 위해 더 길거나 더 짧은 지연이 사용될 수 있지만 지연은 그것을 멈출 수 있습니다. 즉석에서 요소를 지우고 다시 만드는 것은 여러 오디오 / 비디오 및 메모리 누수를 건너 뛰는 SOP였습니다.
나무


8
경쟁 조건을 해결하는 데 임의의 setTimeout 기간을 사용해서는 안됩니다.
Gadget Blaster


5

시도 해봐

n.pause();
n.currentTime = 0;
var nopromise = {
   catch : new Function()
};
(n.play() || nopromise).catch(function(){}); ;


2

원하는 솔루션의 복잡성에 따라 다음이 유용 할 수 있습니다.

var currentPromise=false;    //Keeps track of active Promise

function playAudio(n){
    if(!currentPromise){    //normal behavior
        n.pause();
        n.currentTime = 0;
        currentPromise = n.play();    //Calls play. Will store a Promise object in newer versions of chrome;
                                      //stores undefined in other browsers
        if(currentPromise){    //Promise exists
            currentPromise.then(function(){ //handle Promise completion
                promiseComplete(n);
            });
        }
    }else{    //Wait for promise to complete
        //Store additional information to be called
        currentPromise.calledAgain = true;
    }
}

function promiseComplete(n){
    var callAgain = currentPromise.calledAgain;    //get stored information
    currentPromise = false;    //reset currentPromise variable
    if(callAgain){
        playAudio(n);
    }
}

이것은 약간 과잉이지만 독특한 시나리오에서 Promise를 처리 할 때 도움이됩니다.


2

여기에서 제안한 솔루션은 저에게 적합하지 않았거나 큰 곳에서 작동하지 않았으므로 다른 것을 찾고 있었고 bountysource.com/issues/에서 @dighan이 제안한 솔루션을 찾았습니다.

내 문제를 해결 한 코드는 다음과 같습니다.

var media = document.getElementById("YourVideo");
const playPromise = media.play();
if (playPromise !== null){
    playPromise.catch(() => { media.play(); })
}

여전히 콘솔에 오류가 발생하지만 적어도 비디오가 재생 중입니다. :)


1

내가 알아 낸 것처럼 이것에 대한 더 나은 해결책 일 것입니다. Spec은 @JohnnyCoder에서 인용 한대로 말합니다.

media.pause ()

paused 속성을 true로 설정하고 필요한 경우 미디어 리소스를로드합니다.

->로드

if (videoEl.readyState !== 4) {
    videoEl.load();
}
videoEl.play();

미디어 HAVE_ENOUGH_DATA = 4의 준비 상태를 나타냅니다.

기본적으로 아직로드되지 않은 경우에만 비디오를로드합니다. 동영상이로드되지 않았기 때문에 언급 된 오류가 발생했습니다. 시간 제한을 사용하는 것보다 나을 수도 있습니다.


1

모든 오류 제거 : (typescript)

audio.addEventListener('canplay', () => {
    audio.play();
    audio.pause();
    audio.removeEventListener('canplay');
}); 

1

라이브 스트리밍에서 나는 같은 문제에 직면했습니다. 내 수정은 이것입니다. html video TAG에서 "autoplay"제거 하고 아래 코드를 사용하여 재생하십시오.

if (Hls.isSupported()) {
            var video = document.getElementById('pgVideo');
            var hls = new Hls();
            hls.detachMedia();
            hls.loadSource('http://wpc.1445X.deltacdn.net/801885C/lft/apple/TSONY.m3u8');
            hls.attachMedia(video);
            hls.on(Hls.Events.MANIFEST_PARSED, function () {
                video.play();
            });
            hls.on(Hls.Events.ERROR, function (event, data) {
                if (data.fatal) {
                    switch (data.type) {
                        case Hls.ErrorTypes.NETWORK_ERROR:
                            // when try to recover network error
                            console.log("fatal network error encountered, try to recover");
                            hls.startLoad();
                            break;
                        case Hls.ErrorTypes.MEDIA_ERROR:
                            console.log("fatal media error encountered, try to recover");
                            hls.recoverMediaError();
                            break;
                        default:
                            // when cannot recover
                            hls.destroy();
                            break;
                    }
                }
            });
        }

1
훌륭한 솔루션 !!
Junaid Mukhtar

1

Chrome은 최신 버전에서 Promise를 반환합니다. 그렇지 않으면 간단히 :

        n.pause();
        n.currentTime = 0;
        setTimeout(function() {n.play()}, 0);

1

나는 같은 문제가 있으며 마침내 다음과 같이 해결합니다.

video.src = 'xxxxx';
video.load();
setTimeout(function() {
  video.play();
}, 0);

1

이 코드는 나를 위해 수정되었습니다!

@JohnnyCoder의 수정 된 코드

HTML :

 <video id="captureVideoId" muted width="1280" height="768"></video>
                <video controls id="recordedVideoId" muted width="1280" 
 style="display:none;" height="768"></video>

JS :

  var recordedVideo = document.querySelector('video#recordedVideoId');
  var superBuffer = new Blob(recordedBlobs, { type: 'video/webm' });
  recordedVideo.src = window.URL.createObjectURL(superBuffer);
  // workaround for non-seekable video taken from
  // https://bugs.chromium.org/p/chromium/issues/detail?id=642012#c23
  recordedVideo.addEventListener('loadedmetadata', function () {
    if (recordedVideo.duration === Infinity) {
        recordedVideo.currentTime = 1e101;
        recordedVideo.ontimeupdate = function () {
            recordedVideo.currentTime = 0;
            recordedVideo.ontimeupdate = function () {
                delete recordedVideo.ontimeupdate;
                var isPlaying = recordedVideo.currentTime > 0 && 
     !recordedVideo.paused && !recordedVideo.ended && 
      recordedVideo.readyState > 2;
                if (isPlaying) {
                    recordedVideo.play();
                }
            };
        };
       }
      });

1

다음 코드로 수정했습니다.

플레이하려면 다음을 사용하십시오.

var video_play = $('#video-play');
video_play.on('canplay', function() {
 video_play.trigger('play');
});

마찬가지로 일시 중지를 원할 때 :

var video_play = $('#video-play');
video_play.trigger('pause');

video_play.on('canplay', function() {
  video_play.trigger('pause');
});

0

비디오 다운로드가 매우 느리고 비디오가 버퍼링되지 않았기 때문에 다른 해결책이 있습니다.

if (videoElement.state.paused) { videoElement.play(); } else if (!isNaN(videoElement.state.duration)) { videoElement.pause(); }


0

많은 프로그래머가이 문제에 직면 한 것 같습니다. 해결책은 아주 간단해야합니다. 미디어 요소 Promise는 작업에서 반환 되므로

n.pause().then(function(){
    n.currentTime = 0;
    n.play();
})

트릭을해야한다


0

다음은 googler 블로그의 솔루션입니다.

var video = document.getElementById('#video')
var promise = video.play()
//chrome version 53+
if(promise){
    promise.then(_=>{
        video.pause()
    })
}else{
    video.addEventListener('canplaythrough', _=>{
        video.pause()
    }, false)
}

0

모든 새로운 브라우저는 비디오가 음소거 된 상태에서만 자동 재생되도록 지원하므로 이와 같은 것을 넣으십시오.

<video autoplay muted="muted" loop id="myVideo">
  <source src="https://w.r.glob.net/Coastline-3581.mp4" type="video/mp4">
</video>

사이트가 https로 실행되는 경우 동영상의 URL이 SSL 상태와 일치해야하며 동영상 URL도 https에 있어야하며 HTTP에 대해서도 동일해야합니다.


0

깨끗 하고 간단한 해결책 :

var p = video.play();
if (p !== undefined) p.catch(function(){});

0

이유 1-플레이 약속이 해결 될 때까지 기다리지 않고 일시 중지 호출

이 시나리오에 대한 답변이 너무 많으므로 해당 문제에 가장 적합한 문서를 참조하겠습니다.

https://developers.google.com/web/updates/2017/06/play-request-was-interrupted

이유 2-탭에 초점이 맞지 않을 때 재생 호출

이 경우 브라우저는 다음 play을 호출 하여 중단 할 수 있습니다.pause 는 탭에 포커스가 없을 때 있습니다. 활성 탭의 리소스를 절약하기 위해.

따라서 play를 호출하기 전에 탭에 초점이 맞춰질 때까지 기다릴 수 있습니다.


async function waitForTabFocus() {
  return new Promise((resolve, reject) => {
    const onFocus = () => { resolve(); window.removeEventListener('focus', onFocus) };
    window.addEventListener('focus', onFocus)
  })
}
if (!document.hasFocus()) await this.waitForTabFocus();
videoEl.play();

-1

동일한 문제가 발생하여을 autoplay사용하는 대신 동적으로 속성을 추가하여 문제를 해결했습니다 play(). 그런 식으로 브라우저는 경쟁 조건에 부딪히지 않고 플레이하는 것을 알아 냈습니다.


-1

play()끝날 때 호출하여 자동 재생 비디오를 반복하려고 시도 했지만 시간 제한 해결 방법이 작동하지 않았습니다 (시간 제한이 길어도).

그러나 비디오가 끝났을 때 jQuery로 비디오를 복제 / 교체하면 제대로 반복된다는 것을 발견했습니다.

예를 들면 :

<div class="container">
  <video autoplay>
    <source src="video.mp4" type="video/mp4">
  </video>
</div>

$(document).ready(function(){
  function bindReplay($video) {
    $video.on('ended', function(e){
      $video.remove();
      $video = $video.clone();
      bindReplay($video);
      $('.container').append($video);
    });
  }
  var $video = $('.container video');
  bindReplay($video);
});

Chrome 54.0.2840.59 (64 비트) / OS X 10.11.6을 사용하고 있습니다.


-1

나는 그들이 html5 비디오를 업데이트하고 일부 코덱을 사용하지 않는다고 생각합니다. 코덱을 제거한 후 저에게 효과적이었습니다.

아래 예에서 :

<video>
    <source src="sample-clip.mp4" type="video/mp4; codecs='avc1.42E01E, mp4a.40.2'">
    <source src="sample-clip.webm" type="video/webm; codecs='vp8, vorbis'"> 
</video>

    must be changed to

<video>
    <source src="sample-clip.mp4" type="video/mp4">
    <source src="sample-clip.webm" type="video/webm">
</video>


-1

Uncaught (in promise)이 오류가 표시되면 .catch()이 경우 약속을 처리해야 함을 의미합니다 .이 경우 .play()약속을 반환합니다. 메시지를 기록 할 것인지, 코드를 실행할 것인지, 아니면 아무것도하지 않을 것인지 결정할 수 있지만 .catch(), 오류가 발생하면 사라집니다.

var n = new Audio();
n.pause();
n.currentTime = 0;
n.play().catch(function(e) {
  // console.log('There was an error', e);
});

그것은 약속 반환하지 않습니다
마틴 도슨

@MartinMazzaDawson 약속을 반환합니다. xxx의 명확한 설명을 보면 "오류입니다. 여기에 전체 오류가 있습니다. Uncaught (약속에서) DOMException : The play () 요청이 pause () 호출에 의해 중단되었습니다."
seantomburke

-5

이 문제에 대응하기 위해 트릭을 사용했습니다. 전역 변수 var audio를 정의합니다.

그리고 기능 검사에서

if(audio === undefined)
{
   audio = new Audio(url);
}

그리고 정지 기능에서

audio.pause();
audio = undefined;

그래서 다음 전화 audio.play '0'currentTime부터 오디오가 준비됩니다.

나는 사용했다

audio.pause();
audio.currentTime =0.0; 

하지만 작동하지 않았습니다. 감사.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.