質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1366閲覧

自作サイトでブラウザを非アクティブまたはタブを変更すると、動画が止まる

sumwave

総合スコア11

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/12/24 20:41

前提

html、javascriptで動画プレイヤーを作っています。
実際はnode.jsを使用したYouTubeダウンローラーですが、それはここではなしとします。

実現したいこと

タイトルの通り、<video> の再生がタブの変更などで非アクティブ化した際、
再生が止まってしまうのを解決したいです。
例えば、動画の音だけでも聞きながらほかの作業をしようとした際に、動画が停止してしまいます
まだ製作段階なので、とりあえずボタンとか雑ですがお許しを
divは好きです

該当のソースコード

html

1<html lang="ja"> 2 3<head> 4 <title>YouTube Player</title> 5 <script src="./playwith/index.js"></script> 6 <link type="text/css" rel="stylesheet" href="./playwith/stylesheet.css"> 7 <link type="text/css" rel="stylesheet" href="../publicstylesheet.css"> 8</head> 9 10<body> 11 <div class="leftAria"> 12 <div class="playerWindow"> 13 <video id="video" src="" poster="" preload="metadata"></video> 14 <div class="playerPopup"> 15 <div class="playerHeader"></div> 16 <div class="playerFooter"> 17 <div id="seekbar-wrap"> 18 <div id="seek-point"></div> 19 <div id="seekbar-out"> 20 <div id="seekbar-load"></div> 21 <div id="seekbar-in"></div> 22 </div> 23 </div> 24 </div> 25 </div> 26 </div> 27 </div> 28 <div class="rightAria"> 29 <input type="button" value="再生" onclick="video.play()"> 30 <input type="button" value="一時停止" onclick="video.pause()"> 31 </div> 32</body> 33 34</html>

./playwith/index.js

javascript

1addEventListener("load", e => { 2 const 3 video = document.getElementById("video"), 4 seekbarDrag = document.getElementById("seekbar-wrap"), 5 seekbarLoad = document.getElementById("seekbar-load"), 6 seekpoint = document.getElementById("seek-point"), 7 seekbarIn = document.getElementById("seekbar-in"), 8 audio = new Audio() 9 document.body.appendChild(audio) 10 video.addEventListener("timeupdate", e => { 11 let bufferNo 12 seekbarIn.style.transform = "scaleX(" + (video.currentTime / video.duration) + ")"; 13 seekpoint.style.left = (video.currentTime / video.duration) 14 for (let i = (video.buffered.length); bufferNo == undefined && video.buffered.length != 0 && i != 0; i--) { 15 if (video.buffered.start(i - 1) < video.currentTime) { 16 bufferNo = video.buffered.end(i - 1); 17 } 18 } 19 seekbarLoad.style.transform = "scaleX(" + (bufferNo / video.duration) + ")"; 20 }) 21 video.addEventListener("play", e => { 22 audio.currentTime = video.currentTime 23 audio.play() 24 }) 25 video.addEventListener("pause", e => { 26 audio.pause() 27 }) 28 seekbarDrag.addEventListener("click", e => { 29 e.preventDefault() 30 let percent = (e.pageX - (seekbarDrag.getBoundingClientRect().left + window.pageXOffset)) / seekbarDrag.clientWidth 31 video.currentTime = video.duration * percent 32 audio.currentTime = video.currentTime 33 }) 34 seekbarDrag.addEventListener("mousemove", e => { 35 e.preventDefault() 36 if (document.getElementsByClassName("drag")[0]) { 37 let percent = (e.pageX - (seekbarDrag.getBoundingClientRect().left + window.pageXOffset)) / seekbarDrag.clientWidth 38 video.currentTime = video.duration * percent 39 audio.currentTime = video.currentTime 40 } 41 }) 42 seekbarDrag.addEventListener("mousedown", e => seekbarDrag.classList.add("drag")) 43 seekbarDrag.addEventListener("mouseup", e => { 44 seekbarDrag.classList.remove("drag") 45 }) 46 const params = new Proxy(new URLSearchParams(window.location.search), { get: (searchParams, prop) => searchParams.get(prop) }) 47 const videoId = params.v 48 video.src = "../../ytvideo/" + videoId 49 audio.src = "../../ytaudio/" + videoId 50})

試したこと

js

1addEventListener("focus", e => e.preventDefault()) 2addEventListener("focusin", e => e.preventDefault()) 3addEventListener("focusout", e => e.preventDefault())

これでどうにか食い止められるかやってみましたが、何か変化はなかったです...

補足情報(FW/ツールのバージョンなど)

環境: Edge, Chrome

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

強引ではありますが、audioタグを使用した解決をします。
<audio>は例え他のタブへ移動しようとも、別のウィンドウで作業しようとも、
全く再生が止まらないため、それを利用し<video>の再生停止をコントロールする形で解決しました。
ただ、こんな強引な方法が正規なのかなんてわからないため、出来れば知識をお願いします。
これが本当にベストアンサーなのか。

コード

javascript

1const audio = new Audio() 2addEventListener("load", async e => { 3 const 4 video = document.getElementById("video"), //動画 5 seekbarDrag = document.getElementById("seekbar-wrap"), //シーク操作のために使用 6 seekbarLoad = document.getElementById("seekbar-load"), //バッファ表示に使用 7 seekpoint = document.getElementById("seek-point"), //小さな丸を表示するために使用 8 seekbarIn = document.getElementById("seekbar-in") //再生ケージ表示に使用 9 const videoRestart = () => { //動画と音声を同期させるために使用する 10 if (!audio.paused) { //再生中なら 11 audio.pause() //停止 12 video.currentTime = audio.currentTime //同期 13 setTimeout(() => audio.play(), 200) //パフォーマンスのため、遅延して再生 14 } else video.currentTime = audio.currentTime //停止していたら同期のみ 15 } 16 //丸の位置を設定 17 const seekpointmove = () => seekpoint.style.left = (audio.currentTime / audio.duration) * seekbarDrag.clientWidth - (seekpoint.clientWidth / 2) 18 addEventListener("focus", videoRestart) //フォーカス。ページがアクティブになったら 19 audio.addEventListener("timeupdate", e => { //時間が更新されたら 20 let bufferNo //バッファの数をカウントするために使用 21 seekbarIn.style.transform = "scaleX(" + (audio.currentTime / audio.duration) + ")"; //反映 22 seekpointmove() //丸の位置(ry 23 //再生位置にある最も近いバッファを取得する 24 for (let i = (audio.buffered.length); bufferNo == undefined && audio.buffered.length != 0 && i != 0; i--) { 25 if (audio.buffered.start(i - 1) < audio.currentTime) { 26 bufferNo = audio.buffered.end(i - 1); 27 } 28 } 29 seekbarLoad.style.transform = "scaleX(" + (bufferNo / audio.duration) + ")"; //反(ry 30 }) 31 addEventListener("resize", seekpointmove) //ウィンドウサイズ変更時に丸の位置を更新 32 audio.addEventListener("play", e => { //再生されると 33 audio.currentTime = video.currentTime //同期 34 video.play() //再生 35 }) 36 audio.addEventListener("pause", e => { //停止すると 37 video.pause() //停止 38 }) 39 seekbarDrag.addEventListener("click", e => { //シークバーのクリックで 40 e.preventDefault() //軽量化を狙う 41 //シークバーの長さをクリック位置からパーセントを計算 42 const percent = (e.pageX - (seekbarDrag.getBoundingClientRect().left + window.pageXOffset)) / seekbarDrag.clientWidth 43 audio.currentTime = audio.duration * percent //反映 44 videoRestart() //同期 45 }) 46 addEventListener("mousemove", e => { //マウス移動 47 e.preventDefault() //軽量化を狙う 48 if (document.getElementsByClassName("drag")[0]) { //ドラッグ中だったら 49 //シークバーの長さと丸のドラッグ位置からパーセ(ry 50 const percent = (e.pageX - (seekbarDrag.getBoundingClientRect().left + window.pageXOffset)) / seekbarDrag.clientWidth 51 audio.currentTime = audio.duration * percent 52 video.currentTime = audio.duration * percent 53 } 54 }) 55 seekpoint.addEventListener("mousedown", e => { //丸をクリックすると 56 seekbarDrag.classList.add("drag") //ドラック判定 57 if (video.played) video.pause() //動画のみ停止(パフォーマンス安定化) 58 }) 59 addEventListener("mouseup", e => { //クリック解除 60 if (document.getElementsByClassName("drag")[0]) { //ドラッグ中だったら 61 seekbarDrag.classList.remove("drag") //ドラッグ解除 62 audio.currentTime = video.currentTime //反映 63 videoRestart() //同期 64 } 65 }) 66 //クエリ取得 67 const params = new Proxy(new URLSearchParams(window.location.search), { get: (searchParams, prop) => searchParams.get(prop) }) 68 const videoId = params.v //VideoID 69 video.src = "/ytvideo/" + videoId //動画のファイルパス 70 video.poster = "/ytimage/" + videoId //動画のサムネ 71 audio.src = "/ytaudio/" + videoId //音声のファイルパス 72 try { audio.play() } catch (e) { } //自動再生 73})

説明

上のコードは実際に使用してるコードです。
そして非アクティブになって動画が止まろうとも、またアクティブになれば再生が始まります。
videoRestartという名の関数を使うことで、必ず音声と動画のタイミングが合うようにしています。
実際に使用しているコードはGitHubの various-programs に置いてあります。

投稿2022/12/25 22:27

sumwave

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問