0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【GAS】YouTubeのライブ配信の同接の統計を取る

Posted at

できるもの

設定した時間おきに、ライブ配信の「集計日時、同接、高評価数」がスプレッドシートの指定した列に追加されていきます。
一気に複数のライブ配信を集計することも可能です。

動画ID(URLから特定可能)がわかればどんな動画も集計できるはずです。
ちなみに、スプレッドシートの機能でデータをグラフにすると見てて楽しいです。

他の方のライブ配信の統計を投稿者の了承なく取っていいのか、またその統計結果を許可を取らずに公開していいのかどうかは、私にはわかりません。
詳しい人いたら教えてください。

また、この記事を参考にしたことで何かあっても責任は取りません。
ご了承ください。

動画の再生回数や高評価数の統計を取りたい方はこちら↓
(終了したライブ配信の再生回数などを取りたい場合もこちら)

※この記事は上記の記事の続編です。
そのため一部内容が似通っていますがご了承ください。

準備

コードを書き始めるに、まずは環境の準備が必要です。

新しくプロジェクトを作る

まずはデータを出力するためのスプレッドシートを新しく作ります。
このスプシにライブ配信の統計データが入ります。

また、このスプレッドシートの「拡張機能」タブからApps Scriptを選択して、
GASのエディタ画面を開いておいてください。

gas_editor.png

YouTube Data APIを入れる

GASの画面で、左側にある「サービス」の隣の+をクリックします。
そしてそこから 「YouTube Data API v3」を選択 します。
バージョンはv3、IDはYouTubeのままで大丈夫です。

api.png

サービスのところにYouTubeが追加されていたら成功です。

service.png

このYouTubeはGASのコードから使えるAPIで、配信データはこれを通して取得します。

コードを書く

解説を読む時間がない方は完成形もありますので、ぜひご活用ください。

準備が整ったので、早速データ取得を行うコードを書きます。
コードではこんな感じのことをやります。

  1. ライブ配信が配信中か終了済みかを示すステータスを更新する
  2. ステータスがlive_activeになっている配信の動画IDを取得する
  3. 2の配信のデータを取得する
  4. 3のデータをスプレッドシートに出力する

また、同時に以下の機能も作ります。

  • テンプレートの自動入力機能
  • 上記の処理を実行するコンテキストメニュー

配信データを取得する

色々書きましたが、まずは全ての基盤となる配信データ取得用の関数を作ります。

function fetchLiveData(id) { // 動画IDを引数に取る
  const data = YouTube.Videos.list('statistics,liveStreamingDetails', { id });
  console.log('データを取得: ', data.items[0]); // デバッグ用
  return data.items[0];
}

この関数ではYouTube.Videos.listという関数を呼び出しています。
これはYouTubeのライブ配信や動画のデータを取得するためのAPIです。

YouTube.Videos.list('statistics,liveStreamingDetails', { id });

YouTube.Videos.listは、第一引数に取得したいデータのタイプを取ります。
ここではstatisticsliveStreamingDetailsを指定しています。

  • statistics: 動画に関する統計情報(高評価数など)
  • liveStreamingDetails: 配信中のライブ配信に関する統計情報(同接など)

YouTube Data APIの解説はドキュメントが一番わかり易いと思うので、こちらもぜひご覧ください。


ここで一度、この関数をテストしておきます。

まずはテスト用の関数であるtestを実装します。

function test() {
  console.log(fetchLiveData("ここに動画ID"))
}

次は、そのへんから適当に配信中のライブ配信を見つけてください。
そして、その配信の動画IDを上記のコードのここに動画IDの部分にコピペします。

動画IDとは、たとえば https://www.youtube.com/watch?v=aaaaaaaaaa というURLの動画あったとしたら、動画IDはaaaaaaaaaaです。
URLのv=以降の部分を抜き出してください。

testを実行したときにそれっぽいデータがログに流れればOKです。

テンプレートの自動入力機能を作る

例えば以下のようなシートがあったとします。

A B C
1
2
3

ここのA1セルに[videoId]:liveという文字を入れます。

A B C
1 4WXs3sKu41I:live
2
3

そしたら以下のように自動入力される機能を、今から作ります。

A B C
1 4WXs3sKu41I:live videoId = 4WXs3sKu41I live_null
2 日時 同接 高評価数
3

上の例だと4WXs3sKu41Iという動画IDのライブ配信が集計されることになります。
また、live_nullは前述したステータスの1つで、初期状態(ステータス未取得)を示します。


実装はこんな感じです。

function onEdit(e) {
  if(e.range.getRow() !== 1)  return;

  const cellValues = e.range.getValue()?.split(':');
  if(cellValues.length < 2) return;
  if(cellValues[0].length !== 11) return;
  if(!triggers.includes(cellValues[1])) return;

  if (cellValues[1] !== 'live') return
  const nextRange = e.range.getSheet().getRange(e.range.getRow(), e.range.getColumn() + 1, 1, 2);
  nextRange.setValues([['videoId = ' + cellValues[0], 'live_null']]);
  const bottomRange = e.range.getSheet().getRange(e.range.getRow()+1, e.range.getColumn(), 1, 3);
  bottomRange.setValues([['日時', '同接', '高評価']])
}

onEditは特殊な関数で、スプレッドシートにユーザーが変更を加えた時に自動的に実行されます。
また、第一引数のオブジェクトのrangeから編集されたセルのRangeが取得できます。

ステータスの更新関数を作る

まず、ステータスとはその配信が配信中かどうかを示すものです。
終了済みのライブ配信はこれ以上集計する必要がなく、過去に集計した全ての配信に毎回リクエストを送るのは非効率的です。
そのため、スプレッドシートの特定のセルにステータスを保存し、現在配信中の配信のみからデータを取得していきます。

ステータスには以下の3種類があります。

  • live_null: ステータス未取得
    • 自動入力によって入力される
    • 更新によってlive_activeまたはlive_completedになる
  • live_active: 配信中
    • 更新によってlive_completedになる可能性がある
  • live_completed: 終了済み
    • 更新されない

実装はこちらです。

const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

function updateStatus() {
  function isActiveLive(id) {
    const data = fetchLiveData(id)
    return !!data.liveStreamingDetails.concurrentViewers
  }
  for (const sheet of spreadsheet.getSheets()) {
    const rowA = sheet.getRange(1,1,1,sheet.getLastColumn());
    for(const [column, cell] of rowA.getValues()[0].entries()) {
      if (!['live_null', 'live_active'].includes(cell)) continue
      const videoId = rowA.getCell(1, column).getValue().split(" ")[2]
      const isActive = isActiveLive(videoId)
      const statusRange = rowA.getCell(1, column + 1)
        
      if (cell === 'live_null') {
        statusRange.setValue(isActive ? 'live_active' : 'live_completed')
        console.log(`Updated: live ${videoId} status`)
      }
      if (cell === 'live_active' && !isActive) {
        statusRange.setValue('live_completed')
        console.log(`Updated: live ${videoId} status to completed`)
      }
    }
  }
}

ここではlive_nullまたはlive_activeが入力されているセルを探しています。
そして、その左にある動画IDからステータスを取得して更新しています。

また、その配信が配信中かどうかはisActiveLive関数が判定しています。


ここで一度この関数をテストしておきます。

まずは自動入力を使ってシートを以下の状態にします。
といっても、A1セルにWr6477JwkNk:liveを入力するだけで大丈夫なはずです。

A B C
1 Wr6477JwkNk:live videoId = Wr6477JwkNk live_null
2 日時 同接 高評価数
3

ここではC1セルがステータスの保管場所になります。

次にupdateStatus関数を実行します。
Wr6477JwkNkは終了済みのライブ配信の動画IDなので、実行するとC1セルの文字列がlive_completedに置き換わるはずです。
無事に置き換わっていれば成功です。

また、そのへんから配信中のライブ配信を見つけて同じテストをし、ステータスがlive_activeになることも確認してみてください。

最終行を返す関数を作る

そしたらいよいよシートにデータを追加したいところですが、その前にデータを追加したい列の最終行を返す関数を作ります。

function getLastRow(column, sheet) {
  const range = sheet.getRange(1, column, sheet.getLastRow(), column);
  const result = range.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
  
  if(range.getValues()[1]?.[0] == '') {
    return 1;
  } else {
    return result;
  }
}

ここではrange.getNextDataCell(SpreadsheetApp.Direction.DOWN)を使って、データがある最終行のセルを取得しています。
そしたらgetRow()を使い、そのセルの行数(=最終行の行数)を取得しています。

こちらのサイトを参考にしました。

メイン処理を作る

最後に、live_activeになっている全ての配信を探し、そのデータを取って出力する関数liveを実装します。
あとはこれを数分おきに実行するだけでOKな状態まで持っていきます。

実装はこちらです。

function live() {
  updateStatus() // 事前にステータスを更新
  for (const sheet of spreadsheet.getSheets()) {
    const rowA = sheet.getRange(1,1,1,sheet.getLastColumn());
    for(const [column, str] of rowA.getValues()[0].entries()) {
      if (str !== 'live_active') continue 
      // データを取得してシートに出力
      const videoId = rowA.getCell(1, column).getValue().split(" ")[2]
      const data = fetchLiveData(videoId)
      const range = sheet.getRange(getLastRow(column, sheet) + 1, column - 1, 1, 3)
      range.setValues([[new Date(), data.liveStreamingDetails.concurrentViewers, data.statistics.likeCount]]);
    }
  }
}

この関数は冒頭で言った手順を実行しています。

  1. updateStatusでステータスを更新する
  2. ステータスがlive_activeになっている配信の動画IDを取得する
  3. 2の配信のデータをfetchLiveDataで取得する
  4. 3のデータをスプレッドシートに出力する

一度この関数をテストしてみます。
ちなみにこれが動けばほかも問題ないはずです。

まずはそのへんから配信中の配信を探し、[動画ID]:live形式の文字列を入力します。
そうしたら自動入力が機能し、ステータスがlive_nullになるはずです。

そしたらlive関数を実行します。
実行した結果、

  • ステータスがlive_activeになる
  • 同接と高評価のデータが追加される

これらが起これば成功です。

以下は一例です。

A B C
1 xxxxxxxx:live videoId = xxxxxxx live_active
2 日時 同接 高評価数
3 2025/8/15 12:30:00 1000 142

おまけ: liveを実行するメニューを追加する

今後この統計システムを使う上で、数分おきの自動実行だけではなく自分の好きなタイミングでliveを実行したくなるときが来ると思います。
また、作っておくとデバッグでも非常に便利です。
ということで、メニューをポチポチするだけで統計が更新できる機能を作ります。

実装はこちらです。

function onOpen() {
  spreadsheet.addMenu('統計を更新', [
    {name: 'ライブ配信を更新', functionName: 'live'},
  ]);
}

onOpenonEditのように特殊な関数で、スプレッドシートを開いたタイミングで自動的に実行されます。
その中でメニューを追加する関数であるaddMenuを呼ぶことで、スプシを開くとメニューが追加される仕組みです。(数秒ほどの遅延はありますが...)

また、これが実行されると、上部の「ファイル」「編集」「表示」とか書いてあるところに「統計を更新」が増えます。
その中に「ライブ配信を更新」があり、それを押すとlive関数が実行され、データが1行増えるはずです。

完成形

ここまでのコードをまとめたものはこちらです。

コピペ用
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

function live() {
  updateStatus() // 事前にステータスを更新
  for (const sheet of spreadsheet.getSheets()) {
    const rowA = sheet.getRange(1,1,1,sheet.getLastColumn());
    for(const [column, str] of rowA.getValues()[0].entries()) {
      if (str !== 'live_active') continue 
      // データを取得してシートに出力
      const videoId = rowA.getCell(1, column).getValue().split(" ")[2]
      const data = fetchLiveData(videoId)
      const range = sheet.getRange(getLastRow(column, sheet) + 1, column - 1, 1, 3)
      range.setValues([[new Date(), data.liveStreamingDetails.concurrentViewers, data.statistics.likeCount]]);
    }
  }
}

function updateStatus() {
  function isActiveLive(id) {
    const data = fetchLiveData(id)
    return !!data.liveStreamingDetails.concurrentViewers
  }
  for (const sheet of spreadsheet.getSheets()) {
    const rowA = sheet.getRange(1,1,1,sheet.getLastColumn());
    for(const [column, cell] of rowA.getValues()[0].entries()) {
      if (!['live_null', 'live_active'].includes(cell)) continue
      const videoId = rowA.getCell(1, column).getValue().split(" ")[2]
      const isActive = isActiveLive(videoId)
      const statusRange = rowA.getCell(1, column + 1)
        
      if (cell === 'live_null') {
        statusRange.setValue(isActive ? 'live_active' : 'live_completed')
        console.log(`Updated: live ${videoId} status`)
      }
      if (cell === 'live_active' && !isActive) {
        statusRange.setValue('live_completed')
        console.log(`Updated: live ${videoId} status to completed`)
      }
    }
  }
}

function getLastRow(column, sheet) {
  const range = sheet.getRange(1, column, sheet.getLastRow(), column);
  const result = range.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
  
  if(range.getValues()[1]?.[0] == '') {
    return 1;
  } else {
    return result;
  }
}

function onEdit(e) {
  if(e.range.getRow() !== 1)  return;

  const cellValues = e.range.getValue()?.split(':');
  if(cellValues.length < 2) return;
  if(cellValues[0].length !== 11) return;
  if(!triggers.includes(cellValues[1])) return;

  if (cellValues[1] !== 'live') return
  const nextRange = e.range.getSheet().getRange(e.range.getRow(), e.range.getColumn() + 1, 1, 2);
  nextRange.setValues([['videoId = ' + cellValues[0], 'live_null']]);
  const bottomRange = e.range.getSheet().getRange(e.range.getRow()+1, e.range.getColumn(), 1, 3);
  bottomRange.setValues([['日時', '同接', '高評価']])
}

function onOpen() {
  spreadsheet.addMenu('統計を更新', [
    {name: 'ライブ配信を更新', functionName: 'live'},
  ]);
}

トリガーを設定する

ということで、live関数が一定時間おきに自動で実行されるようにします。
これにより我々は統計を気にせず集中して配信を見ることができます。

まずはサイドバーの時計アイコン(上から4番目)を押します。
次に、右下に「トリガーを追加」と書かれたボタンがあるので押します。

するとポップアップが出てくるので、適切に設定を行います。

trigger.png

  • 実行する関数を選択: live
  • 実行するデプロイを選択: Head(初期設定のまま)
  • イベントのソースを選択: 時間主導型
  • 時間ベースのトリガーのタイプを選択: 分ベースのタイマー
  • 時間の間隔を選択: 10分おき
  • エラー通知設定: お好みでどうぞ(最初は「今すぐ通知を受け取る」がおすすめ)

このうち「時間ベースのトリガーのタイプを選択」と「時間の間隔を選択」を変更することで、集計の間隔(=liveが実行される間隔)を変更できます。
上記の設定だと10分おきですが、ほかにも1分おきや30分おきなどの設定国目があるので、お好みで調整してみてください。

これが設定できたら完成です。

運用方法の一つとして、統計を取りたいライブ配信があるたびにトリガーを追加し、終わったら削除するという方法があります。
毎回追加しなければならないのは面倒ですが、普段使わないトリガーをずっと残しておくのはデメリットもあるかもしれません。

場合によってはGoogleからのエラー通知メール(しかも内容はよくわからない)が毎日来て邪魔になることもあります。
そうなったらぜひお試しください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?