youtube iframe api(ブラウザ上でyoutube再生をjs操作できるライブラリ)で視聴時間をカウント(倍速なら倍)。視聴完了も検知する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>YouTube IFrame API - レジューム再生と視聴時間記録</title> <script> var player; var watchTime = 0; // 実際に見た時間(秒) var lastTime = 0; // 直前の再生位置 var lastTimestamp = 0; // 最後に計測した時間 var tracking = false; // 視聴時間の計測状態 var threshold = 2; // シーク検知の閾値(2秒以上の移動はシークとみなす) var videoId = 'M7lc1UVf-VE'; // YouTube動画ID(変更可能) var resumeTime = 0; // レジューム用の再生位置 // LocalStorage から視聴データを取得 function loadWatchData() { var savedData = JSON.parse(localStorage.getItem('youtube_watch_data')) || {}; if (savedData[videoId]) { resumeTime = savedData[videoId].lastTime || 0; watchTime = savedData[videoId].watchTime || 0; } } // YouTube IFrame API の読み込み function onYouTubeIframeAPIReady() { loadWatchData(); // 視聴データを読み込む player = new YT.Player('player', { height: '360', width: '640', videoId: videoId, events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } }); } // プレイヤー準備完了時の処理 function onPlayerReady(event) { console.log("YouTubeプレイヤーが準備完了"); if (resumeTime > 0) { console.log(`レジューム再生: {resumeTime}秒から再開`); player.seekTo(resumeTime, true); // シークして再生位置を復元 } updateWatchTimeDisplay(); // 表示更新 } // プレイヤーの状態変化を監視 function onPlayerStateChange(event) { if (event.data == YT.PlayerState.PLAYING) { console.log("再生開始"); startTrackingWatchTime(); } else if (event.data == YT.PlayerState.PAUSED) { console.log("一時停止"); stopTrackingWatchTime(); saveWatchData(); } else if (event.data == YT.PlayerState.ENDED) { console.log("動画終了"); stopTrackingWatchTime(); saveWatchData(); document.getElementById("status").innerText = "視聴完了 ✅"; } } // 視聴時間の計測を開始 function startTrackingWatchTime() { tracking = true; lastTimestamp = performance.now(); lastTime = player.getCurrentTime(); trackTime(); } function trackTime() { if (!tracking) return; let now = performance.now(); let elapsed = (now - lastTimestamp) / 1000; // 経過時間(秒) lastTimestamp = now; let currentTime = player.getCurrentTime(); let timeDiff = currentTime - lastTime; let playbackRate = player.getPlaybackRate(); // 現在の再生速度 // シークしていない場合、視聴時間を加算 if (timeDiff >= 0 && timeDiff <= threshold) { watchTime += elapsed * playbackRate; // 再生速度を考慮 } else { console.log("シーク検知! 視聴時間には加算しない"); } lastTime = currentTime; saveWatchData(); // 視聴時間を保存 updateWatchTimeDisplay(); requestAnimationFrame(trackTime); } function stopTrackingWatchTime() { tracking = false; } // 視聴データを保存 (LocalStorage) function saveWatchData() { var currentTime = player.getCurrentTime(); var saveData = JSON.parse(localStorage.getItem('youtube_watch_data')) || {}; saveData[videoId] = { lastTime: currentTime, watchTime: watchTime }; localStorage.setItem('youtube_watch_data', JSON.stringify(saveData)); } // 視聴時間を更新 function updateWatchTimeDisplay() { document.getElementById("watchTimeDisplay").innerText = "視聴時間: " + formatTime(watchTime); } // 時:分:秒 形式に変換 function formatTime(seconds) { const h = Math.floor(seconds / 3600); const m = Math.floor((seconds % 3600) / 60); const s = Math.floor(seconds % 60); return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`; } // 視聴データをクリア function clearWatchData() { var saveData = JSON.parse(localStorage.getItem('youtube_watch_data')) || {}; delete saveData[videoId]; localStorage.setItem('youtube_watch_data', JSON.stringify(saveData)); watchTime = 0; resumeTime = 0; updateWatchTimeDisplay(); document.getElementById("status").innerText = ""; alert("視聴データをリセットしました"); } </script> <!-- キャッシュ対策 --> <script> var script = document.createElement("script"); script.src = "https://www.youtube.com/iframe_api?v=" + new Date().getTime(); document.head.appendChild(script); </script> </head> <body> <h1>YouTube IFrame API - レジューム再生と視聴時間記録</h1> <div id="player"></div> <h2>視聴情報</h2> <p id="watchTimeDisplay">視聴時間: 00:00:00</p> <p id="status"></p> <button onclick="clearWatchData()">視聴データをリセット</button> </body> </html> |