您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
AbemaTV(HTML5版)を閲覧中に動画が止まったとき、動画を再読み込みします。
当前为
// ==UserScript== // @name AbemaTV Auto Reload // @namespace https://greasyfork.org/ja/scripts/25598 // @version 3 // @description AbemaTV(HTML5版)を閲覧中に動画が止まったとき、動画を再読み込みします。 // @include https://abema.tv/now-on-air/* // @grant none // ==/UserScript== (function() { 'use strict'; /* ---------- Settings ---------- */ // 変更した値はWebブラウザのローカルストレージに保存するので // スクリプトをバージョンアップするたびに書き換える必要はありません。 // (値が0のとき、以前に変更した値か初期値を使用します) // 動画が止まったとき、チャンネルを切り替えるまでの待ち時間(ミリ秒) // 初期値:1500 // 有効値:1000~30000 var waitingReloadChannel = 0; /* ------------------------------ */ function log(s, t) { if (ls.debug) { if (t) console[t](sid, s); else console.log(sid, s); } } function logV(s, t) { if (ls.debug) { try { var v = returnVideo('logV'); if (v) { var a = [ v.readyState, v.networkState, v.played.length, v.currentTime, v.id.slice(v.id.indexOf('-') + 1), { 'duration': v.duration, 'seeking': v.seeking, 'preload': v.preload, 'ended': v.ended, 'srcLength': v.src.length }, Object.assign({}, flag) ]; if (Array.isArray(s)) { for (var i = s.length; i > 0; i--) { a.unshift(s[i - 1]); } } else a.unshift(s); if (v.paused) a.push('paused'); if (v.error) a.push('error', v.error.code); log(a, t); } else log(['logV not found Video', s], 'warn'); } catch (error) { log(['logV error', s, error], 'error'); } } } //デスクトップ通知 function notify(f, m, t, s) { var title = 'AbemaTV Auto Reload', message = m, notifi; log(['notify', f, m], t); if ('Notification' in window) { if (Notification.permission === 'granted') { notifi = new Notification(title, { body: message, tag: f }); } else if (Notification.permission !== 'denied') { Notification.requestPermission(function(permission) { if (permission === 'granted') { notifi = new Notification(title, { body: message, tag: f }); } }); } if (notifi) setTimeout(notifi.close.bind(notifi), s ? s : 3000); } else console.log(title, message); } //ローカルストレージに設定を保存する function saveLocalStorage() { localStorage.setItem(sid, JSON.stringify(ls)); } //HTML5動画の要素を返す function returnVideo(s) { var e = document.getElementsByTagName('video') || null, v; if (!e) log(['returnVideo error', s], 'debug'); else { var len = e.length; v = e[0]; if (len > 1) { for (var i = 0; i < len; i++) { if (e[i].id && /^videoplayer/.test(e[i].id)) { v = e[i]; break; } } } } return v; } //左下のチャンネルロゴ画像の要素を返す function returnChLogo(s) { var e = document.querySelector('div[class*="styles__channel-logo"] > img'); if (s) { if (e) { chId = e.getAttribute('alt'); log(['chId', chId], 'debug'); } else log('returnChLogo error', 'error'); } return e; } //動画を再読み込みする function reloadVideo(s) { logV(['reloadVideo', s]); if (!document.hidden && !flag.changeChannel && !flag.undoChannel) { if (theoplayer.player(0) && (!flag.reloadTime || (flag.reloadTime && Date.now() - flag.reloadTime < waitingReloadChannel))) { if (!flag.reloadTime) flag.reloadTime = Date.now(); theoplayer.player(0).load(); setTimeout(function() { checkPlayingVideo(eV.currentTime, 'reloadVideo'); }, 500); } else { if (!flag.changeChannel && !flag.undoChannel) changeChannel('reloadVideo'); else if (!flag.reload) { flag.reload = true; reloadPage(s); } } } } //チャンネルを切り替える function changeChannel(s) { log(['changeChannel', s], 'debug'); flag.reloadTime = 0; flag.changeChannel = true; eNext.click(); } //ページを再読み込みする function reloadPage(s) { if (flag.reload) { log(['reloadPage', s], 'debug'); notify('reloadPage', 'ページを再読み込みします!'); setTimeout(function() { location.reload(); }, 500); } } //動画が切り替わったかを調べる function checkChangeVideo(a) { logV('checkChangeVideo'); var e = returnVideo('checkChangeVideo'); if (!flag.change1 && !e) { log(['checkChangeVideo1', a]); flag.change1 = true; setTimeout(function() { flag.change1 = false; checkChangeVideo('checkChangeVideo'); }, 550); } else if (!flag.change2 && e && (!eV || e.id !== eV.id)) { log(['checkChangeVideo2', a]); flag.change2 = true; setTimeout(function() { flag.change2 = false; addEventVideo('checkChangeVideo'); }, 1000); } else { log(['checkChangeVideo3', a]); checkPlayingVideo(e.currentTime, 'checkChangeVideo3'); } } //動画が実際に再生中なのかを調べる function checkPlayingVideo(o, s) { setTimeout(function() { if (!eV || !eV.currentTime) { setTimeout(function() { checkChangeVideo('checkPlayingVideo'); }, 500); return; } var now = eV.currentTime; log(['checkPlayingVideo', s, 'time', o, now]); if (!now) { setTimeout(function() { var old = eV.currentTime; setTimeout(function() { now = eV.currentTime; if (!now || now === old) reloadVideo(s); }, 100); }, 2000); } else if (now === o) reloadVideo(s); }, 100); } //動画の取得中にエラーが発生したとき function videoError() { logV('videoError'); checkPlayingVideo(eV.currentTime, 'videoError'); } //動画を再生し始めたときや再生中にソースが切り替わったとき function videoPlaying() { logV('videoPlaying'); if (flag.reloadTime) { flag.reloadTime = 0; } if (flag.undoChannel) flag.undoChannel = false; } //動画を取得できなかったときや取得し終えたとき function videoStalled() { logV('videoStalled'); if (eV && (eV.readyState < 3 || eV.networkState !== 2)) checkPlayingVideo(eV.currentTime, 'videoStalled'); } //動画の読み込みを待っているとき function videoWaiting() { logV('videoWaiting'); var old = eV.currentTime; if (!old) reloadVideo('videoWaiting'); else checkPlayingVideo(old, 'videoWaiting'); } //動画を再生できるがキャッシュが足りないとき function videoCanplay() { logV('videoCanplay'); } //動画を再生できてキャッシュも足りるとき function videoCanplaythrough() { logV('videoCanplaythrough'); } //動画の長さが変更されたとき function videoDurationchange() { if (eV.readyState < 3 || eV.networkState !== 2) logV('videoDurationchange'); } //動画が空になったとき function videoEmpied() { logV('videoEmpied'); } //動画を最後まで再生したとき function videoEnded() { logV('videoEnded'); } //動画のメタ情報を読み込んだとき function videoLoadedmetadata() { logV('videoLoadedmetadata'); } //動画を再生できる状態になったとき function videoLoadeddata() { logV('videoLoadeddata'); } //動画をこれから読み込むとき function videoLoadstart() { logV('videoLoadstart'); } //動画を一時停止・解除したとき function videoPause() { logV('videoPause'); } //動画を(手動操作で)再生し始めたとき function videoPlay() { logV('videoPlay'); } //動画を取得しているとき function videoProgress() { logV('videoProgress'); } //動画をシークし終えたとき function videoSeeked() { logV('videoSeeked'); } //動画をシークし始めたとき function videoSeeking() { logV('videoSeeking'); } //動画の取得を取りやめたとき function videoSuspend() { logV('videoSuspend'); } //動画の再生位置が更新されたとき function videoTimeupdate() { if (eV.readyState < 3 || eV.networkState !== 2) logV('videoTimeupdate'); } //ページが見えている状態かを調べる function checkPageVisibility() { var h = document.hidden; log(['checkPageVisibility', h]); if (flag.hidden && !h && !eV.paused) checkPlayingVideo(eV.currentTime, 'checkPageVisibility'); flag.hidden = h; } //ページにイベントリスナーを追加 function addEventPage() { log('addEventPage'); document.addEventListener('visibilitychange', checkPageVisibility, false); } //動画にイベントリスナーを追加 function addEventVideo(s) { logV(['addEventVideo', s]); if (!flag.reload) { eV = returnVideo('addEventVideo2'); if (!eV) { checkChangeVideo('addEventVideo2'); return; } if (!eV.classList.contains(sid)) { eV.classList.add(sid); eV.addEventListener('error', videoError, false); eV.addEventListener('playing', videoPlaying, false); eV.addEventListener('stalled', videoStalled, false); eV.addEventListener('waiting', videoWaiting, false); if (ls.debug) { eV.addEventListener('canplay', videoCanplay, false); eV.addEventListener('canplaythrough', videoCanplaythrough, false); eV.addEventListener('durationchange', videoDurationchange, false); eV.addEventListener('emptied', videoEmpied, false); eV.addEventListener('ended', videoEnded, false); eV.addEventListener('loadeddata', videoLoadeddata, false); eV.addEventListener('loadedmetadata', videoLoadedmetadata, false); eV.addEventListener('loadstart', videoLoadstart, false); eV.addEventListener('pause', videoPause, false); eV.addEventListener('play', videoPlay, false); eV.addEventListener('progress', videoProgress, false); eV.addEventListener('seeked', videoSeeked, false); eV.addEventListener('seeking', videoSeeking, false); eV.addEventListener('suspend', videoSuspend, false); eV.addEventListener('timeupdate', videoTimeupdate, false); } } } } //動画が表示されるのを待つ function waitShowVideo(s) { log(['waitShowVideo', s, flag.show]); if (!flag.show) { flag.show = true; clearInterval(interval); setTimeout(function() { if (theoplayer.player(0) && !isNaN(theoplayer.player(0).duration)) { eV = returnVideo('waitShowVideo'); if (s === 'init') startObserve(); else addEventVideo('waitShowVideo1'); flag.show = false; } else { clearInterval(interval); interval = setInterval(function() { if (theoplayer.player(0) && !isNaN(theoplayer.player(0).duration)) { clearInterval(interval); flag.countWaitShowVideo = 0; eV = returnVideo('waitShowVideo'); if (s === 'init') startObserve(); else addEventVideo('waitShowVideo2'); flag.show = false; } else if (flag.countWaitShowVideo > 25) { clearInterval(interval); flag.countWaitShowVideo = 0; changeChannel('waitShowVideo'); } }, 200); } }, 400); } if (s === 'observerC') { returnChLogo('waitShowVideo-observerC'); if (flag.changeChannel && !flag.undoChannel) { log('undoChannel', 'debug'); flag.changeChannel = false; flag.undoChannel = true; ePrev.click(); setTimeout(function() { flag.undoChannel = false; }, 100); } } } function waitShowVideoC() { waitShowVideo('observerC'); } function waitShowVideoV() { waitShowVideo('observerV'); } //ページを開いて動画が表示されたら1度だけ実行 function startObserve() { log('startObserve'); ePrev = document.querySelector('div[class^="style__box"] > button:first-child'); eNext = document.querySelector('div[class^="style__box"] > button:last-child'); observerC.observe(returnChLogo(), moConfig); observerV.observe(eV.parentNode, moConfig2); addEventPage(); addEventVideo('startObserve'); } //ページを開いたときに1度だけ実行 function init() { log('init'); var rc = (!Number.isInteger(waitingReloadChannel)) ? 0 : waitingReloadChannel; rc = (rc === 0) ? 0 : (rc > 30000) ? 30000 : (rc < 1000) ? 1000 : rc; waitingReloadChannel = (rc) ? rc : 1500; if (ls.waitingReloadChannel && rc && ls.waitingReloadChannel !== rc) { ls.waitingReloadChannel = rc; saveLocalStorage(); } waitShowVideo('init'); } var sid = 'AutoReload', ls = JSON.parse(localStorage.getItem(sid)) || {}, observerC = new MutationObserver(waitShowVideoC), observerV = new MutationObserver(waitShowVideoV), moConfig = { attributes: true, characterData: true }, moConfig2 = { childList: true }, flag = { change1: false, change2: false, changeChannel: false, countWaitShowVideo: 0, hidden: false, loadstart: false, reload: false, reloadTime: 0, show: false, undoChannel: false }, eV, ePrev, eNext, chId, interval; init(); })();