Audio(Video)タグで"play() request was interrupted …"とかいうエラーが出てきたよ

Web開発/デザインjavascript

どうも最近はHTML5を使っているサイトも増えてきましたね。今作っているページもHTML5で作っているのですが、<video>やら<auidio>とかいうのもあったんですね(最近知りました)。というわけで、さっそくAudioを使ってみした。使ってみると動作的には正常に動いているように見えたのですが、”Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().”というエラーが出ちゃいました。というわけでどうにか解決できないかなーと奮闘する記事です。


1. どんな時に発生したか

さて、このエラーですが、どこで発生したのかをまず確認しようと思います。こういう時はコンソールを見るとエラーが発生している行数なんかが見えるものですが、今回の事例ではなぜかHTMLの1行目を示していて参考になりませんでした。しょうがないので、console.logをたくさん書いて、エラー箇所を見つけようと思ったのですが見つからずでした。しかし、エラー文からpley()とpause()が怪しいのは明らかです。というわけで、それを呼び出している箇所をコメントアウトしてみるとエラーが出なくなりました。

このことを踏まえつつGoogle先生で検索し、出てきたページの英文を必死こきながら解釈したところ、どうやらpause()した後にすぐplay()をするみたいなことをするとこのエラーが発生することがあるみたいです。確かに今回の自分のコードでは、連続してこれらの関数を使っていますが、そこ以外の箇所でエラーが発生しているようです。正直原因不明です。その後しばらく試行錯誤し、結局どう書いたところが悪かったかといますと、以下のコードの部分でした。このコード内の”addEventListener”の中にあるplay_seという関数を消したら大丈夫でした。ちなみに”addEventListener”外からこのplay_se関数を呼び出した場合はエラーは発生しませんでした。

簡単に何をしているかを説明しますと、再生中のSEが指定時間(1秒)になったら、再生を止め別のSEを鳴らすという処理です。これを、”timeupdate(再生箇所が変更されたら発火)”のリスナーに登録して実装していました。

2. 解決方法(仮)

さて先程はちらっと原因不明と書きましたが、自分的には、「リスナーの中でpuaseしちゃいけないんでね?」という発想に行き着きました。というわけで、pauseを行うplay_se関数を呼び出すお方法を”timeupdate”リスナーから、setTimeout関数という指定時間後に予約した処理を実行してくれるイケメンさんに変えてみました。すると、エラーは発生しなくなり。無事解決と相成りました。ちなみに以下が改良後のコードです。改良前と比べてむしろスマートになって嬉しい限りです。

つまり今回の記事をまとめると、指定時間で音声を入れ替えたい場合はリスナーなんか使わずにおとなしくsetTimeoutを使えって話でした。

おわりに

さて、今回も謎の備忘録ちっくにまとめてきました。やはり趣味でも何かしらの開発をしていると記事にすることは絶えませんね。投稿側からしたら記事にすることを探す手間が省けるので楽ですね。これからも頑張って続けるぞー。

2017-01-12Web開発/デザインjavascript