1
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?

CastCraftのWebhookの正体を探ってみた【Next.jsでAPI構築&MongoDB】

Posted at

CastCraftってなに

CastCraftは、YouTube/Twitchなどでの配信をサポートするアプリケーションです。例えばコメントの管理、コメントの読み上げ、オーバーレイ、映像エフェクトなど配信を魅力的にできる機能が盛りだくさんです。

私もYoutubeでゲーム配信をしており、お世話になることが多いアプリケーションです。めちゃくちゃ助かってます。

CastCraftのWebhook機能

この間設定をちらほら見ていると、超マイナーな欄に**Webhook(Experimental)**と書かれた欄がありました。Webhookとは、あるWebアプリケーションで特定のイベントが発生した際に、他のWebアプリケーションへ自動的に通知を送る仕組みですが、「指定されたWebhook URLに対してチャットデータをJSON形式でPOSTします」とだけ書かれており、どのhookで送信されるものなのか明確に書いていません。詳細な情報が載ってるドキュメントを探しましたが、どこにも見つからず...

{ADE067C4-09B9-4572-AB3F-6846889ED91F}.png

というわけで、hookを受け取るAPIを作成し、NoSQLに格納してデータの中身を見てみることにしました。

API構築における概要

今回はhookを受け取るだけの簡単なものなのでスピード重視でやります。
とりあえずAPIを作ってみたい初心者の方におすすめです。

技術スタック

  • Next.js (v14。 AppRouter)
  • TypeScript
  • MongoDB Atlas

API開発

MongoDBまわり

Mongodbをインストールし、

terminal
$ npm i mongodb

clientインスタンスを作ります

client.ts
import { MongoClient, ServerApiVersion } from "mongodb";

export default class MongoDBClient extends MongoClient {
    private db_name: string;

    constructor(db_name: string, uri: string) {
        super(uri,
            {   
                serverApi: ServerApiVersion.v1,
            }
        );
        this.db_name = db_name;
    }

    collection(collection_name: string) {
        return this.db(this.db_name).collection(collection_name);
    }
}

MongoDB Atlas側でデータベースNameとURIを控えておきましょう

.env
MONGODB_NAME = "*****"
MONGODB_URI = "mongodb+srv://*****:[db_password]@..."

API本体

/app/apiに、route.tsを置き、POSTルートを作ります。
さっき作ったclientもインポートしてつかいます

route.ts
import MongoDBClient from "clients/mongodb";

const mongodb = new MongoDBClient(
    process.env.MONGODB_DB_NAME || '',
    process.env.MONGODB_URI || ''
);

export async function POST(req: Request) {
    try {
        const request = await req.json();
        const collection = mongodb.collection('collection-name');
        const result = await collection.insertOne(request);
        
        const response = {
            message: 'Webhook received successfully',
            request: request,
            response: result
        };
        return Response.json(response);
    } catch (error) {
        return Response.json({ error: String(error) }, { status: 500 });
    }
}

とりあえずこれで、任意のJSON形式のリクエストに対して、JSONを指定のMongoDB ClusterにinsertするAPIがかけました!

検証結果

これをVercelでデプロイし、さっきのWebhook送信先リンクにURLを貼り付けて配信してみました

レスポンスからおおまかに以下のようなリクエストデータが得られました。
どうやらチャットを取得することにhookが送信されるようです。

type response = {
    videoId: string,
    chatMessages: {
        chatMessageId: string,
        platform: string,
        youtubeExtension: Object[], // 深すぎるので省略
        displayMessage: string,
        displayName: string,
        photoUrl: string,
        platformAudienceId: string
        createdAt: {
            seconds: number,
            nanoseconds: number
        }
    }[]
}

それぞれ意味をまとめるとこうです

type response = {
    videoId: "配信のvideoId",
    chatMessages: {
        chatMessageId: "チャットメッセージのId",
        platform: "youtubeExtension", // ?
        youtubeExtension: Object[], // 深すぎるので省略
        displayMessage: "チャットメッセージのテキスト",
        displayName: "チャットした人のアカウント名テキスト",
        photoUrl: "チャットした人のアイコンソース",
        platformAudienceId: "?"
        createdAt: {
            seconds: number,
            nanoseconds: number
        } // チャットされた時間
    }[] // ロードされたときに取得したコメント一覧
}

まとめ

今回はCastcraftのマイナーな機能の実態について探ってみました。
実際のところ、Youtubeのライブチャット取得にはYoutube Data API v3でも可能ですが、リアルタイム取得では短期間に数回のリクエストを送らなければ取得できません。
これにはネックな点があり、1日の取得回数に上限があります。上限解放もできますが長期間にわたってYoutubeと申請を送り合う必要があり、かなり面倒です。


今回発見したこのwebhook機能は、その問題を解決するに至りました。


これだけのデータがとれていれば、自分の配信に限られてしまいますが、チャットリアルタイム取得をノーコストで実現できる可能性があります。


次の記事では、Youtube Data APIなしでライブチャットをリアルタイム取得してみようと考えてます。

1
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
1
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?