"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.