【デザイン基礎】HTMLMediaElementのplayedプロパティを極める:動画視聴データの分析とUX向上のための実装ガイド

概要

WebサイトやWebアプリケーションにおける動画コンテンツの重要性は年々高まっています。単に動画を再生させるだけでなく、「ユーザーがどの程度動画を視聴したか」「どの箇所を繰り返し再生したか」を正確に把握することは、マーケティング分析やUX改善において不可欠な指標です。HTML5のMedia APIが提供する `HTMLMediaElement.played` プロパティは、まさにそのために存在する強力なツールです。このプロパティは、メディア要素の再生履歴を `TimeRanges` オブジェクトとして保持しており、これを利用することで、ユーザーが「どの区間を視聴済みか」をプログラムから即座に特定することが可能になります。本記事では、このプロパティの仕様から、実務で使える高度な実装テクニック、そしてパフォーマンスを意識した設計までを網羅的に解説します。

詳細解説:TimeRangesオブジェクトの構造とplayedプロパティの挙動

`played` プロパティが返す `TimeRanges` オブジェクトは、メディア再生の履歴を管理する特殊なデータ構造です。ここを正しく理解しないと、単純な再生時間と混同し、実装ミスを招く恐れがあります。

`TimeRanges` は、複数の「再生済み区間」を保持する配列のようなオブジェクトです。例えば、ユーザーが動画を再生し、途中でシーク(スキップ)し、さらにその先を再生した場合、`played` プロパティ内には複数の区間(startとendのペア)が記録されます。

主なプロパティとメソッド:
– `length`: 記録されている区間の数。
– `start(index)`: 指定したインデックスの区間の開始時刻(秒単位)。
– `end(index)`: 指定したインデックスの区間の終了時刻(秒単位)。

重要な点は、`played` が「連続的な再生」を記録する点です。ユーザーが一時停止ボタンを押して再開した場合、あるいはシークバーを動かして別の箇所に移動した場合、`played` オブジェクトには新しい区間が追加されます。このため、単に `end` の最大値を取得するだけでは「総再生時間」にはならず、各区間の `end – start` を合計することで、正確な「ユニークな視聴済み時間」を算出する必要があります。

サンプルコード:視聴済み区間の可視化と総時間の算出

以下は、`played` プロパティを利用して、動画の視聴済み区間を計算し、合計の視聴時間を取得する実用的な実装例です。


const video = document.querySelector('video');

// 視聴済み合計時間を計算する関数
function getTotalPlayedTime(mediaElement) {
  const played = mediaElement.played;
  let total = 0;

  for (let i = 0; i < played.length; i++) {
    total += played.end(i) - played.start(i);
  }
  return total;
}

// 再生状況を監視するイベントリスナー
video.addEventListener('timeupdate', () => {
  const totalSeconds = getTotalPlayedTime(video);
  const duration = video.duration;
  
  // 視聴率を計算(パーセンテージ)
  const coverage = (totalSeconds / duration) * 100;
  
  console.log(`現在の視聴率: ${coverage.toFixed(2)}%`);
});

// ユーザーが動画を閉じる際にデータを送信する例
window.addEventListener('beforeunload', () => {
  const finalPlayedData = [];
  for (let i = 0; i < video.played.length; i++) {
    finalPlayedData.push({
      start: video.played.start(i),
      end: video.played.end(i)
    });
  }
  // navigator.sendBeaconでサーバーへ送信
  navigator.sendBeacon('/api/log-video-progress', JSON.stringify(finalPlayedData));
});

実務アドバイス:精度とパフォーマンスの両立

実務において `played` を扱う際、いくつかの注意点があります。

1. イベントの頻度と負荷
`timeupdate` イベントは非常に高頻度で発生します(通常は毎秒数回〜250ms毎)。このイベント内で複雑な計算を繰り返すと、メインスレッドをブロックし、動画の再生がカクつく原因になります。計算結果はキャッシュするか、特定の閾値を超えた時のみログを送信するよう設計してください。

2. シーク操作の追跡
`played` プロパティはブラウザが自動的に管理していますが、シーク操作によって「飛び地」が発生します。もしUI上で「視聴済みプログレスバー」を作成する場合、`played` の `length` が増えるたびにDOMを再描画するのではなく、Canvas APIなどを用いて描画負荷を抑えるのが賢明です。

3. データの欠落対策
`beforeunload` や `visibilitychange` イベントでデータを送信する場合、ブラウザの通信制限に注意が必要です。`navigator.sendBeacon` を活用することで、ページがアンロードされる直前でも確実にデータを送信できるため、必ずこれを利用してください。また、JSONのサイズが大きくなりすぎないよう、区間データは適宜サンプリングや間引きを行う設計も重要です。

4. 広告挿入時の挙動
動画内に広告(Vastなど)が挿入される場合、`HTMLMediaElement` が広告動画に切り替わることがあります。この際、`played` プロパティの内容は広告用要素に引き継がれるわけではありません。コンテンツ本編の視聴時間を計測したい場合は、広告再生中は監視を一時停止するなどのロジックが必要です。

まとめ

`HTMLMediaElement.played` プロパティは、Web動画の視聴体験をデータドリブンに改善するための鍵となります。単に「何秒再生されたか」だけでなく、「どこが繰り返し視聴されているのか」「どの区間がスキップされているのか」といった詳細なインサイトは、コンテンツの質を高めるための貴重な資産です。

実装にあたっては、以下のポイントを常に念頭に置いてください。
- `TimeRanges` オブジェクトの構造を理解し、合計時間を算出する際はループ処理を確実に行うこと。
- パフォーマンスのためにイベントの実行頻度と処理内容を最適化すること。
- データの欠損を防ぐために `sendBeacon` 等の非同期送信技術を活用すること。

Webデザイナーやエンジニアにとって、動画は単なるメディアではなく、ユーザーとの対話の場です。`played` プロパティを使いこなし、ユーザーの行動を正しく理解することで、より深く、より魅力的なコンテンツ体験を構築してください。本記事の内容が、あなたの次なるプロジェクトの技術的信頼性を高める一助となれば幸いです。

コメント

タイトルとURLをコピーしました