できるもの
設定した時間おきに、ライブ配信の「集計日時、同接、高評価数」がスプレッドシートの指定した列に追加されていきます。
一気に複数のライブ配信を集計することも可能です。
動画ID(URLから特定可能)がわかればどんな動画も集計できるはずです。
ちなみに、スプレッドシートの機能でデータをグラフにすると見てて楽しいです。
他の方のライブ配信の統計を投稿者の了承なく取っていいのか、またその統計結果を許可を取らずに公開していいのかどうかは、私にはわかりません。
詳しい人いたら教えてください。
また、この記事を参考にしたことで何かあっても責任は取りません。
ご了承ください。
動画の再生回数や高評価数の統計を取りたい方はこちら↓
(終了したライブ配信の再生回数などを取りたい場合もこちら)
※この記事は上記の記事の続編です。
そのため一部内容が似通っていますがご了承ください。
準備
コードを書き始めるに、まずは環境の準備が必要です。
新しくプロジェクトを作る
まずはデータを出力するためのスプレッドシートを新しく作ります。
このスプシにライブ配信の統計データが入ります。
また、このスプレッドシートの「拡張機能」タブからApps Scriptを選択して、
GASのエディタ画面を開いておいてください。
YouTube Data APIを入れる
GASの画面で、左側にある「サービス」の隣の+をクリックします。
そしてそこから 「YouTube Data API v3」を選択 します。
バージョンはv3、IDはYouTubeのままで大丈夫です。
サービスのところにYouTubeが追加されていたら成功です。
このYouTube
はGASのコードから使えるAPIで、配信データはこれを通して取得します。
コードを書く
解説を読む時間がない方は完成形もありますので、ぜひご活用ください。
準備が整ったので、早速データ取得を行うコードを書きます。
コードではこんな感じのことをやります。
- ライブ配信が配信中か終了済みかを示すステータスを更新する
- ステータスが
live_active
になっている配信の動画IDを取得する - 2の配信のデータを取得する
- 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
は、第一引数に取得したいデータのタイプを取ります。
ここではstatistics
とliveStreamingDetails
を指定しています。
-
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]]);
}
}
}
この関数は冒頭で言った手順を実行しています。
-
updateStatus
でステータスを更新する - ステータスが
live_active
になっている配信の動画IDを取得する - 2の配信のデータを
fetchLiveData
で取得する - 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'},
]);
}
onOpen
はonEdit
のように特殊な関数で、スプレッドシートを開いたタイミングで自動的に実行されます。
その中でメニューを追加する関数である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番目)を押します。
次に、右下に「トリガーを追加」と書かれたボタンがあるので押します。
するとポップアップが出てくるので、適切に設定を行います。
- 実行する関数を選択:
live
- 実行するデプロイを選択:
Head
(初期設定のまま) - イベントのソースを選択: 時間主導型
- 時間ベースのトリガーのタイプを選択: 分ベースのタイマー
- 時間の間隔を選択: 10分おき
- エラー通知設定: お好みでどうぞ(最初は「今すぐ通知を受け取る」がおすすめ)
このうち「時間ベースのトリガーのタイプを選択」と「時間の間隔を選択」を変更することで、集計の間隔(=live
が実行される間隔)を変更できます。
上記の設定だと10分おきですが、ほかにも1分おきや30分おきなどの設定国目があるので、お好みで調整してみてください。
これが設定できたら完成です。
運用方法の一つとして、統計を取りたいライブ配信があるたびにトリガーを追加し、終わったら削除するという方法があります。
毎回追加しなければならないのは面倒ですが、普段使わないトリガーをずっと残しておくのはデメリットもあるかもしれません。
場合によってはGoogleからのエラー通知メール(しかも内容はよくわからない)が毎日来て邪魔になることもあります。
そうなったらぜひお試しください。