DynamoDB, AppSync,GraphQLについて学んでみた
DynamoDB, AppSync,GraphQLについて学んでみた DynamoDB = MySQL = データストア AppSync = APIサーバ = エンドポイント GraphQL = SQL = 問い合わせ言 続きを読む DynamoDB, AppSync,GraphQLについて学んでみた
本とか料理とかコンピュータとか
DynamoDB, AppSync,GraphQLについて学んでみた DynamoDB = MySQL = データストア AppSync = APIサーバ = エンドポイント GraphQL = SQL = 問い合わせ言 続きを読む DynamoDB, AppSync,GraphQLについて学んでみた
朝っぱらからサーロインステーキ!ヒラメのアラ煮、鯛の煮干しと昆布のお吸い物 1キロ近くあると大迫力! こういう時のためのグリルパン う~ん、めちゃ豪華! マグロぶつならぬステーキぶつみたいになった。 もうちょいレア気味の 続きを読む 朝っぱらからサーロインステーキ!ヒラメのアラ煮、鯛の煮干しと昆布のお吸い物
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> |
大アジフライ定食1300円@かつ誠@築地 築地かつ誠 築地本願寺の裏手にある この店の正解は、左上のロースカツ。あん肝フライは珍しい。 店内は見事におじさんばかり! 大アジフライ定食。1300円なんだから、もうちょい何か 続きを読む 大アジフライ定食1300円@かつ誠@築地
麻布十品定食1859円@福島屋(おでん屋)@麻布十番。自分以外の5人とも女性客だった。 福島屋 行こう行こうと思いつつ、数年が経過したので行ってみた。 サクッと出てくるのかと思ったら10分位かかった。 千切りキャベツで一 続きを読む 麻布十品定食1859円@福島屋(おでん屋)@麻布十番。自分以外の5人とも女性客だった。