youtubeAPIを使ってyoutubeのライブ配信のチャットを取得(Visual Studio C++)④
ソースコード
概要
①②③でメモしたことを組み合わせ、
VisualStdio C++からライブ配信のコメントを取得します。
前提条件
下記実施済みである事
①のcurl導入
②のyoutubeのAPIキーを取得
③のpicojson導入
ソースコード
using namespace std; #include <curl/curl.h> #include <picojson.h> #include <codecvt> size_t callbackWrite(char *ptr, size_t size, size_t nmemb, string *stream) { int dataLength = size * nmemb; stream->append(ptr, dataLength); return dataLength; } string GetactiveLiveChatId(string LiveID){ CURL *curl; CURLcode ret; string url = "https://www.googleapis.com/youtube/v3/videos?part=liveStreamingDetails"; string key = "AAAAAAAAAAAAAAAAAAAAAAAAAA";//APIキー string chunk; printf("youtube初期設定\n"); curl = curl_easy_init(); if (curl == NULL) { cerr << "curl_easy_init() failed" << endl; getchar(); } url = url + "&id=" + LiveID + "&key=" + key; cout << "activeLiveChatId取得用URL= " << std::endl; cout << url << endl; // レスポンスのコールバック curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callbackWrite); // 書き込みバッファを指定 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk);//取得行が多すぎるとエラーになる ret = curl_easy_perform(curl); curl_easy_cleanup(curl); if (ret != CURLE_OK) { cerr << "curl_easy_perform() failed." << endl; getchar(); } picojson::value v; string err; err = picojson::parse(v, chunk); if (err.empty() == false) { std::cerr << err << std::endl; getchar(); } std::cout << "取得jsonすべてを出力" << std::endl; std::cout << v << std::endl; std::cout << std::endl; //jsonを参照 picojson::object& obj = v.get<picojson::object>(); //std::cout << "item配列をarrayで参照 " << std::endl; picojson::array& obj2 = obj["items"].get<picojson::array>(); //ここでエラーが出るときは配信が公開・限定公開になっているか確認 string ACLiveID = obj2[0].get< picojson::object >().at("liveStreamingDetails") .get< picojson::object >().at("activeLiveChatId") .get< std::string>(); std::cout << "activeLiveChatId" << ACLiveID << std::endl; printf("youtube初期設定終了\n"); return ACLiveID; } //youtubeチャット取得 //引数にkey void Getlivechat(string ACLiveID,int* totalResults, string* nextPageToken) { CURL *curl; CURLcode ret; string url = "https://www.googleapis.com/youtube/v3/liveChat/messages?"; string key = "AAAAAAAAAAAAAAAAAAAAAAAAAA";//APIキー string chunk = ""; int pollingIntervalMillis = 0; picojson::value v2; string err2; printf("youtubeチャット取得\n"); url = url + "key=" + key + "&part=snippet,authorDetails" + "&liveChatId=" + ACLiveID + "&pageToken=" + *nextPageToken; std::cout << "チャット確認用URL" << std::endl; cout << url << endl; curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callbackWrite); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk); ret = curl_easy_perform(curl);//取得行が多すぎるとエラーになる curl_easy_cleanup(curl); if (ret != CURLE_OK) { cerr << "curl_easy_perform() failed." << endl; getchar(); } err2 = picojson::parse(v2, chunk); if (err2.empty() == false) { std::cerr << err2 << std::endl; getchar(); } //jsonを参照 picojson::object& obj = v2.get<picojson::object>(); std::cout << "チャット用jsonすべてを出力" << v2 << std::endl;; //nextPageToken/polling時間を取得 *nextPageToken = obj["nextPageToken"].get<std::string>(); pollingIntervalMillis = (int)obj["pollingIntervalMillis"].get < double >(); std::cout << "polling時間 " << obj["pollingIntervalMillis"].get<double>() << std::endl;; //メッセージ数を取得 *totalResults = (int)obj["pageInfo"].get< picojson::object >().at("totalResults").get < double >(); std::cout << "メッセージ数 " << *totalResults << std::endl;; string displayMessage; //std::cout << "item配列をarrayで参照 " << std::endl; picojson::array& obj12 = obj["items"].get<picojson::array>(); //item配列0番を参照 for (int i = 0;i < *totalResults;i++) { //youtubeのjsonはitemsが配列だが //item配列0番を直接参照する方法がわからなかったので、obj2からactiveLiveChatIdを直接参照 displayMessage = obj12[i].get< picojson::object >().at("snippet") .get< picojson::object >().at("displayMessage") .get< std::string>(); //日本語はUTF-8で入手してしまう //出力時はSJISでないといけない //string(UTF-8):displayMessageとwstringの文字コード変換:wdisplayMessage std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; std::wstring wdisplayMessage = converter.from_bytes(displayMessage); //wstring(wdisplayMessage)からstring(Shift_JIS):SdisplayMessageとの文字コード変換 std::size_t converted{}; std::vector<char> dest(wdisplayMessage.size() * sizeof(wchar_t) + 1, '\0'); if (::_wcstombs_s_l(&converted, dest.data(), dest.size(), wdisplayMessage.data(), _TRUNCATE, ::_create_locale(LC_ALL, "jpn")) != 0) { //throw std::system_error{ errno, std::system_category() }; std::cout << "絵文字またはエラー" << endl;; } dest.resize(std::char_traits<char>::length(dest.data())); dest.shrink_to_fit(); std::string SdisplayMessage = std::string(dest.begin(), dest.end()); std::cout << "メッセージ " << SdisplayMessage << endl;; } Sleep(pollingIntervalMillis); //return totalResults; }
関数使い方
int totalResults = 0;//新規チャット数 string nextPageToken = "";//最新チャットのみ取得のためのトークン string ACLiveID = "";; //ライブ配信毎に設定 //idはhttps://www.youtube.com/watch?v=xxxxxxxxxxxのxxxxxxxxxxxの部分を入れます //自分の配信の場合、右上の共有可能なリンクを取得 から可能 string LiveID = "xxxxxxxxxxxx"; ACLiveID = GetactiveLiveChatId(LiveID); //youtubeチャット取得 実行の度に最新チャットを取得し新規チャット数を取得 Getlivechat(ACLiveID, &totalResults, &nextPageToken);